흔히 사용하는 System.out.println()은 리소스를 많이 사용해 성능에 악영향을 끼친다.
Logger는 클래스의 이름, 시간, logging level 등의 정보를 제공한다.
| 항목 | 세부 내용 |
|---|---|
| Error | 메시지, 스택 추적, 에러 발생했을 때 애플리케이션이 실행하고 있던 작업 |
| Debugging | 디버깅시 필요한 세부 추적 정보 - 적용되는 변수 값, 메서드 등 실행에 대한 세부 정보 |
| 주요 이벤트 | 로그에 저장하고 싶은 중요 이벤트 - 엔티티 생성, 유저 로그인 성공, 작업 실행 등 |
| 기록 위치 | 세부 내용 |
|---|---|
| 콘솔 | 직관적 - 애플리케이션 종료 혹은 콘솔 버퍼를 초과하면 내용이 휘발될 수 있음 |
| 파일 | 로그가 휘발되지 않고 저장됨 - 눈으로 읽긴 쉽지만 프로그래밍처럼 패턴화 된 방식으로 필터링 해보기에는 다른 방법보다 어려움이 따름 |
| 이메일/문자 (SMTP/SMS) | 즉시 조치를 취해야 하는 등의 심각한 오류나 이벤트 시에는 관리자에게 알림이 가도록 설정 |
| 데이터베이스 | 로그 필터링이 쉽고 효율적 - 파일보다 기록 속도가 느리고 로깅 양이 많을 때 부하가 발생할 수 있지만 NoSQL 데이터베이스(MongoDB 등)에 저장한다면 대부분의 문제가 해결됨 |
로그를 파일에 기록할 때는 파티션을 따로 나누어서 저장하는 것이 좋다.
서비스를 배포했을 때 생성되는 로그의 용량은 상당히 크기 때문에 서비스하는 공간과 다른 영역에 저장해야 한다.
로그 내용에 따라서 log level을 구분 할 수 있다.
TRACE < DEBUG < INFO < WARN < ERROR
위 항목 처럼 Error가 가장 높은 레벨을 갖고 Trace가 가장 낮은 레벨을 갖는다.
로그를 작성할 때 이와 같은 레벨을 설정하여 원하는 로그만 출력시킬 수 있다.
log.info(...);
가령 위와 같이 log레벨을 INFO로 설정했을 때, INFO의 하위 레벨인 TRACE, DEBUG 레벨은 무시 되고, 상위레벨인 DEBUG, TRACE와 자기 자신인 INFO 레벨만 출력된다.
| 항목 | 설명 |
|---|---|
| ERROR | 즉시 대응해야 할 레벨 대응하지 않을 경우, 애플리케이션 동작 중지 등 심각한 장애를 겪을 수 있음 |
| WARN | 상황에 따라 잠재적으로 위험할 수 있을 때 (예외 처리 등) |
| INFO | 로그에 저장하고 싶은 중요 애플리케이션 이벤트 (운영 참고 정보) |
| DEBUG | 개발 단계에서 사용 디버깅이 가능하도록 상세한 내용이 출력 |
| TRACE | 개발 단계에서 사용 DEBUG 레벨보다 상세하며 모든 레벨 로그가 출력 |

Simple Logging Facade For Java
Spring에서 다양한 logging 관련 라이브러리들을 하나의 통일된 방식으로 사용할 수 있는 방법을 제공한다.

위 그림과 같이 logback, log4j, java.utill.logging 등의 라이브러리들을 SLF4J에 바인딩시켜 사용할 수 있다.
Facade Pattern이란?
복잡한 클래스 라이브러리에 대해 사용하기 편하게 간편한 인터페이스를 구성하기 위한 구조 패턴
즉, 복잡한 클래스들을 재정리하여 하나의 인터페이스 만들어둔 것
Java에서 가장 많이 사용되었던 log4j의 후속버전으로 log4j의 개선된 버전으로 볼 수 있다.
SLF4J를 사용해서 로깅을 할 때, 실제 로깅 작업은 구현체인 logback이 처리한다.
application.properties 파일에서 간단히 설정하는 방법이 있고 logback-spring.xml 파일을 만들어 세부 설정하는 방법이 있다.
logging.level.root=warn
logging.level.org.springframework.web=debug
logging.level.org.hibernate=error
위와 같이 설정 난이도가 비교적 쉽지만 세부적인 설정이 불편하다
Appender 영역, Encoder 영역, Root 영역으로 나뉘어 설정한다.
Log의 형태 및 어디에 출력할지 설정하기 위한 영역
<appender name="INFO_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter. Threshold Filter">
<level>INFO</level>
</filter>
<file>${logdir}/${moduleld}/${logback)/info_${type}.log</file>
<append>true</append>
<rolling Policy class="ch.qos.logback.core.rolling. TimeBased Rolling Policy">
<fileNamePattern>${logdir}/${moduleid}/${logback)/info_${type}.%d{yyyy-MM-dd}.gz</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%thread] %logger %msg%n</pattern>
</encoder>
</appender>
대표적인 Appender 형식
Appender 내에 포함되는 항목이며, pattern을 사용하여 원하는 형시긍로 로그를 표현할 수 있다.
<encoder>
<pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%thread] %logger %msg%n</pattern>
</encoder>
설정한 Appender를 참조하여 로그의 레벨을 설정하는 영역이다.
root는 전역 설정이며, 지역 설정을 하기 위해서는 logger를 사용해야한다.
<root level="DEBUG">
<appender-ref ref="INFO_LOG"/>
</root>
| pattern | 설명 |
|---|---|
%Logger{length} | Logger Name |
%-5level | 로그 레벨, -5는 출력의 고정폭 값 |
%msg | 로그 메세지 영역 (==%message) |
${PID:-} | 프로세스 id |
%d | 로그 기록 시간 |
%p | 로깅 레벨 |
%F | 로깅이 발생한 프로그램 파일명 |
%M | 로깅이 발생한 메소드의 이름 |
%1 | 로깅이 발생한 호출지의 정보 |
%L | 로깅이 발생한 호출지의 라인 수 |
%thread | 현재 Thread 명 |
%t | 로깅이 발생한 Thread 명 |
%c | 로깅이 발생한 카테고리 |
%C | 로깅이 발생한 클래스 명 |
%m | 로그 메시지 |
%n | 줄바꿈 |
%% | % 출력 |
%r | 어플리케이션 실행 후 로깅이 발생한 시점까지의 시간 |