우아한테크코스 4기/레벨3

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

나는후니 2022. 7. 16. 13:25

프로젝트를 진행하다 보면 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