본문 바로가기
서버 인프라 실무

Logback 실무 가이드: MDC·TraceId·PatternLayout으로 구조적 로그 완성하기

by yamoojin83 2025. 12. 1.

Logback 실무 가이드: MDC·TraceId·PatternLayout으로 구조적 로그 완성하기


백엔드 개발에서 로그는 단순 출력이 아니라 **운영 품질을 결정하는 핵심 지표**입니다. 특히 마이크로서비스·API 서버·분산 시스템에서는 “한 요청이 어떤 흐름으로 처리되는지”를 추적할 수 있어야 장애 분석 속도가 크게 줄어듭니다.

이를 위해 실무에서는 Logback을 기본 로거로 사용하며, 로그를 구조화하기 위해 반드시 **MDC(Context 기반 로그)**, **TraceId**, **PatternLayout 커스터마이징**을 적용합니다.

이번 글은 Spring Boot 기반 실무 환경에서 Logback을 어떻게 설정하고, 어떤 패턴으로 운영하며, 어떤 기준으로 로그를 분리·구조화하는지 전체 흐름을 알기 쉽게 정리한 실전 가이드입니다.

MDC + TraceId 개념도

 

1. 왜 구조적 로그(Structured Logging)가 필요한가?


과거에는 단순히 “로그가 출력되면 된다”고 생각했지만, 오늘날의 운영 환경은 다음과 같이 복잡합니다.

■ API 요청이 여러 서버를 거쳐 처리됨 ■ 스레드가 비동기로 생성됨 ■ 외부 API·DB·캐시 등 다양한 컴포넌트와 상호작용 ■ 장애 원인이 여러 서비스 레이어에 나뉘어 있음

이런 환경에서는 로그가 다음 조건을 만족해야 합니다.

- 요청 단위로 묶여야 함 - 어떤 사용자의 요청인지 추적 가능해야 함 - 어떤 API, 어떤 스레드에서 발생했는지 알아야 함 - 호출 흐름이 ‘눈에 보이게’ 표현돼야 함 - APM/Grafana/ELK 수집에 최적화되어야 함

이 모든 요구사항을 해결해주는 기술이 **MDC**와 **TraceId 기반 로그 구조화**입니다.

2. MDC(Mapped Diagnostic Context)란?


MDC는 로그 출력 시 “추가 컨텍스트 정보”를 함께 포함할 수 있게 해주는 Logback 기능입니다.

예를 들어 다음과 같은 정보를 로그에 함께 넣을 수 있습니다.

- traceId - userId - sessionId - request path - client IP - correlationId

MDC로 값을 넣는 방법은 매우 간단합니다.


MDC.put("traceId", UUID.randomUUID().toString());

그리고 PatternLayout에서 `%X{traceId}`로 꺼내 로그에 포함할 수 있습니다.

MDC는 “스레드 단위로 격리”되므로, 요청 단위의 TraceId를 저장하면 같은 요청 흐름에서 찍힌 모든 로그가 자동으로 묶이게 됩니다.

3. TraceId 넣기: 필터에서 자동 적용


Spring Boot에서는 Filter 단계에서 TraceId를 생성해 MDC에 넣고, 응답 시 제거하는 패턴이 가장 안전하고 흔히 쓰입니다.


@Component
public class TraceIdFilter implements Filter {

    @Override
    public void doFilter(
            ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        String traceId = UUID.randomUUID().toString().replace("-", "");
        MDC.put("traceId", traceId);

        try {
            chain.doFilter(request, response);
        } finally {
            MDC.clear(); // 메모리 누수 방지
        }
    }
}


이제 애플리케이션의 모든 로그는 traceId를 포함하게 됩니다.

Logback 구조(패턴 + Appender + Logger) 다이어그램

4. logback-spring.xml 기본 틀(실무 표준)


Spring Boot 프로젝트의 기본 Logback 설정 파일 위치는 `src/main/resources/logback-spring.xml`입니다. 아래는 가장 많이 사용되는 실무형 기본 구조입니다.


<configuration scan="true" scanPeriod="30 seconds">

    <property name="LOG_PATH" value="./logs"/>

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>
                [%d{yyyy-MM-dd HH:mm:ss.SSS}] [%highlight(%-5level)] [%X{traceId}] [%thread] %logger{36} - %msg%n
            </pattern>
        </encoder>
    </appender>

    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/app.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/archive/app.%d{yyyy-MM-dd}.gz</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>
                [%d{yyyy-MM-dd HH:mm:ss.SSS}] %-5level [%X{traceId}] [%thread] %logger{36} - %msg%n
            </pattern>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
    </root>

</configuration>


이 설정은 다음 특징을 가집니다.

■ traceId 포함 ■ console + file 동시 출력 ■ 일별 롤링 + gzip 압축 ■ 스레드명, 클래스명 포함

이 구조에서 traceId가 자동으로 로그에 포함되기 때문에, **APM·Logstash·Grafana Loki** 같은 로그 수집 시스템과 매우 쉽게 연결됩니다.

5. 요청별 로그 묶기: 사용자 ID · API 경로 · IP 추가 (MDC 확장)


실무에서는 traceId만으로는 장애를 완전히 분석하기 어렵습니다. 따라서 다음 정보를 추가로 넣는 경우가 많습니다.

- userId - method (GET/POST...) - uri - clientIp

예시:


MDC.put("userId", userId);
MDC.put("uri", httpServletRequest.getRequestURI());
MDC.put("method", httpServletRequest.getMethod());
MDC.put("ip", httpServletRequest.getRemoteAddr());


그리고 로그 출력 패턴에 다음을 추가합니다.

[%X{userId}] [%X{uri}] [%X{method}] [%X{ip}]

6. 운영 환경에서 필수로 적용해야 하는 로그 전략 5가지


아래 다섯 가지 전략은 실무 엔지니어에게 반드시 필요한 내용이며, 특히 장애 대응 속도를 극대화합니다.

1) logback-spring.xml ← 반드시 이 파일명 사용
Spring Boot는 logback.xml보다 logback-spring.xml을 우선 적용함.

2) 로그 레벨을 환경별로 나누기
- dev: DEBUG - stage: INFO - prod: WARN 이상

3) stdout/stderr를 container runtime과 연동(도커·쿠버네티스 환경)
쿠버네티스 사용 시 FILE appender 대신 STDOUT appender 사용을 권장.

4) MDC는 반드시 clear() 처리
스레드풀 사용 시 MDC 누수로 엉뚱한 traceId가 섞이는 치명적 문제 발생.

5) JSON 로그로 변환하면 APM과 궁합 최고
Elastic Stack, Loki, Datadog 등은 JSON 구조를 선호.

JSON 로그 시각화

7. JSON 로그 출력(고급 실무)


운영 환경에서 JSON 로그는 분석과 검색 속도에서 절대적 우위를 가지므로 대부분의 실무 엔지니어는 JSON 기반 로그로 전환합니다.


<appender name="JSON" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="net.logstash.logback.encoder.LogstashEncoder">
        <customFields>{"service":"my-api-server"}</customFields>
    </encoder>
</appender>


JSON 로그를 사용하면 traceId와 MDC 값이 자동으로 JSON 필드로 들어가므로 Grafana, Loki, Kibana에서 검색과 필터링이 매우 쉬워집니다.

8. 결론: 로그는 단순 출력이 아니라 ‘운영의 시작점’이다


정리하면 Logback을 제대로 사용하는 핵심은 다음 세 가지입니다.

■ MDC로 traceId·userId·IP 등 컨텍스트 정보를 넣기 ■ PatternLayout을 실무형으로 커스터마이징 ■ 운영 환경에서는 JSON 기반 로그로 전환

이 세 가지만 적용하면 로그 분석 속도는 3배 빨라지고, APM과 연동 시 장애 원인 추적이 훨씬 명확해집니다.

다음 글에서는 로그 기반의 관찰성(Observability)과 APM 연동, 구조적 로그의 모니터링 전략까지 확장하여 다루겠습니다.