본문 바로가기
우아한테크코스 4기/레벨3

[Logback] Spring Logback configuration 과정 (1) - Appenders

by 나는후니 2022. 7. 16.

프로젝트를 진행하다 보면 Exception Handler에서 예외가 잡혀 stackTrace를 보지 못하고 에러 지점을 찾지 못하는 경우가 있습니다.

그런 경우에 Spring Boot에서 기본으로 제공하는 Logback을 사용하는데요, Lombok 플러그인을 사용하면 그 사용법이 정말 간단합니다.

// lombok과 spring-boot-starter-web을 dependency에 추가해야합니다.
@Slf4j
public class LogbackTest {
  public static void main(String[] args) {
    log.info("어쩌규");
    log.error("저쩌구");
  }
}

이렇게 코드로 작성한 로그를 항상 콘솔로 보며 모니터링 할 수 있을까요?

당연히 불가능합니다. 따라서 Spring의 경우 src/main/resources 경로에 logback-spring.xml 파일을 두어 profile, 로그 종류 등에 따라 각기 다른 로깅 조건을 설정할 수 있습니다.

 

Spring에서 기본 Console 로깅 전략으로 아래와 같은 xml파일을 확인할 수 있는데요.

<!-- {consol-appender.xml} -->
<included>
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>${CONSOLE_LOG_CHARSET}</charset>
        </encoder>
    </appender>
</included>

<!-- {file-appender.xml} -->
<included>
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder>
            <pattern>${FILE_LOG_PATTERN}</pattern>
            <charset>${FILE_LOG_CHARSET}</charset>
        </encoder>
        <file>${LOG_FILE}</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz}</fileNamePattern>
            <cleanHistoryOnStart>${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false}</cleanHistoryOnStart>
            <maxFileSize>${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB}</maxFileSize>
            <totalSizeCap>${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0}</totalSizeCap>
            <maxHistory>${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-7}</maxHistory>
        </rollingPolicy>
    </appender>
</included>

형태를 대략적으로 살펴보면 아래와 같습니다.

  • 이름과 클래스를 가진 appender
  • pattern과 charset을 지정할 수 있는 encoder
  • (RollingFileAppender의 경우) rollingPolicy와 그 전략(파일 이름 패턴, 시작시 클린, 최대 파일 사이즈, 총 사이즈 제한, 최대 저장 기한) 등

이 xml Configuration들이 어딘가에 객체로 할당되어 사용되고 있다는 뜻인데요. 이제부터 이 설정파일이 어디에 저장되고 사용하는지 알아보겠습니다.

Logback-core

위 사진이 바로 Logback-core의 핵심이 되는 존재인 Appender입니다. Appender는 방금 xml 코드에서 봤던, 설정의 root가 되는 존재인데요.

공식 문서에서는 OutputStreamAppender부터 상세히 설명하고 있었습니다.

OutputStreamAppender는 문자열로 쉽게 매핑할 수 없어, 직접 인스턴스화하지 않습니다. 즉 configure 파일에 직접 이 OutputStreamAppender를 설정하여 사용할 수 없습니다. 따라서 ConsolAppender, FileAppender, RollingFileAppender를 root appender 로 사용하게 되겠죠?

ConsoleAppender

ConsoleAppender의 경우 설정해야 할 내용이 크게 없습니다. 가장 핵심이 되는 존재가 encoder 클래스인데요. 그 외에도 여러 몇 가지들이 있습니다.

  • target : System.out or System.err / default System.out
  • withJansi: 윈도우인데, 콘솔 로그에 색을 주고싶다면 true(class path에 jansi version이 담긴 클래스도 함께 입력해야함), default는 false 하지만 맥과 리눅스는 자동으로 지원해줍니다.
  • Encoder: encoder의 default 클래스는 PatternLayoutEncoder입니다. FileAppender와 그 하위 클래스는 꼭 PatternLayoutEncoder를 사용해야 하고 Layout(Pattern, charset)과 logback Context, 로그 파일 상단에 Pattern을 작성하는 옵션을 제공합니다.

Encoder는 챕터가 따로 존재합니다. 간단한 내용을 소개하자면 현재는 PatternLayoutEncoder가 only really usefult encoder라고 합니다. 그 이유는 챕터에 소개가 되어 있으니 읽어보는 것을 추천합니다. 링크

FileAppender와 RollingFileAppender

로그는 파일로 저장해두어야 합니다. 그 파일을 이용하여 서비스를 더욱 개선할 수 있는 자료로 만들 수 있고, 또 적절하게 에러를 고칠 수도 있습니다. FileAppender 클래스는 이런 기능을 제공해줍니다. 하지만 FileAppender에는 용량이 가득찼을 때 대처할 수 있는 방법이 존재하지 않습니다. 또, 오래된 로그 파일을 제거할 수 있는 방법도 없습니다.

그래서 로그 파일을 저장할 때 File을 Rolling하며 로그를 저장할 수 있는 기능을 가진 RollingFileAppender를 주로 사용합니다.

  • file: 파일 명 지정, 폴더가 없을 경우 직접 생성해줍니다.
  • rollingPolicy: 롤오버가 필요할 때를 지정해주는 정책입니다. 주로 TimeBasedRollingPolicy 나 SizeAndTimeBasedRollingPolicy를 사용합니다.
  • triggeringPolicy: 롤오버를 활성화 할때를 지정해주는 정책입니다. 이해한 바로는 RollingPolicy와 유사하여 굳이 동시에 쓸 필요는 없어보입니다.
  • Prudent: 서로 다른 호스트의 JVM에서 File에 로그를 저장하려 할 때 이를 안정적으로 처리해줍니다. 다만 성능이 false일 때보다 약 3배 가량 늦습니다. 1초에 100개 이상의 로그가 남을 때 성능에 크리티컬한 이슈가 발생하므로, 해당 상황에는 이 전략을 피해야 합니다. TimeBasedRollingPolicy에서 이 전략을 사용할 수 있고 두가지 주의사항이 있으니 참고하여 사용해야 합니다.
  • immediate flush: outputSream에 남은 로그를 바로 flush합니다. 덕분에 로그를 잃을 일이 없어 안정적이지만, 로깅 입력이 급격하게 늘어날 때 이 옵션을 false로 유지해야 합니다. (Disk에 I/O 를 로그가 남을 때 마다 진행하면 성능 저하가 발생하기 때문이지 않을까..)

위와 같은 Appender설정으로 최초에 설명했던 xml 코드를 읽어와 로깅을 효과적으로 할 수 있게 됐습니다.

하지만 이렇게만 설정하면 로그가 남지 않습니다. 바로 <included> 이녀석 때문인데요, 아직 로그 설정에 포함 될 수 있는 존재로만 설정이 된 것입니다.

 

다음 포스팅에는 Spring profile 별, 에러 레벨 별로 다른 로그 정책을 설정하는 방법에 대해 소개해보겠습니다.

 

참고 링크 : https://logback.qos.ch/manual/appenders.html