Search
🙉

MDC 와 Intercepter 설정

Intro::

로깅시 클라이언트 정보는 횡단 관심사이기 때문에 이를 효과적으로 처리할 수 있는 방법에 대해 알아봅시다.

1. MDC(Mapped Diagnostic Context)

1.
개념
MDC는 스레드별로 키–값 쌍을 저장해 두는 로깅 컨텍스트입니다.
하나의 HTTP 요청 처리 과정에서 발생하는 모든 로그에 동일한 식별 정보를 포함시킬 수 있습니다.
2.
사용 목적
요청별 고유 ID(requestId), 사용자 ID(userId), 클라이언트 IP(clientIp) 등을 한 번만 설정해 두면, 이후 logger.info(…) 호출 시 자동으로 로그 패턴에 포함됩니다.
여러 스레드나 비동기 작업에서도 스레드 로컬로 관리되므로, 서로 다른 요청의 로그가 뒤섞이지 않습니다.
3.
주요 메서드
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.slf4j.MDC; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; @Component public class MdcInterceptor implements HandlerInterceptor { @Override public boolean preHandle( HttpServletRequest request, HttpServletResponse response, Object handler) { // 프록시(X-Forwarded-For) 헤더 우선, 없으면 remoteAddr 사용 String clientIp = request.getHeader("X-Forwarded-For"); if (clientIp == null || clientIp.isEmpty()) { clientIp = request.getRemoteAddr(); } // MDC에 저장 MDC.put("clientIp", clientIp); return true; } @Override public void afterCompletion( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { // 요청 처리 완료 후 MDC 정리 MDC.remove("clientIp"); } }
Java
복사
4.
설정
# application.yml logging: pattern: console: "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} [%X{clientIp}] - %msg%n"]
YAML
복사
# 실행할 때 java -Djava.net.preferIPv4Stack=true -jar build/libs/your-app.jar
Docker
복사
5.
장점
로깅 호출문(예: logger.info(…))을 일일이 수정하지 않고도 부가 정보를 포함
AOP나 인터셉터 등 어디서든 MDC에 값을 세팅하면, 전체 로깅 흐름에 일괄 적용

2. HandlerInterceptor

1.
개념
Spring MVC에서 요청 전·후에 공통 처리를 삽입하기 위한 컴포넌트입니다.
preHandle, postHandle, afterCompletion 3가지 메서드를 오버라이드해 사용합니다.
2.
주요 메서드
import com.cowave.cdcproxy.interceptor.MdcInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { private final MdcInterceptor mdcInterceptor; @Autowired public WebConfig(MdcInterceptor mdcInterceptor) { this.mdcInterceptor = mdcInterceptor; } @Override public void addInterceptors(InterceptorRegistry registry) { // 모든 요청 경로에 MdcInterceptor 적용 registry.addInterceptor(mdcInterceptor) .addPathPatterns("/**"); } }
Kotlin
복사
3.
활용 사례
로깅 컨텍스트 관리: 요청별 requestId, clientIp 등을 MDC에 자동 세팅
인증·권한 검사: 모든 요청에 대해 토큰 유효성 검사를 공통으로 처리
성능 측정: preHandle에서 시작 시간, afterCompletion에서 처리 시간 계산

3. MDC + Interceptor 조합

1.
Interceptor에서 MDC에 값을 세팅 →
2.
로깅 패턴%X{…}로 포함 →
3.
서비스/컨트롤러에서는 별도 파라미터 없이 logger.info(…) 사용
이로써 비즈니스 로직 코드는 로깅 코드로 복잡해지지 않으면서도, 모든 로그에 일관된 부가 정보를 자동으로 붙일 수 있습니다.

References::