자바 java.util.logging vs log4j vs slf4j? 어떤 것을 사용해야 할까?

시작하기에 앞서 일단 정답은 없다. 대학교 때 교수님께서 하신 말씀을 인용하자면 it depends. 모든 질문의 답은 상황에 따라 다르다.

logging이란 정보를 기록하는 것을 말한다. 시스템을 모니터 하는 대상에게 필요한 정보가 될 수도 있고 디버깅을 하는 개발자에게 필요한 정보가 될 수도 있다. 때문에 로깅은 프로그램 운영과 관리에 큰 영향을 미칠 수 있다.

구글링으로 알아본 자바에 여러 로깅 라이브러리들이 서로 어떻게 다른지, 그리고 어떤 것을 사용하면 좋을지에 대한 정보를 간단히 적어보았다.




java.util.logging

자바가 1.4부터 기본적으로 제공하는 로깅 유틸리티이다. 

7개의 레벨로 구분된 로깅을 제공한다. 

SEVERE (highest value)
WARNING
INFO
CONFIG
FINE
FINER
FINEST (lowest value)

선언 예제

private static final Logger logger = Logger.getLogger(MyApplication.class.getName());

사용 예제

logger.info("new transaction has been created");
logger.log(Level.FINE, "processing {0} entries in loop", list.size());

장점

원하는 기능이 아주 기본적인 수준이라면 외부 라이브러리 사용 없이 로깅이 가능하다. 


단점

  • 자바 1.4의 시점에 이미 잘 만들어진 log4j가 존재하였고 널리 쓰이고 있었다. 굳이 기존 log4j 사용자들이 jul (java.util.logging) 으로 갈아탈 이유가 없었다.
  • 다른 라이브러리와 비교했을 때 퍼포먼스 (속도) 가 느리다.
  • Predefine 된 레벨의 개념이 명확하지 않다. Debug의 뜻으로 사용된 FINE이 무엇을 뜻하는지 처음 보면 알 수 있을까? FINE vs FINER vs FINEST의 차이점을 쉽게 구분할 수 없다.
  • 나만의 custom 레벨을 만들면 메모리 누수가 일어난다.
  • 타 라이브러리에 비해 기능이 부족하다.
  • 유연하지 않다.


log4j

참고로 2020년 현시점에서 다음 버전인 log4j2가 나왔기 때문에 새로운 프로젝트라면 log4j2를 사용하는 게 좋다. log4j2는 계속 기능 추가와 유지보수가 되고 있는 반면 log4j는 보다 적은 유지보수만을 가지고 있고 시간이 지남에 따라 점점 줄어들 것이다. 하지만 이미 log4j가 적용되어 있다면 굳이 업그레이드를 할 필요는 없다. 


log4j는 3개의 컴포넌트들로 이루어져 있다.
  • logger: 데이터를 기록하는 역할
  • appender: 데이터를 어디에 기록할지 정하는 역할 (파일, 콘솔, jdbc, smtp, 등)
  • layout: 데이터를 어떤 스타일로 기록할지 정하는 역할

기능

몇 개만 뽑으면
  • thread safe 하다.
  • 퍼포먼스가 최적화되어있다.
  • 여러 종류의 appender를 지원한다.
  • jul에 비해 명확한 기준의 레벨을 가지고 있다: ALL, TRACE, DEBUG, INFO, WARN, ERROR and FATAL

jul의 단점의 대부분을 보완한 것이 log4j라고 볼 수 있겠다. 특별히 단점을 찾지는 못하였다. 


선언 예제

private static Logger logger = LogManager.getLogger(MyApplication.class);



사용 예제

logger.info("new transaction has been created");
logger.debug("processing {0} entries in loop", list.size());





slf4j

slf4j와 다른 라이브러리의 가장 큰 차이점은 slf4j는 wrapper라는 것이다. 

slf4j를 사용하여 설정에 따라 다른 로깅 라이브러리를 사용할 수 있게 된다.

 Application code -> log4j -> 기록 

이던 것이

 Application code -> slf4j (wrapper) -> log4j (혹은 log4j, logback, 등) 

와 같이 2 티어로 변경되면서 원하는 destination (implementation) 을 사용할 수 있게 해 준다. 때문에 jul을 쓰다가 log4j로 갈아타는 등 마이그레이션 프로세스가 간단해진다. 

그래서 대부분 프로젝트는 slf4j의 사용을 추천한다. 

slf4j의 인기가 높아지다 보니 slf4j 자체에도 로깅 implementation을 포함하기도 했다. 




추천

그럼 내 프로젝트에 적용을 한다면
  • slf4j 사용할 것
  • Implementation은 logback이나 log4j2를 사용할 것
정도가 되겠다. 

logback이 다른 라이브러리보다 조금 더 핫 하며 log4j2가 조금 더 많은 기능을 제공한다.




레퍼런스

https://docs.oracle.com/javase/7/docs/api/java/util/logging/Level.html
https://stackoverflow.com/questions/11359187/why-not-use-java-util-logging
https://stackoverflow.com/questions/607863/do-you-find-java-util-logging-sufficient
https://www.tutorialspoint.com/log4j/log4j_overview.htm