흰 스타렉스에서 내가 내리지

스프링부트 Logback, 로그, @Slf4j 본문

Spring

스프링부트 Logback, 로그, @Slf4j

주씨. 2023. 2. 5. 19:39
728x90

logback

스프링부트의 기본으로 설정되어 있어서 사용시 별도로 라이브러리를 추가하지 않아도 된다.

 

spring boot logback 설정

▶ 스프링, 일반 자바 프로그램

- logback.xml

▶ 스프링 부트

- logback-spring.xml

 

참고 순서

1. resources 디렉토리에 logback-spring.xml 파일이 있으면 읽는다.

2. logback-spring.xml 파일이 없다면 .yml 파일의 설정을 읽는다.

3. logback-spring.xml 파일과 .yml 파일이 동시에 있으면, .yml 설정파일을 적용한 후 .xml 파일이 적용된다. 

 

로그 레벨 순서 및 사용방법

▶ TRACE < DEBUG < INFO < WARN < ERROR

1) ERROR : 요청을 처리하는 중 오류가 발생한 경우

2) WARN : 처리 가능한 문제, 향후 시스템 에러의 원인이 될 수 있는 경고성 메시지를 나타낸다.

3) INFO : 상태변경과 같은 정보성 로그를 표시한다. 

4) DEBUG : 프로그램을 디버깅하기 위한 정보를 표시한다. 

5) TRACE : Debug 보다 훨씬 상세한 정보를 나타낸다.

 

- 출력 레벨의 설정에 따라 설정 레벨 이상의 로그를 출력한다.

- 로길 레벨 설정을 INFO 로 하였을 경우 TRACE, DEBUG 레벨은 무시한다. 

 

- 스프링부트에서는 간단히 application.properties 에 값만 세팅해도 설정 가능하다. 

logging.level.root=info

 

- 상위 패키지의 디폴트 레벨을 설정하고, 하위 패키지들에 대한 각각의 로깅 레벨을 별도로 설정할 수 있다. 

logging.level.com.demo=info

logging.level.com.demo.controller=debug

 

 

logback-spring.xml

 기본 특징

- name attribute를 반드시 지정해야 한다. 

- appender와 logger 로 크게 두개로 구분된다.

- Dynamic Reloading 기능을 지원한다. 

    ex. 60초 주기마다 로그파일(logback-spring.xml)이 바뀌었는지 검사하고 바뀌었으면 프로그램을 갱신한다. 

<configuration scan="true" scanPeriod="60 seconds">
    로그백 설정
</configuration>

 

▶ 1) appender

- log의 형태를 설정, 로그 메시지가 출력될 대상을 결정하는 요소 (콘솔 or 파일에 출력)

 

- appender의 class 종류

1 ch.qos.logback.core.ConsoleAppender 콘솔에 출력한다. 
2 ch.qos.logback.core.FileAppender 파일에 출력한다. 최대 보관 일수 등을 지정할 수 있다. 
3 ch.qos.logback.core.rolling.RollingFileAppender 여러개의 파일을 순회(롤링)하면서 로그를 찍는다.
FileAppender를 상속받는다.
지정 용량이 넘어간 Log File을 넘버링 하여 나누어 저장할 수 있다. 
4 ch.qos.logback.classic.net.SMTPAppender 로그를 메일에 찍어 보낸다.
5 ch.qos.logback.classic.db.DBAppender 로그를 DB에 찍는다.

 

▶ 2) root, logger

- 설정한 appender를 참조하여 package와 level을 설정한다.

 

> root 

- 전역 설정이라고 볼 수 있다. 

- 지역적으로 선언된 logger 설정이 있다면 해당 logger 설정이 default로 적용된다. 

 

> logger

- 지역 설정이라고 볼 수 있다. 

- additivity 값은 root 설정 상속 유무 설정

 

> property

- 설정 파일에서 사용될 변수값 선언

 

> layout, encoder

- Layout : 로그의 출력 포맷을 지정한다.

- encoder : Appender에 포함되어 사용자가 지정한 형식으로 표현될 로그메시지를 변환하는 역할을 담당하는 요소.

                    encoder는 바이트를 소유하고 있는 appender가 관리하는 OutputStream에 쓸 시간과 내용을 제어할 수 있다. 

                    FileAppender와 하위 클래스는 encoder를 필요로 하고 더 이상 layout은 사용하지 않는다. 

즉 이제 layout 보다는 encoder를 사용하면 된다. 

 

> pattern

%Logger{length} Logger name을 축약할 수 있다. {length}는 최대 자리 수, ex)logger{35}
%-5level 로그 레벨, -5는 출력의 고정폭 값(5글자)
%msg 로그 메시지 (=%message)
${PID:-} 프로세스 아이디
%d 로그 기록시간
%p 로깅 레벨
%F 로깅이 발생한 프로그램 파일명
%M  로깅이 발생한 메소드의 명
%l 로깅이 발생한 호출지의 정보
%L 로깅이 발생한 호출지의 라인 수
%thread 현재 Thread 명
%t  로깅이 발생한 Thread 명
%c 로깅이 발생한 카테고리
%C 로깅이 발생한 클래스 명
%m 로그 메시지
%n 줄바꿈(new line)
%% %를 출력
%r  애플리케이션 시작 이후부터 로깅이 발생한 시점까지의 시간(ms)

 

> etc

<file> 기록한 파일명과 경로를 설정한다. 
<rollingPolicy class="ch.qos.~~~"> ch.qos.logback.core.rolling.TimeBasedRollingPolicy => 일자별 적용
ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP => 일자별 + 크기별 적용
<fileNamePattern> 파일 쓰기가 종료된 log 파일명의 패턴을 지정한다. .gz나 .zip으로 자동으로 압축할 수도 있다.
<maxFileSize> 한 파일당 최대 파일 용량을 지정한다.
log 내용의 크기도 IO성능에 영향을 미치기 때문에 되도록이면 너무 크지 않은 사이즈로 지정하는 것이 좋다.(최대 10MB 내외 권장)
용량의 단위는 KB, MB, GB 3가지를 지정할 수 있다.
<maxHistory> 최대 파일 생성 갯수
예를들어 maxHistory가 30이고 Rolling정책을 일 단위로 하면 30일동안만 저장되고, 월 단위로 하면 30개월간 저장된다.
<Filter> 해당 패키지에 무조건 로그를 찍는 것말고도 필터링이 필요한 경우에 사용하는 기능이다.

 

 

설정

1. 스프링 프로필 설정 - application.yml

spring:
  profiles:
    active: local

 

2. logback-local.yml 파일 생성

log:
  config:
    path: /logs/local     # 로그파일 경로
    filename : local_log  # 로그파일 이름

 

3. logback-spring.xml 생성

<?xml version="1.0" encoding="UTF-8"?>
<!-- 60초마다 설정 파일의 변경을 확인 하여 변경시 갱신 -->
<configuration scan="true" scanPeriod="60 seconds">
    <!--springProfile 태그를 사용하면 logback 설정파일에서 복수개의 프로파일을 설정할 수 있다.-->
    <springProfile name="local">
        <property resource="logback-local.yml"/>
    </springProfile>
    <springProfile name="dev">
        <property resource="logback-dev.yml"/>
    </springProfile>
    <!--Environment 내의 프로퍼티들을 개별적으로 설정할 수도 있다.-->
    <springProperty scope="context" name="LOG_LEVEL" source="logging.level.root"/>

    <!-- log file path -->
    <property name="LOG_PATH" value="${log.config.path}"/>
    <!-- log file name -->
    <property name="LOG_FILE_NAME" value="${log.config.filename}"/>
    <!-- err log file name -->
    <property name="ERR_LOG_FILE_NAME" value="err_log"/>
    <!-- pattern -->
    <property name="LOG_PATTERN" value="%-5level %d{yy-MM-dd HH:mm:ss}[%thread] [%logger{0}:%line] - %msg%n"/>

    <!-- Console Appender -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>
    </appender>

    <!-- File Appender -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 파일경로 설정 -->
        <file>${LOG_PATH}/${LOG_FILE_NAME}.log</file>

        <!-- 출력패턴 설정-->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>

        <!-- Rolling 정책 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- .gz,.zip 등을 넣으면 자동 일자별 로그파일 압축 -->
            <fileNamePattern>${LOG_PATH}/${LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <!-- 파일당 최고 용량 kb, mb, gb -->
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!-- 일자별 로그파일 최대 보관주기(~일), 해당 설정일 이상된 파일은 자동으로 제거-->
            <maxHistory>30</maxHistory>
            <!--<MinIndex>1</MinIndex>
            <MaxIndex>10</MaxIndex>-->
        </rollingPolicy>
    </appender>

    <!-- 에러의 경우 파일에 로그 처리 -->
    <appender name="Error" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>error</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <file>${LOG_PATH}/${ERR_LOG_FILE_NAME}.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>
        <!-- Rolling 정책 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- .gz,.zip 등을 넣으면 자동 일자별 로그파일 압축 -->
            <fileNamePattern>${LOG_PATH}/${ERR_LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <!-- 파일당 최고 용량 kb, mb, gb -->
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!-- 일자별 로그파일 최대 보관주기(~일), 해당 설정일 이상된 파일은 자동으로 제거-->
            <maxHistory>60</maxHistory>
        </rollingPolicy>
    </appender>

    <!-- root레벨 설정 -->
    <root level="${LOG_LEVEL}">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
        <appender-ref ref="Error"/>
    </root>

    <!-- 특정패키지 로깅레벨 설정 -->
    <logger name="org.apache.ibatis" level="DEBUG" additivity="false">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
        <appender-ref ref="Error"/>
    </logger>
</configuration>

 

세분화 해서 살펴보기

 

1) Console Appender 설정

<!-- pattern -->
<property name="LOG_PATTERN" value="%-5level %d{yy-MM-dd HH:mm:ss}[%thread] [%logger{0}:%line] - %msg%n"/>

<!-- Console Appender -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        <pattern>${LOG_PATTERN}</pattern>
    </encoder>
</appender>

<!-- root레벨 설정 -->
<root level="${LOG_LEVEL}">
    <appender-ref ref="CONSOLE"/>
</root>

ex) %-5level %d{yy-MM-dd HH:mm:ss}[%thread] [%logger{0}:%line] - %msg%n

=> INFO  20-02-16 16:34:42[http-nio-8080-exec-3] [TestController:41] - INFO Level 테스트

 

 

2) File Appender 설정

    <!-- root레벨 설정 -->
    <root level="${LOG_LEVEL}">
        <appender-ref ref="FILE"/>
    </root>

 

 

 

+++++++++++++++

<?xml version="1.0" encoding="UTF-8"?>
<!-- 60초마다 설정 파일의 변경을 확인 하여 변경시 갱신 -->
<configuration scan="true" scanPeriod="60 seconds">
    <!--springProfile 태그를 사용하면 logback 설정파일에서 복수개의 프로파일을 설정할 수 있다.-->
<!--    <springProfile name="local">-->
<!--        <property resource="log/logback-local.yml"/>-->
<!--    </springProfile>-->
<!--    <springProfile name="dev">-->
<!--        <property resource="log/logback-dev.yml"/>-->
<!--    </springProfile>-->
    <!--Environment 내의 프로퍼티들을 개별적으로 설정할 수도 있다.-->
    <springProperty scope="context" name="LOG_LEVEL" source="logging.level.root"/>

    <!-- log file path -->
    <springProperty scope="context" name="LOG_PATH" source="log.config.path"/>
    <!-- log file name -->
    <springProperty scope="context" name="LOG_FILE_NAME" source="log.config.filename"/>
    <!-- err log file name -->
    <property name="ERR_LOG_FILE_NAME" value="err_log"/>
    <!-- pattern -->
    <property name="LOG_PATTERN" value="%-5level %d{yy-MM-dd HH:mm:ss} [%t] [%logger{0}:%M:%L] - %msg%n"/>

    <!-- Console Appender -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>
    </appender>

    <!-- File Appender -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 파일경로 설정 -->
        <file>${LOG_PATH}/${LOG_FILE_NAME}.log</file>

        <!-- 출력패턴 설정-->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>

        <!-- Rolling 정책 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- .gz,.zip 등을 넣으면 자동 일자별 로그파일 압축 -->
            <fileNamePattern>${LOG_PATH}/${LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <!-- 파일당 최고 용량 kb, mb, gb -->
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!-- 일자별 로그파일 최대 보관주기(~일), 해당 설정일 이상된 파일은 자동으로 제거-->
            <maxHistory>30</maxHistory>
            <!--<MinIndex>1</MinIndex>
            <MaxIndex>10</MaxIndex>-->
        </rollingPolicy>
    </appender>

    <!-- 에러의 경우 파일에 로그 처리 -->
    <appender name="Error" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>error</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <file>${LOG_PATH}/${ERR_LOG_FILE_NAME}.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>
        <!-- Rolling 정책 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- .gz,.zip 등을 넣으면 자동 일자별 로그파일 압축 -->
            <fileNamePattern>${LOG_PATH}/${ERR_LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <!-- 파일당 최고 용량 kb, mb, gb -->
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!-- 일자별 로그파일 최대 보관주기(~일), 해당 설정일 이상된 파일은 자동으로 제거-->
            <maxHistory>60</maxHistory>
        </rollingPolicy>
    </appender>

    <!-- root레벨 설정 -->
    <root level="${LOG_LEVEL}">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
        <appender-ref ref="Error"/>
    </root>

<!--    &lt;!&ndash; 특정패키지 로깅레벨 설정 &ndash;&gt;-->
<!--    <logger name="org.apache.ibatis" level="DEBUG" additivity="false">-->
<!--        <appender-ref ref="CONSOLE"/>-->
<!--        <appender-ref ref="FILE"/>-->
<!--        <appender-ref ref="Error"/>-->
<!--    </logger>-->
</configuration>
spring:
  config:
    activate:
      on-profile: "local"

log:
  config:
    path: ./logs/local   #로그파일 경로
    filename: local_log #로그파일 이름

logging:
  config: classpath:log/logback-spring.xml
  level:
    root: info