프로젝트를 진행하면서 로그 파일의 중요성을 체감하지 못했다. 배치 서버를 개발하면서 배치 로직이 잘 실행되는지, 만약 에러가 발생할 경우 로그를 명확하게 분석하기가 어려웠다. 별도의 설정 없이도 Logback을 통해 로그를 콘솔에 출력해 오다가 배포를 진행하면서 이전의 로그를 찾는데 불편함을 느끼면서 로그 관리의 필요성을 깨달았다.
로그백(Logback) 설정을 하는 이유는 여러 가지가 있으며, 특히 클라우드 서버와 같은 환경에서 로깅을 효율적으로 관리하고 분석하기 위한 중요성이 크다.
1. 유연한 로그 레벨 관리
로그 레벨 지정: 로그백을 사용하면 DEBUG, INFO, WARN, ERROR 등 다양한 로그 레벨을 설정할 수 있다. 이를 통해 필요한 정보만 필터링하여 볼 수 있어, 문제를 빠르게 파악하고 디버깅할 수 있다.
환경별 설정: 개발, 테스트, 운영 등 환경에 따라 로그 레벨을 다르게 설정할 수 있어, 운영 환경에서는 ERROR나 WARN 레벨만 기록하고, 개발 환경에서는 DEBUG 레벨을 기록할 수 있다.
PRD 또는 STG 서버에서는 로그에 모든 로깅 레벨을 설정할 필요는 없다. DEBUG 레벨은 많은 양의 로그를 생성하기 때문이다. PRD나 STG 환경에서는 높은 로깅 레벨(INFO, ERROR)만을 사용하여 로그의 양을 줄이고, 성능 저하를 방지해야한다.
DEBUG 레벨은 디버깅 시에만 필요한 상세 정보를 제공하므로, 운영 환경에서는 중요한 정보만 로그에 남기고, 불필요한 디버깅 정보를 제거하여 로그의 가독성을 높여 로그를 분석하기가 더 쉬워진다.
DEBUG 로그에 민감한 정보(예: 사용자 데이터, 인증 정보)가 포함될 수 있다. PRD 환경에서는 이러한 정보가 로그에 남지 않도록 주의해야한다.
2. 로그 출력 형식 조정
포맷 커스터마이징: 로그 메시지의 형식을 조정할 수 있어, 필요한 정보(예: 타임스탬프, 로그 레벨, 메시지, 스레드 정보 등)를 포함하여 가독성을 높일 수 있다.
<configuration>
<property name="LOG_PATTERN" value="%d{yy-MM-dd HH:mm:ss} [%thread] %highlight(%-5level{color}) [%logger{0}:%line] - %msg%n"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${LOG_PATTERN}</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE" />
</root>
</configuration>
로그 패턴을 분석해보면 다음과 같은 구성 요소로 되어 있다
패턴 | 설명 |
%d{yy-MM-dd HH:mm:ss} | 로그가 기록된 날짜와 시간을 지정 (연도(2자리), 월, 일, 시, 분, 초 형식) |
%thread | 로그가 기록된 스레드 이름을 표시 |
%highlight(%-5level{color}) | 로그 레벨을 설정하며, color 옵션을 사용하여 로그 레벨에 따라 색상을 다르게 표시. %-5level은 로그 레벨을 왼쪽 정렬하고, 5자리를 차지하도록 설정 |
%logger{0}:%line | 로그를 발생시킨 로거의 이름과 로그가 발생한 소스 코드의 라인 번호를 표시 {0}은 로거 이름을 전체로 표시하는 것이고, :%line은 라인 번호를 표시 |
%msg | 실제 로그 메시지 표시 |
3. 로그 파일 관리
파일 롤링: 로그 파일의 크기나 날짜에 따라 자동으로 새로운 로그 파일로 롤링할 수 있어, 로그 파일이 너무 커지는 것을 방지할 수 있어 디스크 공간 관리에 도움이 된다.
아카이빙: 오래된 로그를 아카이브하거나 삭제하여 서버의 성능을 유지할 수 있다.
이번 글을 쓴 핵심적인 이유이다. AWS Code Pipeline으로 CI/CD를 진행하던 중 알 수 없는 이유로 CodeDeploy에서 배포 오류가 발생했다.
파이프 라인에서 빌드 프로세스,애플리케이션을 실행하는 스크립트 등 설정값은 문제가 없었다. 정확히는 deploy.log에서 배포 중 먹통 현상이 발생한 것이다. 혹시 메모리가 가득찬게 아닐까 df -h로 서버의 메모리 사용량을 확인해보니 로그파일 사이즈로 용량이 가득차 있었다.
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/${hostName}-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <!-- 파일 이름 패턴 -->
<maxFileSize>500MB</maxFileSize> <!-- 최대 파일 크기를 500MB로 설정 -->
<maxHistory>7</maxHistory> <!-- 최대 보관 일수 -->
<totalSizeCap>2GB</totalSizeCap> <!-- 총 로그 파일 크기 제한을 2GB로 설정 -->
</rollingPolicy>
%d{yyyy-MM-dd}: 매일 자정에 로그 파일이 롤링 (만약 시간 단위로 롤링하고 싶다면, %d{yyyy-MM-dd_HH}와 같이 설정)
각 로그 파일의 최대 크기를 500MB로 설정하여 이 크기를 초과하면 새로운 로그 파일이 생성된다. 총 로그 파일 크기를 2GB로 설정하여, 총 크기가 이 값을 초과하지 않도록 관리한다. 총 크기가 2GB를 초과하게 되면, 가장 오래된 로그 파일부터 삭제하여 새로운 로그 파일을 생성할 수 있는 공간을 만든다. 이 과정은 롤링 정책에 따라 이루어지며, 지정된 최대 보관 일수(maxHistory)를 초과한 파일이 우선적으로 삭제된다.
테스트 해본 결과는 아래와 같다.
a. 로그 파일 생성 및 롤링
새로운 로그 파일이 생성될 때마다 각 파일의 크기가 최대 500MB에 도달하면 롤링이 발생한다. 예를 들어, app-2024-12-01.0.log, app-2024-12-01.1.log, app-2024-12-02.log, ... ,app-2024-12-09.log 등의 파일이 생성되었다.
b. 총 파일 용량 초과
만약 로그 파일이 계속해서 생성되어 총 파일 용량이 2.5GB에 도달하였다.
c. 파일 삭제 및 관리
총 파일 용량이 2GB를 초과할 경우, 가장 오래된 로그 파일(app-2024-12-01.0.log)부터 삭제하여 공간을 확보한다. 이때 삭제되는 파일은 7일(maxHistory)이 지난 파일이다.
뿐만 아니라, 패키지 별 로그 레벨과 앱렌더를 설정하여 패키지에서 발생하는 로그를 쉽게 모니터링하고, 문제가 발생했을 때 신속하게 원인을 파악할 수 있다.
<!-- SQL 로그 설정 -->
<logger name="org.hibernate.SQL" level="ERROR" additivity="false">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="SQL_FILE"/>
</logger>
<logger name="org.hibernate.type.descriptor.sql.BasicTypeDescriptor" level="ERROR" additivity="false">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="SQL_FILE"/>
</logger>
<logger name="org.hibernate.type" level="ERROR" additivity="false">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="SQL_FILE"/>
</logger>
<!-- SpringFramework 로그 설정 -->
<logger name="org.springframework" level="INFO" additivity="false">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="ERROR"/>
</logger>
<!-- SpringBatch 로그 설정 -->
<logger name="org.springframework.batch" level="INFO" additivity="false">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="ERROR"/>
</logger>
4. 중앙 집중식 로깅
로그 수집: 클라우드 환경에서는 여러 서비스의 로그를 중앙에서 수집하고 분석할 수 있다. 로그백과 같은 로깅 프레임워크를 사용하면, 로그를 특정 위치(ELK 등)로 전송하여 분석할 수 있다.
모니터링 및 알림: 로그의 특정 패턴이나 오류를 모니터링하고, 이를 기반으로 알림을 설정하여 즉각적인 대응을 할 수 있다.
Logback 적용 중 발생했던 문제
1. 롤링 파일이 생성되지 않음
<file>과 <fileNamePattern>이 동일하게 설정되어 있어, 기본 로그 파일(batch.log)만 생성되고, 롤링 파일은 만들어지지 않았다. 즉, 롤링 정책이 작동하지 않았던 것이다.
롤링 파일을 생성하려면 <fileNamePattern>을 통해 날짜나 인덱스가 포함된 별도의 파일 이름을 정의해야 한다. 예를 들어, batch-%d{yyyy-MM-dd}.log와 같은 형식으로 설정하면 일 단위로 롤링 파일이 생성된다.
2. LOG_PATH 값이 정의되지 않음
log.config.path_IS_UNDEFIND라는 에러는 LOG_PATH 변수가 정의되지 않았거나 Logback 설정 파일이 이를 찾을 수 없기 때문에 발생하였다.
Spring Boot는 logback-spring.xml 파일을 먼저 로드하며, 이 파일에서 필요한 변수들이 정의되지 않으면 로그 설정이 실패하거나, 로그가 생성되지 않는 등의 문제가 발생한다.
# logback-dev.properties
log.config.path=/home/ec2-user
log.config.filename=hama-batch
# logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds">
<springProfile name="dev">
<property resource="logback-dev.properties"/>
</springProfile>
<springProperty scope="context" name="LOG_LEVEL" source="logging.level.root"/>
<property name="LOG_PATH" value="${log.config.path}"/>
<property name="LOG_FILE_NAME" value="${log.config.filename}"/>
...
</configuration>
***
directory 경로
resources-dev
├── application-dev.yml
├── logback-dev.properties
└── logback-spring.xml
'Spring' 카테고리의 다른 글
[Spring] Spring Security Filter 예외 핸들링 (0) | 2024.12.14 |
---|