본문 바로가기

언어/자바

Logback

Logback이란?

Logback is intended as a successor to the popular log4j project, picking up where log4j leaves off.

-> 로그백이란 slf4j 프로젝트 구현체이며, log4j를 대체하는 역할을 한다.

재밌게도 logback의 창시자인 Ceki Gülcü는 log4j의 창시자이기도 하다. log4j를 만들 때의 노하우를 통해 보다 좋은 것을 만들어낸 것이다.

 

 

Slf4j란?

The Simple Logging Facade for Java (SLF4J) serves as a simple facade or abstraction for various logging frameworks (e.g. java.util.logging, logback, log4j) allowing the end user to plug in the desired logging framework at deployment time.

-> slf4j는 자바를 위한 로그 프레임워크로, 파사드 패턴이 적용되어 있으며, 다양한 구현체를 위해 추상화되어 있다.

 

이러한 slf4j가 없다면, 특정 로깅 라이브러리를 사용하는데 해당 라이브러리에 치명적인 버그가 있어서 다른 라이브러리로 교체해야할 때 관련된 모든 코드를 수정해야할 수도 있다. 왜냐하면 각 로깅라이브러리의 인터페이스와 구현은 제각각 일 수 있기 때문이다.

 

반면에 slf4j를 사용하면 구현체를 어플리케이션 레벨의 코드 수정없이 구현체를 쉽게 변경할 수 있다. gradle, maven과 같은 툴을 사용한다면, 기존 구현체의 디펜던시를 제거하고 사용하고자 하는 구현체를 디펜던시 걸어두면 말끔하게 바뀐 구현체로 어플리케이션이 구동될 수 있다.

 

이게 가능한 이유는 Slf4j에서 lazy init방식으로 로거를 만들 때 class path를 뒤져서 구현체를 알아서 찾아내기 때문이다.

(코드 참고: org.slf4j.LoggerFactory::getILoggerFactory, org.slf4j.LoggerFactory::performInitialization )

 

logback의 구성

logback의 주요 컴포넌트는 크게 Appender, Logger, Layout으로 나뉜다. (http://logback.qos.ch/manual/architecture.html)

Logger는 org.slf4j.Logger의 구현체로, 트리 구조를 이룬다. 즉, 자식Logger와 부모 Logger를 가질 수 있다. Logger를 계층구조로 엮고 관리하는 역할은 LoggerContext에 있다. 각 Logger는 LoggerContext에 속한다.

각 Logger는 이름(name)을 가지고 있으며 로깅 level과 appender를 가지고 있다.

 

Appender는 실질적인 로그 이벤트를 처리하는 역할로, FileAppender, ConsoleAppender 등이 있다.

대표적인 Appender로 RollingFileAppender를 꼽을 수 있다. 실제 웹서비스는 일단위로 로그를 저장하는 경우가 많고 이 때 파일을 일 단위로 바꿔가며(rolling) 기록하는 역할을 위해 RollingFileAppender를 사용한다.

 

Layout 로그의 포맷을 결정하는 역할이다.

 

Logger

 Logger는 slf4j logger의 구현체로, 로그를 남기기위해 사용하는 클래스이다. 일반적으로 어플리케이션 코드에서 Appender, Layout은 구현체를 만들어 별도로 사용하지 않는다. Logger의 뒷편에서는, 로그를 남기기 위해 Appender와 Layout이 동원되고 개발자는 이 사실을 모르고 사용해도 된다. 이런게 고수준 추상화(facade)가 아닐까?

 

 Logger는 로그를 남겨달라는 메소드 (ex. info, warn, error) 등의 메소드가 호출되면, 자신이 허용하는 level을 확인하여 로그를 남겨도 되는지 판단한다. 로그를 남겨도 된다고 판단되면 appender에게 역할을 위임하여 로그를 남기도록 한다. (참고로 Logger의 임무를 대신 수행하는 Appender를 여러개 가지고 있을 수 있다.)

 

 이제는 Logger를 좀 더 깊게 알아보자. 앞서 말했듯이 Logger는 이름(name)을 가지고 있고 트리 구조로 구성된다. 재밌는 사실은, Logger는 이 이름으로 계층구조를 만든다 (항상 이름으로 만드는 것은 아니다). Logger의 이름은 case-sensitive하며 '.' (dot)을 기준으로 부모 자식을 구분할 수 있다. 공식문서의 설명을 보자.

 

Named Hierarchy

A logger is said to be an ancestor of another logger if its name followed by a dot is a prefix of the descendant logger name. A logger is said to be a parent of a child logger if there are no ancestors between itself and the descendant logger.

 

어플리케이션 레벨에서 Logger를 아래와 같은 방식으로 만든다.

private static final Logger logger = LoggerFactory.getLogger(MyClass.class);

혹은 이렇게도 만들 수 있다.

private static final Logger logger = LoggerFactory.getLogger("com.testtesttest.MyClass");

 

 결과적으로 getLogger는 이름으로 찾는다. class 객체를 넘기는 것도 이름으로 변환되어 이름으로 Logger를 찾아온다. 그런데 logback.xml에 모든 로거를 만들어두지 않는 이상, 특정 클래스 이름에 해당하는 Logger가 없을 수 있다. 이 때는 디폴트 로거가 동적으로 만들고 이름을 붙여준다(getLogger에 호출한 이름으로 붙여준다). 이렇게 클래스 이름으로 생성된 Logger는 '.'을 기준으로 부모 자식의 관계를 분리하여 결과적으로는 트리 구조로 구성된다.

 

 예시를 살펴보자. logback.xml을 아래와 같이 구성하고

코드는 이렇게 짰을 때 

 

로거의 구현체는 이렇게 구성된다. '.'을 기준으로 계층 구조를 이루는 것에 주목하라.

logback.xml 설정을 통해 만든 Root Logger와 com.nanostudio Logger에는 Level이 적혀있고, 디폴트로 만들어진 다른 Logger에는 Level이 null로 설정되어 있다.

 

 이는 자식 Logger는 부모 Logger의 설정을 상속받기 때문이다. Root Logger가 Info이상을 남기도록 level을 설정했지만 com.nanostudio.slf4j.Slf4j Logger의 가장 가까운 not default 부모는 com.nanostudio Logger다. 따라서 logger.debug로 로그가 남겨진다.

 

 Logger를 좀더 깊게 보기위해서 additivity 속성도 공부하면 좋다.

 

Logger는 여기까지 알아보자.

 

Appender

 Appender는 Logger가 발생하는 LoggingEvent를 전달받아서 실제로 로그를 남기는 역할을 한다. Appender의 특성에 따라 로그를 남기는 유형은 다를 수 있다. 예를 들어 ConsoleAppender는 콘솔에 로그를 남기고, FileAppender는 특정 파일에 로그를 남긴다. Sentry가 제공하는 SentryAppender는 로그를 Sentry 서버로 보내주는 역할을 한다. (굉장히 신선!!)

 

 하나의 Appender는 여러개의 Logger에 등록될 수 있다. (또한 하나의 Logger는 여러개의 Appender를 가질 수 있다.)

 

 이 중에서 웹 서비스에서 흔하게 사용되는 Appender는 RollingFileAppender다. 이 Appender는 로그파일을 사이즈, 혹은 특정 시간에 따라 교체하면서 (rolling) 로그를 기록한다. 따라서 로그파일을 특정 기준에 맞게 분할해서 관리할 수 있어서 할 수 있는 것이 많아진다. 보통 일 단위로 로그파일을 기록하고, 보관주기를 설정하여 n일 후의 로그파일은 자동삭제하는 등 편의기능이 여러가지가 있다.

 

 Appender의 구성은 아래와 같다.

Layout

Layout은 로그 포맷을 결정할 때 쓸 수 있다. 앞서 나왔던 logback.xml 설정파일에서 <rollingPolicy> 하위의 <fileNamePattern>에 지정한 설정은 Layout 구현체에 들어가게된다.

 

 

출처

http://logback.qos.ch/

https://ksyno3.tistory.com/14