
안녕하세요. 비유바움의 Miss 정 입니다!
오늘은 Spring Boot 애플리케이션에서 Logback을 사용하여 효과적으로 로깅을 설정하는 방법에 대해 알아보겠습니다. 로깅은 애플리케이션의 상태를 모니터링하고 문제를 해결하는 데 매우 중요한 역할을 합니다. Spring Boot와 Logback의 조합을 통해 강력하고 유연한 로깅 시스템을 구성할 수 있습니다.
Logback은 Java 애플리케이션을 위한 로그 프레임워크로, 빠르고 유연하며 설정이 간단합니다. 또한 SLF4J(Simple Logging Facade for Java)를 통해 다양한 로깅 프레임워크와 호환됩니다.
Logback은 logback-core, logback-classic, logback-access 세 가지 모듈로 구성되어 있습니다.
Spring Boot 애플리케이션에서는 기본적으로 src/main/resources 경로에 logback-spring.xml 파일을 생성하여 Logback 설정을 관리할 수 있습니다.
Spring Boot의 프로파일 기능을 활용하여 개발, 테스트, 운영 환경별로 다른 로깅 설정을 적용할 수 있습니다. logback-spring.xml 파일을 다음과 같이 수정하여 환경별 설정을 추가할 수 있습니다.
<?xml version="1.0" encoding="UTF-8"?>
<!-- 1초마다 설정 파일 변경 감지 -->
<configuration scan="true" scanPeriod="1 seconds">
<!-- local profile -->
<springProfile name="local">
<!-- 콘솔 -->
<appender class="ch.qos.logback.core.ConsoleAppender" name="console">
<encoder>
<charset>UTF-8</charset>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] [%X{traceId}] %msg \(%logger:%+3line\)%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="console"/>
</root>
<logger level="off" name="p6spy"/>
</springProfile>
<!-- dev profile -->
<springProfile name="dev">
<!-- 콘솔 -->
<appender class="ch.qos.logback.core.ConsoleAppender" name="console">
<encoder>
<charset>UTF-8</charset>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] [%X{traceId}] %msg \(%logger:%+3line\)%n</pattern>
</encoder>
</appender>
<logger level="off" name="p6spy"/>
<root level="info">
<appender-ref ref="console"/>
</root>
</springProfile>
<!-- prod profile -->
<springProfile name="prod">
<!-- 콘솔 -->
<appender class="ch.qos.logback.core.ConsoleAppender" name="console">
<encoder>
<charset>UTF-8</charset>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] [%X{traceId}] %msg \(%logger:%+3line\)%n</pattern>
</encoder>
</appender>
<logger level="off" name="p6spy"/>
<root level="info">
<appender-ref ref="console"/>
</root>
</springProfile>
</configuration>
위와 같이 springProfile을 통해 개발 환경에 따라 로그 관리를 구분 지을 수 있으며 필요한 appender를 추가할 수 있습니다.
springProfile
환경에 따른 복수 개의 프로파일을 설정할 수 있습니다.
설정한 name은 SPRING_PROFILES_ACTIVE에 따라 결정됩니다.
appender
로그의 형태를 설정하고 로그 메시지가 출력될 대상을 결정할 수 있습니다.
encoder
로그 메시지의 형식을 정의합니다.
pattern
%Logger{length} : Logger name을 축약. {length}는 최대 자리 수
%-5level : 로그 레벨, -5는 출력의 고정폭 값(5글자)
%msg : - 로그 메시지
${PID:-} : 프로세스 아이디
%d : 로그 기록 시간
%p : 로깅 레벨
%F : 로깅이 발생한 프로그램 파일명
%M : 로깅일 발생한 메서드의 명
%l : 로깅이 발생한 호출지의 정보
%L : 로깅이 발생한 호출지의 라인 수
%thread : 현재 Thread 명
%t : 로깅이 발생한 Thread 명
%c : 로깅이 발생한 카테고리
%C : 로깅이 발생한 클래스 명
%m : 로그 메시지
%n : 줄바꿈(new line)
%% : %를 출력
%r : 애플리케이션 시작 이후부터 로깅이 발생한 시점까지의 시간(ms)
root, logger
설정한 appender를 참조하여 package와 level을 설정할 수 있습니다.
root : 전역 설정
logger : 지역 설정
운영 환경에서 로그를 중앙에서 관리하고 알림을 받기 위해 AWS CloudWatch와 Slack을 연동할 수 있습니다.
cloud watch를 사용하기 위해 의존성을 추가합니다.
implementation("ca.pjer:logback-awslogs-appender:1.6.0")
다음은 logback-spring.xml 파일에 추가된 AWS CloudWatch 설정입니다.
<!-- prod profile -->
<springProfile name="prod">
...
<!-- 로그 스트림 -->
<appender class="ca.pjer.logback.AwsLogsAppender" name="aws_cloud_watch_log">
<layout>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] [%X{traceId}] %msg \(%logger:%+3line\)%n</pattern>
</layout>
<logGroupName>/fintech/log</logGroupName>
<logStreamUuidPrefix>log-</logStreamUuidPrefix>
<logRegion>ap-northeast-2</logRegion>
<maxBatchLogEvents>50</maxBatchLogEvents>
<maxFlushTimeMillis>30000</maxFlushTimeMillis>
<maxBlockTimeMillis>5000</maxBlockTimeMillis>
<retentionTimeDays>0</retentionTimeDays>
<accessKeyId>${AWS_ACCESSKEY}</accessKeyId>
<secretAccessKey>${AWS_SECRET_ACCESSKEY}</secretAccessKey>
</appender>
<root level="info">
...
<appender-ref ref="aws_cloud_watch_log"/>
</root>
...
</springProfile>
AWS CloudWatch에 로그를 기록하기 위해 appender를 추가합니다.
layout
encoder와 마찬가지로 로그의 출력 포맷을 지정합니다.
logGroupName
AWS CloudWatch Logs의 로그 그룹 이름입니다.
logStreamUuidPrefix
로그 스트림 이름에 사용할 접두사입니다.
각 로그 스트림 이름은 이 접두사와 UUID를 조합하여 생성됩니다.
logRegion
로그를 전송할 AWS 리전입니다.
maxBatchLogEvents
한 번에 전송할 최대 로그 이벤트 수입니다. (기본값은 50)
maxFlushTimeMillis
로그 이벤트 배치가 전송되기 전, 최대 대기 시간(밀리초)을 지정합니다. (기본값 30,000 밀리초)
즉, 로그 이벤트가 쌓여있더라도 30초가 지나면 해당 로그 이벤트들이 전송됩니다.
maxBlockTimeMillis
배치 작업을 하기 전, 내부 버퍼가 가득 찼을 때 기다리는 시간(밀리초)을 지정합니다. (기본값 5,000 밀리초)
retentionTimeDays
로그의 보관 기간입니다. (기본값 0 : AWS의 보관 정책에 따름)
accessKeyId
AWS Access Key로 환경 변수나 다른 외부 설정에서 제공되어야 합니다.
secretAccessKey
AWS Secret Key로 환경 변수나 다른 외부 설정에서 제공되어야 합니다.
Slack 채널에 로그를 전송하기 위해 의존성을 추가합니다.
implementation("com.github.maricn:logback-slack-appender:1.6.1")
implementation("net.gpedro.integrations.slack:slack-webhook:1.4.0")
다음은 logback-spring.xml 파일에 추가된 Slack 설정입니다.
<!-- prod profile -->
<springProfile name="prod">
...
<!-- 슬랙 -->
<appender class="com.github.maricn.logback.SlackAppender" name="slack">
<webhookUri>${SLACK_WEBHOOK_URI}</webhookUri>
<channel>#finit</channel>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] [%X{traceId}] %msg \(%logger:%+3line\)%n</pattern>
</layout>
<username>핀잇-봇</username>
</appender>
<appender class="ch.qos.logback.classic.AsyncAppender" name="slack_async">
<appender-ref ref="slack"/>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
</appender>
<root level="info">
...
<appender-ref ref="slack_async"/>
</root>
...
</springProfile>
Slack 채널에 로그를 전송하기 위해 appender를 추가합니다.
webhookUri
로그를 전송할 URL이며, Slack에서 제공합니다.
channel
로그를 전송할 채널 이름을 지정합니다.
username
Slack 메시지에 표시될 사용자 이름을 지정합니다.
ch.qos.logback.classic.AsyncAppender
AsyncAppender를 사용하여 비동기적으로 로그를 처리합니다.
appender-ref : 앞서 정의한 slack appender를 참조합니다.
ch.qos.logback.classic.filter.ThresholdFilter
특정 로그 레벨 이상의 로그만을 허용하도록 지정할 수 있습니다.
Spring Boot와 Logback을 사용하면 애플리케이션의 로깅을 효과적으로 관리할 수 있습니다. 환경별로 다른 설정을 적용하고, AWS CloudWatch와 Slack과 같은 외부 서비스와 연동하여 로그를 중앙에서 관리하고 알림을 받을 수 있습니다. 이를 통해 애플리케이션의 상태를 모니터링하고, 문제를 신속하게 해결할 수 있습니다.
이상으로 Spring Boot와 Logback을 사용한 효과적인 로깅 설정 방법에 대해 알아보았습니다. 감사합니다!