티스토리 뷰
실무에서는 우리가 흔히 사용하는 System.out.println()과 같은 시스템 콘솔을 사용해서 필요한 정보를 출력하거나 디버깅하지 않고, 별도의 logging 라이브러리를 사용하여 디버깅이나 타임스탬프 등 정해진 양식에 맞추어 화면 상이나 파일 로그를 남길 목적으로 사용합니다.
그럼, 본격적으로 logging에 대해 알아보겠습니다.
logging의 종류
logging 관련 프레임워크는 대표적으로 log4j, logback, log4j2 그리고 그것을 통합하여 인터페이스로 제공하는 SLF4J 라이브러리가 있습니다.
log4j → logback → log4j2 순으로 등장하였으며, logback과 log4j2는 둘다 log4j를 기반으로 하고 있기 때문에 설정이나 사용 방법이 유사합니다.
log4j는 2015년 8월 5일 이후로 지원이 종료되었기 때문에 이를 제외하고 알아보겠습니다.
logback
- log4j 이후에 출시되어 보다 향상되고 가장 널리 사용되고 있는 java logging 프레임 워크 중 하나입니다.
- slf4j의 구현체로써 동작하기에 Spring Boot환경에서는 spring-boot-starter-web 안에 spring-boot-starter-logging의 logback이 기본적으로 포함되어 있어 별다른 dependency 추가 없이 사용할 수 있습니다.
log4j2
- 가장 최신에 나온 logging 프레임워크로 Apache log4j의 다음 버전입니다.
- logback 처럼 필터링 기능과 자동 리로딩을 지원합니다.
- logback과 가장 큰 차이는 Multi Thread 환경에서 비동기 로거(Async Logger)의 경우 다른 logging 프레임워크보다 처리량이 훨씬 많고, 대기시간이 훨씬 짧습니다.
- java8 부터 도입된 람다식을 지원합니다.
아래의 이미지는 Multi Thread 환경에서 logging 프레임워크의 성능을 비교한 차트입니다.
Spring Boot에서의 logging 사용 방법
그럼 이제 코드를 통해서 어떻게 logging을 사용하고 어떻게 이루어져 있는지 한번 살펴보겠습니다.
package springboot.MVCBasic.basic;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LogTestController {
private final Logger log = LoggerFactory.getLogger(getClass());
@GetMapping("log-test")
public String logTest() {
String name = "Spring";
log.trace("trace log = {}", name);
log.debug("debug log = {}", name);
log.info("info log = {}", name);
log.warn("warn log = {}", name);
log.error("error log = {}", name);
return "ok";
}
}
우선 log를 사용하기 위해선 먼저 선언을 해주고, 선언된 참조 변수를 통해 사용해 주면 되겠습니다.
log의 종류에는 trace, debug, info, warn, error 이 있는데 각각의 의미는 아래 표와 같습니다. (보통 개발 서버는 debug, 운영 서버는 info로 사용합니다.)
Level | Color | Mean |
1. error | Red | 사용자 요청을 처리하는 중 발생한 문제 |
2. warn | Yellow | 처리 가능한 문제이지만, 향후 시스템 에러의 원인이 될 수 있는 문제 |
3. info | Green | 로그인이나 상태 변경과 같은 정보성 메시지 |
4. debug | Green | 개발시 디버깅 목적으로 출력하는 메시지 |
5. trace | Green | debug 보다 좀 더 상세한 메세지 |
특정 로그 레벨을 지정하면 해당 로그 레벨의 상위 우선순위 로그가 모두 출력됩니다. 예를 들어 특정 로그 레벨을 info로 지정하게 되면 info, warn, error 로그가 전부 출력됩니다.
즉, 특정 로그 레벨이 info라면 아래와 같이 출력됩니다.
2022-03-21 17:38:15.537 INFO 31713 --- [nio-8080-exec-1] LogService
2022-03-21 17:38:15.537 ERROR 31713 --- [nio-8080-exec-1] LogService
2022-03-21 17:38:15.537 WARN 31713 --- [nio-8080-exec-1] LogService
로그 레벨의 default 값은 info이며 로그 레벨을 설정하는 방법은 아래와 같습니다.
1. application.yml에서 지정할 때
# 패키지와 그 하위 로그 레벨 설정 (디폴트 값은 info)
logging:
level:
springboot.MVCBasic: debug #springboot.MVCBasic 패키지의 하위 레벨 설정
2. application.properties에서 설정할 때
#전체 로그 레벨 설정(기본 info)
logging.level.root=info
#hello.springmvc 패키지와 그 하위 로그 레벨 설정
logging.level.hello.springmvc=debug
우리는 위 예제 코드에서 private final Logger log = LoggerFactory.getLogger(getClass()); 를 선언해 준 것을 떠올릴 수 있습니다. 사실 Lombok의 @slf4j 어노테이션만 선언해 준다면 아래와 같이 별도로 선언해주지 않고도 사용할 수 있습니다.
package springboot.MVCBasic.basic;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
public class LogTestController {
@GetMapping("log-test")
public String logTest() {
String name = "Spring";
log.trace("trace log = {}", name);
log.debug("debug log = {}", name);
log.info("info log = {}", name);
log.warn("warn log = {}", name);
log.error("error log = {}", name);
return "ok";
}
}
코드를 보다 보면 log.trace("trace log = {}", name); 처럼 사용하지 않고 log.trace("trace log" + name);로 사용하면 안되나?라고 의문이 드실 수도 있습니다. 결론부터 말씀드리자면, 후자의 방식은 성능이 좋지 않습니다.
그 이유는 후자의 방식은 logging level에 포함되어 있지 않아서 출력할 필요가 없음에도 일단 문자열을 서로 더하는 연산이 수행되기 때문에 비용면에서 손해를 보기 때문입니다.
따라서, 전자의 방식으로 사용하는 것을 권장합니다.
System.out.println()을 사용하지 않고 logging을 사용하는 이유
그렇다면 왜 굳이 println을 사용하지 않고 logging을 이용할까요? 그 이유는 logging을 사용했을 때 아래와 같은 장점이 있기 때문입니다.
logging을 사용했을 때의 장점
- 스레드 정보, 클래스 이름 같은 부가 정보를 함께 볼 수 있고, 출력 모양을 조정할 수 있습니다.
- Log level에 따라 개발 서버에서는 모든 로그를 출력하고, 운영 서버에서는 출력하지 않는 등 로그를 상황에 맞게 조절할 수 있습니다.
- 시스템 아웃 콘솔에만 출력하는 것이 아니라, 파일이나 네트워크 등 로그를 별도의 위치에 남길 수 있습니다.
- 특히, 파일로 남길 때에는 일별, 특정 용량에 따라 로그를 분할하는 것도 가능합니다.
- println을 썼을 때보다 내부 버퍼링, 멀티 스레드 등의 환경에서 훨씬 좋습니다.
참고
https://dkswnkk.tistory.com/445
'Spring' 카테고리의 다른 글
[Spring]@RequestBody, @RequestParam, @ModelAttribute의 차이 (0) | 2024.09.12 |
---|---|
[Spring]DAO와 DTO, VO (0) | 2024.09.12 |
[Spring]@No/All/RequiredArgsConstructor (0) | 2024.09.12 |
[Spring Data JPA]JPA Repository란? (+ 사용법, Method) (0) | 2024.09.10 |
[Spring Data JPA]JPA 복합키 사용하기 (0) | 2024.09.10 |
- Total
- Today
- Yesterday