Logback이란 SLF4J 인터페이스를 구현한 클래스이며, 특정 로그를 콘솔, 파일, DB 등에 남길 수 있습니다.

 

...
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
</dependencies>
...

spring-boot-starter-web 라이브러리에 logback-classic, logback-core가 탑재되어있어서 따로 dependency 하지 않아도 됩니다.

이번 테스트에서는 Maven을 사용하고 라이브러리 버전은 다음과 같습니다.

spring-boot-2.2.2.RELEASE
logback-classic-1.2.3
logback-core-1.2.3

1. application.yml

bamdule.logging.dir : D://logs/spring-boot-log/bamdule
bamdule.logging.level : DEBUG

로그 파일 경로와 로그 레벨을 설정해 줍니다.


2. logback-spring.xml

  • src/main/resources/logback-spring.xml
  • spring boot 구동 시 자동으로 위 경로에 logback-spring.xml 파일이 있는지 탐색하고 logback 설정을 적용 합니다.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>

	<!-- aplication.yml에 정의한 log level, dir 데이터를 정의합니다 -->
    <springProperty scope="context" name="LOG_LEVEL" source="bamdule.logging.level"/>
    <springProperty scope="context" name="LOG_DIR" source="bamdule.logging.dir"/>

    <!--콘솔에 로그를 남깁니다.-->
    <appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>
                %d{yyyy-MM-dd HH:mm:ss} [%thread] [%-5level] %logger{36} - %msg%n
            </Pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!--파일에 로그를 남깁니다.-->
    <appender name="File" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_DIR}/bamdule.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>
                %d{yyyy-MM-dd HH:mm:ss} [%-5level] %logger{36} - %msg%n
            </Pattern>
            <charset>UTF-8</charset>
        </encoder>

        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_DIR}/bamdule/bamdule.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
    </appender>
   
<!--파일에 로그를 남깁니다. (Roling)-->
    <appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_DIR}/archived/bamdule_roling.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>%d{yyyy-MM-dd HH:mm:ss} [%-5level] %logger{36} - %msg%n</Pattern>
            <charset>UTF-8</charset>
        </encoder>
        
        <!-- 10MB가 넘어가면 새로운 압축파일이 생성 -->
        <triggeringPolicy
            class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy>

        <!-- 파일을 덮어쓰는 정책 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
            <FileNamePattern>${LOG_DIR}/archived/bamdule_roling.%i.log.zip</FileNamePattern>
            <!--
                10MB단위로 로그 압축 파일이 생성된다. (1 ~ 10)
                10개가 넘어가면 오래된순으로 덮어쓰기 됩니다.
            -->
            <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_DIR}/bamdule-error.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>
                %d{yyyy-MM-dd HH:mm:ss} [%-5level] %logger{36} - %msg%n
            </Pattern>
            <charset>UTF-8</charset>
        </encoder>

        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_DIR}/bamdule/bamdule-error.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
    </appender>
    
    <!--
        org.springframework.web 패키지 아래에서 발생하는 INFO 레벨 로그를 Console, File에 남깁니다.
        root의 속성을 상속받지 않습니다.
    -->
    <logger name="org.springframework.web" level="INFO" additivity="false">
        <appender-ref ref="Console"/>
        <appender-ref ref="File"/>
        <appender-ref ref="Error"/>
    </logger>
    
    <logger name="org.apache.ibatis" level="DEBUG" additivity="false">
        <appender-ref ref="Console"/>
        <appender-ref ref="RollingFile"/>
        <appender-ref ref="Error"/>
    </logger>

    <!--
        DEBUG 레벨 로그를 Console, File, RollingFile에 남깁니다.
        ERROR 인 경우 bamdule-error.log에 남깁니다.
    -->
    <root level="${LOG_LEVEL}">
        <appender-ref ref="Console"/>
        <appender-ref ref="File"/>
        <appender-ref ref="Error"/>
    </root>

</configuration>

위와 같이 하면 설정이 끝나게 됩니다.


3. Logback Test

import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@SpringBootTest
@RunWith(SpringRunner.class)
class LogbackTest {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Test
    void 로그_테스트() {
        logger.debug("[DEBUG]");
        logger.info("[INFO]");
        logger.warn("[WARN]");
        logger.error("[ERROR]");
    }
}

 

  • org.slf4j.Logger와 org.slf4j.LoggerFactory를 import 해야 하며, LoggerFactory를 통해 logger를 주입받으면 됩니다.

 

4. Log Level

  • TRACE, DEBUG, INFO, WARN, ERROR Level이 존재하며 TRACE가 제일 낮고, ERROR가 가장 높습니다.
  • Log Level은 출력 범위를 나타내며, Level이 INFO 인 경우 TRACE, DEBUG Level Log는 보이지 않고
    INFO Level 이상 Log만 화면에 출력됩니다. 즉 현재 레벨 이상의 로그만 화면에 출력됩니다. 

5. Appender

  • 로그를 출력 위치와 출력 패턴 등을 설정합니다.. 
  • ConsoleAppender
    • 로그를 OutputStream에 write하여 콘솔에 출력되도록 합니다.
  • FileAppender
    • 로그의 내용을 File에 write합니다.
    • 최대 보관 일 수를 지정할 수 있습니다.
  • RolingFileAppender
    • FileAppender를 상속 받습니다.
    • 지정한 용량이 넘어간 Log File을 넘버링을 통해 나누어 저장할 수 있습니다.
    • 최소, 최대 개수를 지정 할 수 있고, 최대 개수가 넘어갔을 경우 오래된 순으로 덮어쓰기 됩니다.

6. <logger>와 <root>

logger는 지역적인 설정을 의미하고, root는 전역적인 설정을 의미합니다.

   ...
    <logger name="org.springframework.web" level="INFO" additivity="false">
        <appender-ref ref="Console"/>
        <appender-ref ref="File"/>
        <appender-ref ref="Error"/>
    </logger>
    
    <logger name="org.apache.ibatis" level="DEBUG" additivity="false">
        <appender-ref ref="Console"/>
        <appender-ref ref="RollingFile"/>
        <appender-ref ref="Error"/>
    </logger>

    <root level="${LOG_LEVEL}">
        <appender-ref ref="Console"/>
        <appender-ref ref="File"/>
        <appender-ref ref="Error"/>
    </root>
  • logger
    • org.springframework.web 하위에 동작하는 INFO 로그를 Console, File, Error에 출력하라는 의미입니다.
      그리고 레벨이 INFO이기 떄문에 DEBUG 로그는 찍히지 않습니다.
    • additivity 값은 root 설정 상속 유무인데, 상속을 받게 되면 logger에서 설정하지 않은 나머지 설정이 적용됩니다.
  • root
    • 지정된 레벨 이상의 로그를 출력 했을 경우 Console, File, Error에 출력하라는 의미입니다. 지역적으로 선언된 logger 설정이 있다면 해당 logger 설정으로 적용됩니다.

도움이 되셨다면 공감 한번씩 눌러주시면 감사하겠습니다.

+ Recent posts