본문 바로가기
모니터링 환경 구축하기

오픈소스로 모니터링 환경 구축하기(1) - Logback 로깅 전략 정비 및 MDC 표준화

by fiat_lux 2025. 10. 11.

배경

 

기존엔 콘솔과 파일 위주의 단순한 로깅만으로 운영했다.

하지만 모니터링 스택(Loki, Tempo, Prometheus) 을 도입하면서, 단순 로그 수집만으로는 부족하다는 문제가 발생했다.

 

특히 로그와 트레이스 간의 상관관계를 보장해야 장애 분석과 성능 모니터링이 수월해진다.

이를 위해 로깅 프레임워크와 MDC 전략을 정비했다.

 

기존의 Logback ADR


기존 로깅 설정의 한계

기존의 loback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

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

    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>

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

    <appender name="LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOGS_ABSOLUTE_PATH}/resource.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <charset>utf8</charset>
            <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %thread [%X{traceId}] %-5level %logger - %msg%n</Pattern>
        </encoder>


        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOGS_ABSOLUTE_PATH}/%d{yyyy-MM-dd}/resource.%i.gz</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <maxHistory>180</maxHistory>
        </rollingPolicy>
    </appender>

    <root level="INFO">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="LOG"/>
    </root>


</configuration>

 

 

  • %X{traceId}를 활용한 MDC 기반 요청 추적
  • 콘솔 + Rolling FileAppender 조합
  • 단순 회전 정책 (TimeBasedRollingPolicy + size)

이 방식은 개발 환경에서 로깅 가독성은 확보할 수 있지만, 운영 환경에서는 아래와 같은 한계가 있었다.

  1. MDC 키 표준화 미비로 인해 트레이스-로그 연계 불안정
  2. 회전 정 책이 단순하여서 디스크가 늘어날 가능성 존재
  3. 환경별(개발/운영) 요구사항에 따른 로깅 전략 분리가 미흡

 

 

개선 목표

  1. OTel 에이전트가 자동 주입하는 표준 MDC 키(trace_id, span_id) 활용
  2. 로그 보존 정책 및 회전 정책 강화로 운영 안정성 확보
  3. Spring profile(local/prod)에 따라 로깅 전략을 분리해 가독성과 안정성을 모두 챙김

 

개선된 Logback 설정

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <conversionRule conversionWord="clr"
                    converterClass="org.springframework.boot.logging.logback.ColorConverter"/>

    <springProfile name="local">
        <property name="LOG_DIR" value="./logs"/>

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

        <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>${LOG_DIR}/app.log</file>
            <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                <charset>UTF-8</charset>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger
                    traceId=%X{trace_id:-} spanId=%X{span_id:-} - %msg%n</pattern>
            </encoder>
            <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
                <fileNamePattern>${LOG_DIR}/app-%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
                <maxFileSize>50MB</maxFileSize>
                <maxHistory>14</maxHistory>
                <totalSizeCap>2GB</totalSizeCap>
            </rollingPolicy>
        </appender>

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



    <springProfile name="prod">
        <property name="LOG_DIR" value="/opt/app/logs"/>


        <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>${LOG_DIR}/app.log</file>
            <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                <charset>UTF-8</charset>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger
                    traceId=%X{trace_id:-} spanId=%X{span_id:-} - %msg%n</pattern>
            </encoder>
            <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
                <fileNamePattern>${LOG_DIR}/app-%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
                <maxFileSize>100MB</maxFileSize>
                <maxHistory>30</maxHistory>
                <totalSizeCap>5GB</totalSizeCap>
            </rollingPolicy>
        </appender>

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

</configuration>

 

 

1. MDC 키 동일 (trace_id, span_id)

 

OpenTelemetry Java 에이전트는 요청이 들어오면 자동으로 trace_id / span_id를 MDC에 주입 한다.

기존 수동으로 관리하던 %X{traceId} 대신 %X{trace_id}를 그대로 사용하면 로그와 트레이스 간의 상관관계가 자동으로 연결 된다.

%X{trace_id:-} %X{span_id:-}
  • :-는 값이 없을 경우 공백으로 처리
  • Tempo나 Grafana에서 검색할 때 trace_id 기준으로 손쉽게 조회 가능

 

 

2. 회전 및 보존 정책

 

  • 시간 + 크기 기반 회전
  • totalSizeCap 설정으로 디스크 용량 
  • maxHistory로 로그 보관 기간 관리
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
    <fileNamePattern>${LOG_DIR}/app-%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
    <maxFileSize>50MB</maxFileSize>
    <maxHistory>14</maxHistory>
    <totalSizeCap>2GB</totalSizeCap>
</rollingPolicy>

 

 

3. Profile 기반 로깅 전략 분리

  • local 환경에서는 콘솔 가독성을 위해 컬러 로그를 유지
  • prod 환경에서는 파일 로그만 남기고 운영 서버 디스크 정책에 맞춘 회전 설정을 적용