레벨2 미션에서 예외 처리를 할 때, 예측하지 못한 서버 오류가 발생할 경우에는 로그를 남겨주는 방식으로 처리하고 있었다.
하지만 '로그를 남긴다'는 게 어떤 행위인지, 또 어떤 도구를 사용해 할 수 있는지 잘 알지 못하고 있다는 것을 깨달았다.
그래서 이번 기회에 간단히라도 정리해보려고 한다.
Log와 Logging
- 로그(log)는 컴퓨터의 처리 내용이나, 이용 상황을 시간의 흐름에 따라 기록한 것을 말한다.
- 어플리케이션에서의 로그는 실행 중 발생하는 다양한 이벤트에 대한 기록이라고 할 수 있다.
- Logging은 위와 같이 로그를 남기는 행위를 말한다.
System.out.println()과 Logger의 차이
- System.out.println()은 성능이 떨어진다.
- System.out.println()과 달리 Logger로는 로그를 별도의 파일로 남길 수 있고, 보다 체계적으로 파일을 구성할 수 있다.
- 로그를 별도의 파일로 저장하면, 오류 관리 및 디버깅이 쉽다.
- 별도의 파일 뿐만 아니라, 다른 시스템 및 어플리케이션에 로그를 전송할 수도 있다.
- (특정 정책에 따라 파일을 롤링하는 메커니즘을 제공한다고 하는데 이 부분은 아직 잘 모르겠다)
- Logging을 위한 Logger 프레임워크들은 로그 레벨 제어를 제공한다.
- 항상 모든 로그를 보여준다면 어플리케이션에 지연 시간이 늘어날 것이다.
- 레벨 제어를 해주면 언제 어디서 어떤 정보를 출력할지 쉽게 설정할 수 있다.
Java의 주요 Logger 프레임워크
- java.util.logging
- JDK 1.4부터 포함된 로깅 API
- 서블릿 컨테이너 또는 어플리케이션 서버로 어플리케이션을 배포하면, 자바 유틸 로깅은 어플리케이션의 로그에 남지 않는다.
- 따라서 미션에서와 같은 Spring 프레임워크 환경에서는 이 API를 사용해도 로그가 안남는다.
- Log4j2
- Apache에서 제공하는 로깅 API
- Slf4j 인터페이스, 구현체 Logback
- Slf4j는 원하는 로깅 프레임워크를 사용할 수 있도록, 추상 레이어를 제공하는 인터페이스
- Spring Boot에서는 Slf4j의 구현체인 Logback을 기본 Logger 프레임워크로 사용한다.
- spring-boot-starter를 사용하는 경우 기본적으로 Logback을 로깅에 사용한다. (따로 의존성 등록할 필요 x)
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class.getName());
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleException(Exception exception) {
logger.error(exception.getMessage());
logger.error(Arrays.toString(exception.getStackTrace()));
return ResponseEntity.internalServerError().body(new ErrorResponse("internal server error"));
}
또, Lombok 라이브러리를 사용하면 클래스 위에 @Slf4j 어노테이션만 붙여도 Logger 객체를 생성한 것처럼 사용할 수 있다.
로그 설정과 파일로 기록하기
그런데 나는 Logger를 쓰면서도 여전히 콘솔창을 통해서만 로그를 확인했다.
로그를 파일에 남기는 건 어떻게 하는 것일까?
먼저 로그 설정을 어떻게 하는지 보자면,
application.properties처럼 resources/ 하위 경로에 정해진 이름의 파일을 사용하면 된다.
지하철 미션에서 제공된 파일 중 logback-spring.xml
이 Logback의 로그 설정을 해주는 파일이다.
공식문서에 따르면, logback.xml 보다는 logback-spring.xml 와 같이 -spring 구성의 파일을 사용하기를 권장한다. 전자는 Spring이 구동되기 이전에 적용되고, 후자는 이후에 적용되기 때문에 후자의 경우 application.properteis에 있는 값들을 불러올 수 있다.
이제 이 파일에서 log의 형태를 설정하는, <appender>
의 값을 원하는 대로 정의해주면 된다.
미션에서 제공된 파일에서는 콘솔로 로그를 남기기 때문에 class="ch.qos.logback.core.ConsoleAppender"
로 설정되어있다.
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%n###### HTTP Request ######%n%fullRequest%n###### HTTP Response ######%n%fullResponse%n%n</pattern>
</encoder>
</appender>
<appender-ref ref="STDOUT" />
</configuration>
이를 ch.qos.logback.core.FileAppender
또는 ch.qos.logback.core.RollingFileAppender
로 설정하면, 로그를 파일에 기록할 수 있는 것이다.
아래와 같이 설정을 바꾸고 POSTMAN으로 잘못된 요청을 보내보았다.
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.FileAppender">
<file>test.log</file>
<immediateFlush>true</immediateFlush>
<encoder>
<pattern>%n###### HTTP Request ######%n%fullRequest%n###### HTTP Response ######%n%fullResponse%n%n
</pattern>
</encoder>
</appender>
<root level="ERROR">
<appender-ref ref="FILE"/>
</root>
<appender-ref ref="STDOUT"/>
</configuration>
프로젝트의 상위 위치에 test.log 파일이 생기고, 위와 같이 기록이 남아있음을 확인할 수 있다.
그 외에도 로그를 메일로 발송하거나 DB에 기록하는 Appender도 존재한다.
참고자료
https://www.baeldung.com/java-logging-intro
https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.logging
https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.logging.custom-log-configuration
https://logback.qos.ch/manual/appenders.html#FileAppender
https://recordsoflife.tistory.com/281
'공부 > Spring' 카테고리의 다른 글
Jpa 이벤트를 사용해 일관성 있는 시간 정보 관리하기 (0) | 2023.10.15 |
---|---|
성능 향상을 위한 Hikari Connection Pool 설정 for MySQL (1) (0) | 2023.09.29 |
[문제 해결] @AutoConfigureTestDatabase 설정으로 @JdbcTest에서 원하는 DB 사용하기 (0) | 2023.05.07 |
@RequestBody 사용을 위한 DTO의 조건을 정리해보자 (0) | 2023.04.24 |
@Service, @Repository 사용 이유에 대한 고찰 + PSA (0) | 2023.04.20 |