Logback 실무 가이드: MDC·TraceId·PatternLayout으로 구조적 로그 완성하기
백엔드 개발에서 로그는 단순 출력이 아니라 **운영 품질을 결정하는 핵심 지표**입니다. 특히 마이크로서비스·API 서버·분산 시스템에서는 “한 요청이 어떤 흐름으로 처리되는지”를 추적할 수 있어야 장애 분석 속도가 크게 줄어듭니다.
이를 위해 실무에서는 Logback을 기본 로거로 사용하며, 로그를 구조화하기 위해 반드시 **MDC(Context 기반 로그)**, **TraceId**, **PatternLayout 커스터마이징**을 적용합니다.
이번 글은 Spring Boot 기반 실무 환경에서 Logback을 어떻게 설정하고, 어떤 패턴으로 운영하며, 어떤 기준으로 로그를 분리·구조화하는지 전체 흐름을 알기 쉽게 정리한 실전 가이드입니다.

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를 포함하게 됩니다.

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 구조를 선호.

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 연동, 구조적 로그의 모니터링 전략까지 확장하여 다루겠습니다.
'서버 인프라 실무' 카테고리의 다른 글
| 장애를 재현하는 법: 의도적으로 장애를 만들어 원인 추적하기 (실무 트러블슈팅 가이드) (0) | 2025.12.17 |
|---|---|
| Nginx 무중단 배포 완전 가이드: Blue-Green·Canary·graceful reload로 서비스 끊김 없이 배포하기 (0) | 2025.12.15 |
| 트래픽 급증 대응 전략: 캐시·CDN·로드밸런서 실무 가이드 (0) | 2025.11.22 |
| 운영 자동화 — 배포와 로그를 하나로 묶는 DevOps 환경 만들기 실무 가이드 (0) | 2025.11.20 |
| 무중단 HTTPS 유지: Let’s Encrypt 자동갱신 안정화(이중 인증서, 모니터링, 무중단 교체) (0) | 2025.11.02 |