본문 바로가기

JAVA

(18)
Spring MVC와 WebFlux의 요청 처리 흐름 1. Spring MVC (동기 / 블로킹 방식)Thread-per-request 모델클라이언트 요청 → 서블릿 컨테이너(Tomcat 등) → 스레드 할당 → 컨트롤러 실행 → DB/외부 API 요청 시 스레드가 대기 상태 → 응답 반환흐름클라이언트가 요청 보냄 (HTTP Request)Tomcat이 요청마다 새로운 스레드(Thread)를 할당컨트롤러 실행DB/외부 API 호출 → 응답 올 때까지 스레드가 블로킹응답을 클라이언트에게 반환스레드 반환(Thread Pool로 되돌림)👉 요청이 많아지면 스레드가 부족해져서 응답 지연 발생.2. Spring WebFlux (비동기 / 논블로킹 방식)Event Loop 기반 모델요청을 받으면 작업을 등록만 하고 바로 스레드를 반환 → 결과가 준비되면 이벤트 루프..
WebFlux 정리 📌 Spring WebFlux 정리1. 정의Spring 5부터 추가된 리액티브 웹 프레임워크논블로킹 I/O 기반 → 적은 스레드로도 높은 동시성 처리 가능Reactor 라이브러리 (Mono, Flux) 사용 → 리액티브 스트림 표준 준수2. 핵심 개념Mono : 0~1개의 결과 (단일 값 비동기 처리)Flux : 0~N개의 결과 (스트림 비동기 처리)Non-blocking : 결과 기다리지 않고 다음 작업 진행Backpressure : 데이터가 몰릴 때 소비자가 감당 가능한 만큼만 처리3. 코드 비교Spring MVC (동기/블로킹)@GetMapping("/user/{id}")public User getUser(@PathVariable String id) { return userRepository..
Logback/SLF4j 사용 이유 한 줄 요약코드는 SLF4J(리모컨)만 보고 말하고, 실제로 로그를 찍는 일은 Logback(TV)이 함. 그래서 TV를 바꿔도(Logback→다른 것) 코드는 거의 안 바꿔도 됨SLF4J는 로깅 Facade라서 코드가 구현체에 묶이지 않음. 서드파티가 JUL/Log4j/JCL을 써도 브리지로 한 채널로 모음. 또한 {} 파라미터 로깅과 MDC 덕에 성능과 추적성이 좋음. 구현체는 Spring Boot 기본인 Logback을 쓰면 Appender/MDC/Async/JSON 로깅까지 운영 기능이 기본 제공되어, 배포·관리가 쉬움왜 이 조합이 좋을까? (현업 포인트 5개)갈아끼우기 쉬움 : 내일 Logback 대신 Log4j2로 바꿔도, 코드는 SLF4J 그대로 (SLF4J는 ‘로깅 API’ 앞단 추상화 계..
다국어 Papago API 연결 공식 사이트 설명도 좋음. 쉽게 따라하기1) 콘솔에서 키 발급네이버 클라우드에서 Papago Translation 사용 설정 → 애플리케이션 등록 → Client ID/Secret 발급2) 설정 (환경변수/설정파일)application.ymlpapago: base-url: ${PAPAGO_URL} client-id: ${PAPAGO_CLIENT_ID} client-secret: ${PAPAGO_CLIENT_SECRET}운영에선 실제 값은 환경변수로 주입3) WebClient Bean@Configuration@RequiredArgsConstructor@FieldDefaults(level = AccessLevel.PRIVATE)public class Config { @Bean WebClient pa..
Sentry + OpenSearch 로그 수집 왜 이렇게 하나요?Sentry : 예외·에러 알림과 이슈 그룹핑 자동화. (Spring Boot 스타터 + Logback 연동) OpenSearch : JSON 로그를 모아 검색/대시보드. (에이전트로 수집 or Logback에서 바로 전송)1) 의존성 추가 (Gradle 예시)dependencies { // Sentry (Spring Boot + Logback) implementation "io.sentry:sentry-spring-boot-starter-jakarta:8.19.1" implementation "io.sentry:sentry-logback:8.19.1" // JSON 로그 인코더 (Logback) implementation "net.logstash.logback:logstash..
Retry 시스템 만들기 왜 필요한가?네트워크 순간 끊김, 외부 API 일시 장애, DB 잠깐 과부하… 이런 일시적(Transient) 오류는 “조금 있다 다시” 하면 종종 해결...이걸 자동으로 해주는 게 Retry. 단, 영구적(Permanent) 오류는 다시 해도 안됨 (예: 잘못된 파라미터)재시도 대상만 고르는 게 핵심1) 기본 원칙대상 선별 : 재시도할 예외만 고르기 (네트워크 타임아웃, 429/503 등). 재시도해도 소용없는 예외는 제외Backoff + Jitter : 점점 기다리는 시간 늘리기(Exponential Backoff) + 최대 대기 시간(cap)서버 힌트 존중 : HTTP 429에 Retry-After 있으면 그만큼 쉬었다 재시도Idempotency : 같은 요청을 여러 번 보내도 한 번만 처리되게 키..
실무형 Global Exception Handler 만들기 (ErrorCode Enum + 국제화 + 로그 시스템까지) * 에러 응답 표준(Contract)부터 결정클라이언트와 약속이 제일 중요 { "timestamp": "2025-08-19T12:34:56.789Z", "path": "/api/v1/orders", "status": 400, "code": "ORD_001", /** 비즈니스 오류 식별자(사내 표준) **/ "message": "잘못된 주문 요청입니다.", /** 사용자 노출용(i18n 적용) **/ "errors": [ /** 바인딩/검증 상세 **/ {"field": "quantity", "reason": "must be greater than or equal to 1"} ], "traceId": "a1b2c3d4e5f6" /** 로그 추적(MDC)과 연결 **/}1) ErrorCo..
Global Exception Handler 만들기 1. 왜 필요한가?서비스 규모가 커질수록 예외(Exception)가 발생하는 지점이 많아짐매번 try-catch를 넣으면 코드가 지저분해지고 유지보수가 힘들어짐Global Exception Handler를 쓰면, 모든 예외를 한 곳에서 모아서 처리 가능 → 일관성 있는 에러 응답 제공2. 구현 방법(1) @RestControllerAdvice + @ExceptionHandler 사용 @RestControllerAdvicepublic class GlobalExceptionHandler { // 사용자 정의 예외 처리 @ExceptionHandler(CustomException.class) public ResponseEntity handleCustomException(CustomExcepti..