- 의존성 추가
일반 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가 이미 필요한 의존성을 포함하고 있기 때문입니다.
- 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>
- 로거 사용 예제
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("트레이스: 상세 실행 정보");
}
}
- JAR 패키징 시 logback.xml 포함
java -jar myapp.jar 명령을 실행하면 logs 폴더가 JAR 파일과 동일한 디렉토리에 생성됩니다.
참고 자료
- Maven으로 Logback 설정하기
- 주의사항: TimeBasedRollingPolicy는 시간 기반으로, triggeringPolicy=SizeBasedTriggeringPolicy와 함께 사용할 수 없으며 충돌이 발생할 수 있습니다. Logback이 날짜별로 로그 파일을 생성하지 않는 문제에 대한 참고