System.out.println 이 아닌 SLF4J, Logback 등을 이용한 logger를 사용해야 하는 이유에 대해 알아보자

 

대충 요약 : 그냥 System.out.println 쓰지 말고 logger를 써라

 

 

3줄 요약 

System.out은 속도가 느리다.

System.out은 로깅 레벨을 조절할 수 없다.

logger 는 별도의 기능들을 더 제공한다.

 

자세히.

1. 속도

System.out 은 내부 버퍼링과, 멀티 쓰레드 등의 환경에 따라 로그를 모아서 출력하는 등의 상황이 발생한다. 물론 logger 또한 내부 버퍼링이 있지만 성능 최적화가 조금 더 잘 되어있다 

(자세히 : 링크 TODO )

System.out.println("sysout");
System.err.println("syserr");

logger.trace("LOG TRACE");
logger.debug("LOG DEBUG");
logger.info( "LOG INFO");
logger.warn( "LOG WARN");
logger.error("LOG ERROR");

 

2. 로그 레벨 조절

System.out.println (혹은 System.err.println) 은 로그 레벨을 조절할 수 없는 반면

logger는 기본적으로 5개의 로그 레벨을 지원하므로 필요에 따라 다양하게 쓸 수 있으며 이 로그 레벨을 별도의 어플리케이션 코드를 바꾸지 않고 외부에서 설정을 바꿔서 로그 레벨 조절이 가능하다. 이를 활용하여 특정 상황에 맞는 로그를 출력할 수 있다.

 

3. 로그 파일 관리

추가로 수많은 로그가 남는 시스템에서는 로그 파일 크기로 인해 서비스 장애가 발생할 수 있는데

logger에서는 날짜별 로그파일 분리, 파일 크기별 로파일 분리 등을 지원한다.

 

 

 

logger 사용의 올바른 예시

아래의 코드에서 위 두줄과 아래 코드 방식마다 결과의 차이가 있을까? 결론부터 말하자면 "차이가 있을 수 있다." 이다.

String name = "Chris";
String id = "chris1108";

// 1. noncompliant
logger.info("name = " + name);
logger.debug("id = " + id);

// 2. compliant 
if ( logger.isInfoEnabled() ) {
	logger.info("name = " + name);
}
if ( logger.isDebugEnabled() ){
	logger.debug("id = " + id);
}

// 3. compliant 
logger.info("name = {}", name);
logger.debug("id = {}", id);

먼저 1번을 보자

로그 레벨이 DEBUG 일 경우에는 문제가 발생하지 않고 DEBUG 보다 높은 INFO, WARN, ERROR 일 경우에 문제가 발생한다.

java의 연산 순서상 logger.debug 함수로 String을 전달하기 전에 "id = " + id 연산을 처리하게 된다.

log 내부에서는 로그 레벨이 INFO 이기 때문에 별다른 로그 출력을 하지 않게 되겠지만 결과적으로 "id = " 와 id를 더하는 연산은 쓸모없는 냥비가 되는 셈이다.

 

그래서 아래의 2,3번 방법을 사용할 수 있다.

로그 레벨이 DEBUG 일 경우에만 "id = " + id 연산을 하게 하여 불필요한 연산을 줄일 수 있다.

 

여기서 더 나아가 3번의 방법을 사용하면

logger 내부에 "id = {}" 와 id 두 개의 String 을 parameter로 전달하고 내부에서 필요할 경우에만 연산을 처리해 주고 코드의 가독성 또한 높일 수 있다.

+ Recent posts