Java/SpringBoot + Maven에서 Logback 활용 가이드

  1. 의존성 추가

일반 Java + Maven 프로젝트의 경우 다음 의존성을 수동으로 추가해야 합니다.

    <properties>
        <logback.version>1.2.3</logback.version>
        <slf4j.version>1.7.30</slf4j.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>${logback.version}</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-access</artifactId>
            <version>${logback.version}</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>${logback.version}</version>
        </dependency>
    </dependencies>

Spring Boot + Maven 프로젝트의 경우 이 단계는 생략할 수 있습니다. Spring-boot-starter가 이미 필요한 의존성을 포함하고 있기 때문입니다.

  1. logback.xml 설정 파일 생성

src/main/resources 폴더에 logback.xml 설정 파일을 다음과 같이 생성합니다:

방법 1: 모든 로그 레벨을 하나의 파일에 저장

필요에 따라 APP_NAME 속성을 수정합니다. 생성되는 로그 파일 형식은 appname.yyyy-MM-dd.i.log이며, 동일한 날짜마다 10MB마다 새 로그 파일이 생성됩니다.

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="10 seconds">

    <property name="LOG_PATH" value="./logs" />
    <property name="APP_NAME" value="myapplication" />
    <property name="LOG_FORMAT" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n" />

    <!-- 콘솔 출력 -->
    <appender name="CONSOLE_OUTPUT" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>info</level>
        </filter>
        <encoder>
            <pattern>${LOG_FORMAT}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- 파일 출력 -->
    <appender name="FILE_OUTPUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <FileNamePattern>${LOG_PATH}/${APP_NAME}.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
            <MaxFileSize>10MB</MaxFileSize>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${LOG_FORMAT}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- 로그 레벨 설정 -->
    <root level="info">
        <appender-ref ref="CONSOLE_OUTPUT" />
        <appender-ref ref="FILE_OUTPUT" />
    </root>
</configuration>

방법 2: 다른 로그 레벨을 다른 파일에 분리 저장

필요에 따라 APP_NAME 속성을 수정합니다. 생성되는 로그 파일 형식은 appname.loglever.yyyy-MM-dd.i.log이며, 동일한 날짜마다 10MB마다 새 로그 파일이 생성됩니다.

<!-- scan 속성이 true이면 설정 파일이 변경될 때마다 다시 로드됩니다. 기본값은 true입니다. -->
<!-- scanPeriod는 설정 파일을 확인할 간격을 설정합니다. 시간 단위가 지정되지 않으면 기본 단위는 밀리초입니다. scan이 true일 때 이 속성이 유효합니다. 기본 간격은 1분입니다. -->
<!-- debug 속성이 true이면 logback 내부 로그 정보가 출력되어 logback 실행 상태를 실시간으로 볼 수 있습니다. 기본값은 false입니다. -->
<configuration scan="true" scanPeriod="60 seconds" debug="false">

    <!-- 로그 파일 출력 위치 정의 -->
    <property name="LOG_PATH" value="./logs" />
    <property name="APP_NAME" value="myapplication" />

    <!-- 로그 최대 보관 기간 30일 -->
    <property name="maxHistory" value="30" />

    <!-- 로그 단일 파일 최대 크기 10MB -->
    <property name="maxSize" value="10MB" />

    <!-- 로그 출력 형식 설정 -->
    <property name="LOG_FORMAT" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n" />

    <!-- ConsoleAppender 콘솔 로그 출력 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${LOG_FORMAT}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- ERROR 레벨 로그 -->
    <appender name="ERROR_LOGS" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 필터, ERROR 레벨의 로그만 기록 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <!-- 롤링 정책, 시간과 로그 파일 크기에 따라 롤링 정책을 수립합니다. -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <FileNamePattern>${LOG_PATH}/${APP_NAME}.error.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <MaxHistory>${maxHistory}</MaxHistory>
            <MaxFileSize>${maxSize}</MaxFileSize>
        </rollingPolicy>
        <!-- 로그 출력 형식 설정 -->
        <encoder>
            <pattern>${LOG_FORMAT}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- WARN 레벨 로그 appender -->
    <appender name="WARN_LOGS" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <FileNamePattern>${LOG_PATH}/${APP_NAME}.warn.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <MaxHistory>${maxHistory}</MaxHistory>
            <MaxFileSize>${maxSize}</MaxFileSize>
        </rollingPolicy>
        <encoder>
            <pattern>${LOG_FORMAT}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- INFO 레벨 로그 appender -->
    <appender name="INFO_LOGS" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <FileNamePattern>${LOG_PATH}/${APP_NAME}.info.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <MaxHistory>${maxHistory}</MaxHistory>
            <MaxFileSize>${maxSize}</MaxFileSize>
        </rollingPolicy>
        <encoder>
            <pattern>${LOG_FORMAT}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- DEBUG 레벨 로그 appender -->
    <appender name="DEBUG_LOGS" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <FileNamePattern>${LOG_PATH}/${APP_NAME}.debug.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <MaxHistory>${maxHistory}</MaxHistory>
            <MaxFileSize>${maxSize}</MaxFileSize>
        </rollingPolicy>
        <encoder>
            <pattern>${LOG_FORMAT}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- TRACE 레벨 로그 appender -->
    <appender name="TRACE_LOGS" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>TRACE</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <FileNamePattern>${LOG_PATH}/${APP_NAME}.trace.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <MaxHistory>${maxHistory}</MaxHistory>
            <MaxFileSize>${maxSize}</MaxFileSize>
        </rollingPolicy>
        <encoder>
            <pattern>${LOG_FORMAT}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- 루트 레벨 DEBUG -->
    <root>
        <!-- debug 레벨 이상의 로그 출력 -->
        <level value="debug" />
        <!-- 콘솔 출력 -->
        <appender-ref ref="console" />
        <!-- 파일 출력 -->
        <appender-ref ref="ERROR_LOGS" />
        <appender-ref ref="INFO_LOGS" />
        <appender-ref ref="WARN_LOGS" />
        <appender-ref ref="DEBUG_LOGS" />
        <appender-ref ref="TRACE_LOGS" />
    </root>
</configuration>
  1. 로거 사용 예제
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoggingDemo {
    private static Logger logger = LoggerFactory.getLogger(LoggingDemo.class);

    public static void main(String[] args) {
        logger.error("에러 발생: 시스템 오류");
        logger.warn("경고: 잠재적 문제 발생");
        logger.info("정보: 시스템 상태 확인");
        logger.debug("디버그: 처리 과정 추적");
        logger.trace("트레이스: 상세 실행 정보");
    }
}
  1. JAR 패키징 시 logback.xml 포함

java -jar myapp.jar 명령을 실행하면 logs 폴더가 JAR 파일과 동일한 디렉토리에 생성됩니다.

참고 자료

  • Maven으로 Logback 설정하기
  • 주의사항: TimeBasedRollingPolicy는 시간 기반으로, triggeringPolicy=SizeBasedTriggeringPolicy와 함께 사용할 수 없으며 충돌이 발생할 수 있습니다. Logback이 날짜별로 로그 파일을 생성하지 않는 문제에 대한 참고

태그: Logback java spring-boot maven logging

6월 1일 11:46에 게시됨