Spring/Springboot

[Spring boot] MDC(Mapped Diagnostic Context) 클라이언트 요청IP 넣기

늘이 2024. 3. 15. 13:19

 

기존 구현한 코드

import jakarta.servlet.*;
import org.slf4j.MDC;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.UUID;

/*
    @Component: 스프링 컨텍스트에서 클래스를 빈으로 등록, Filter를 구현한 이 클래스를 스프링 빈으로 관리
    @Order: 빈의 우선순위 설정
    Ordered.HIGHEST_PRECEDENCE: 가장 높은 우선 순위
 */
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MDCRequestLoggingFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 필요에 따라 초기화 코드 작성
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        try {
            // 랜덤한 uuid 값을 생성하여 MDC 저장소에 request_id를 키, uuid를 value로 저장
            UUID uuid = UUID.randomUUID();
            MDC.put("request_id", uuid.toString());

            // 다음 필터로 제어 전달, 실제 요청이 로직이 실행되는 지점
            chain.doFilter(request, response);
        } finally {
            // 실제 요청이 완료되면 MDC 저장소를 초기화
            MDC.clear();
        }
    }

    @Override
    public void destroy() {
        // 필요에 따라 소멸 코드 작성
    }
}

 

UUID.randomUUID()로 랜덤값으로 request_id를 넣었는데 

 

uuid가 중복이 없는 값을 쓸 수 있다는 장점이 있지만, 가독성도 떨어지고 요청자 구분을 확실히 하고싶어서

요청자의 IP주소를 넣는 방법이 어떨까해서 수정

 

package com.douzone.projecttemplate.common.log;

import jakarta.servlet.*;
import org.slf4j.MDC;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.UUID;

/*
    @Component: 스프링 컨텍스트에서 클래스를 빈으로 등록, Filter를 구현한 이 클래스를 스프링 빈으로 관리
    @Order: 빈의 우선순위 설정
    Ordered.HIGHEST_PRECEDENCE: 가장 높은 우선 순위
 */
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MDCRequestLoggingFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 필요에 따라 초기화 코드 작성
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        try {
            // 클라이언트의 IP 주소를 추출하여 request_id로 설정
            String clientIP = request.getRemoteAddr();
            MDC.put("request_id", clientIP);

            // 다음 필터로 제어 전달, 실제 요청이 로직이 실행되는 지점
            chain.doFilter(request, response);
        } finally {
            // 실제 요청이 완료되면 MDC 저장소를 초기화
            MDC.clear();
        }
    }

    @Override
    public void destroy() {
        // 필요에 따라 소멸 코드 작성
    }
}

 

 

실제로 이렇게 IP를 확인하는 경우가 있나 싶어서 검색해봤는데 자주 사용되는 방법 중 하나라고 한다.

 

클라이언트 IP주소를 request_id로 사용할 때 이점

1) 요청을 보낸 클라이언트를 식별하는데 사용할 수 있고, 간단하고 고유한 식별자로 사용될 수 있음

2) 트래픽을 모니터링하거나 디버깅할 때 유용함, 특정 클라이언트의 요청을 식별하고 추적할 수 있음

3) 보안 검사에 유용함, 클라이언트 IP를 식별하여 보안 절차를 수행할 수 있음

 

 

 

MDC 적용

https://k-sky.tistory.com/749

 

[Spring boot] MDC(Mapped Diagnostic Context) 적용

1. MDC 사용 이유 1) 스레드 별 로깅 컨텍스트 다중 스레드 환경에서 각 스레드는 독립적으로 실행되며 서로 다른 작업을 수행함 MDC를 사용하면 각 스레드에게 고유한 로깅 컨텍스트를 제공하여

k-sky.tistory.com