Logging (로깅)
로그는 소프트웨어 시스템이 실행될 때 발생하는 이벤트나 정보를 기록하는 중요한 프로세스이다. 로그는 디버깅 및 문제 해결, 성능 모니터링, 보안 감사, 운영 모니터링, 이력 추적 등을 위해 사용한다. Spring Boot에서는 SLF4J (Simple Logging Facade for Java)와 Logback을 주로 활용하여 로깅을 구현한다. Logback은 특히 유연성과 확장성이 뛰어나며 다양한 로깅 형식과 출력 대상을 지원한다. 설정 파일을 일정 시간마다 스캔하여 애플리케이션 중단 없이 설정을 변경할 수 있다.
로깅 처리 과정
로그의 형태와 출력 위치는 xml 파일이나 yml 파일에 로깅 설정 파일을 생성하여 구현한다. 예시를 통해 로깅 설정에 대해 알아보자.
의존성 추가
보통 Spring Boot에서 Logback을 지원하기 때문에 의존성 주입을 하지 않아도 괜찮지만, @S4f4j 어노테이션을 사용하는 경우 추가적인 로깅 라이브러리를 설정해야 한다.
<!-- Maven -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- 추가적인 로깅 라이브러리 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
로깅 파일 구성
로깅 구성은 application.yml (또는 application.properties)로도 구현이 가능하지만 관련 설정이 많아지면 관리가 복잡하기 때문에 logback-spring.xml 파일로 구성한다. yml 파일로도 구성이 가능하며, xml → yml의 파일 변환 방법은 AI를 활용하도록 하자. 파일은 src/main/resources 폴더에 생성한다.
<!-- logback-spring.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- Console Appender -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- File Appender -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 파일의 경로 및 이름 설정 -->
<file>logs/myapp.log</file>
<!-- 특정 레벨만 출력할 경우 -->
<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.TimeBasedRollingPolicy">
<!-- 파일 이름 패턴 -->
<fileNamePattern>./info-%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 백업된 로그 파일의 최대 개수 -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<!-- 파일 내용에 기록될 패턴 -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- A 클래스에 대한 로그 설정 -->
<logger name="a" level="INFO">
<appender-ref ref="CONSOLE" />
</logger>
<!-- Root Logger -->
<root level="INFO">
<appender-ref ref="FILE"/>
</root>
</configuration>
태그 설명
- Appender 종류
- ConsoleAppender: 콘솔에 로그 출력
- FileAppender: 파일에 로그 저장
- RollingFileAppender: 여러 개의 파일을 순회하며 로그 저장 (로그의 레벨 기준으로 순회)
- DBAppender: 데이터베이스에 로그 저장
로그를 레벨 별로 파일을 저장하고 싶을 때는 filter를 사용한다.
- LevelFilter: 레벨에 따른 일종의 if문
- level: 로그 레벨 설정
- onMatch: 해당 레벨과 일치할 때
- onMisMatch: 해당 레벨과 일치하지 않을 때
로그 레벨에는 TRACE, DEBUG, INFO, WARN, ERROR 5가지가 있으며, 보통 로그 파일을 설정할 때는 INFO 이상의 레벨을 기록한다.
로그 레벨 | 설명 |
ERROR | - 가장 심각한 로그 레벨 - 애플리케이션에서 치명적인 오류가 발생했음을 나타냄 - 애플리케이션의 정상적인 동작을 중단시키거나 복구할 수 없는 문제 - 주로 예외가 발생했을 때 기록되며, 심각한 장애 상황을 식별하고 해결하는 데 사용됨 |
WARN | - 에러보다 덜 심각하지만 주의가 필요한 상황 - 애플리케이션은 계속 동작하고 있지만 잠재적인 문제가 있을 때 (ex. 예상치 못한 입력이나 설정 오류와 같은 상황) - 잠재적인 문제를 식별하고 해결하기 위한 정보를 제공함 |
INFO | - 애플리케이션의 정상적인 동작에 관한 중요한 정보 기록 - 애플리케이션이 시작되었거나 주요 이벤트가 발생했을 때 사용 - 애플리케이션의 상태와 동작에 대한 전반적인 정보를 제공하여 상태를 모니터링하고 이해할 수 있도록 함 |
DEBUG | - 디버깅을 위한 상세한 정보 기록 - 주로 개발 단계에서 사용되며, 애플리케이션의 내부 동작을 추적하고 문제를 해결하기 위한 정보 제공 - 애플리케이션의 각 단계에서의 변수 값, 메서드 호출 등과 같은 상세한 정보 포함 |
TRACE | - 애플리케이션의 각 단계에서의 매우 상세한 정보 기록 - 주로 DEBUG 레벨 이상의 정보가 필요한 특정 문제를 해결하기 위해 활성화 - 보통 운영 환경에서는 활성화되지 않고, 개발 환경에서 필요할 때만 활성화 |
- TimeBasedRollingPolicy: RollingFileAppender를 사용하면 날짜 별로 로그 파일을 저장할 수 있기 때문에 사용한다.
- fileNamePattern: 일 별로 해당 파일 패턴을 사용하여 로그 저장, %d를 반드시 사용해야 한다.
- maxHistory: 최대 파일 개수로, 해당 개수가 넘어가면 오래된 파일부터 삭제한다.
- Encoder Pattern
- %d{HH:mm:ss.SSS}: 로그의 날짜 및 시간 형식 지정
- %thread: 현재 스레드의 이름 출력
- %-5level: Logback에서 레벨을 출력하는 패턴
- %logger{36}: 로거 이름 최대 36자까지 출력
- %msg: 실제 로그 메시지 출력
- %n: 개행 문자
특정 클래스에 로거 설정을 저장할 때와 전역 설정으로는 다음으로 구성된다.
- Root: 전역 설정
- Logger: 지역 설정
- appender-ref: appender의 name으로 로거에 참고
앞서 본 logback-spring.xml은 여러 설정을 한 파일에 보여준 예시이다. 로그를 여러 파일에 나누어 설정하는 예시도 알아보자. include/included 태그를 사용하여 구성한다.
<!-- file-appender.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<included>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logdir}/info.log</file>
<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.TimeBasedRollingPolicy">
<fileNamePattern>${logdir}/info-%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${file_pattern}</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="FILE"/>
</root>
</included>
<!-- logback-spring.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- log를 저장할 디렉토리 -->
<property name="logdir" value="./logs" />
<!-- 파일 이름 패턴 -->
<property name="file_pattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n" />
<include resource="file-appender.xml" />
</configuration>
이전과 같은 설정으로 구성하였으며, property를 사용해 log를 저장할 디렉토리와 file pattern을 지정하였다.
'Back-End > Spring Boot' 카테고리의 다른 글
[Spring Boot] Spring AOP (0) | 2024.10.10 |
---|---|
[Spring Boot] 스크래핑 비동기 처리 (6) | 2024.10.09 |
[Spring Boot] N+1 문제 (1) | 2024.10.05 |
[Spring Boot] JPA 쿼리 최적화 (1) | 2024.10.04 |
[Spring Boot] Setter vs Builder (0) | 2024.03.28 |