스프링 부트에서의 로깅

스프링 부트에서 알아서로깅을 해주는데 어떻게 해주는 것일까 ?

스프링 캠프 백기선님의 스프링 부트 와 로깅 을 들으면서 정리한 페이지 입니다.

https://www.youtube.com/watch?v=o2-JaRD9qQE&t=907s

스프링 부트와 로깅

  • 스프링 부트는 JCL을 사용하여 로깅 코드를 작성
  • 스프링 부트 애플리케이션은 SLF4J를 사용한다.
  • 스프링 부트 애플리케이션은 Logback을 사용한다.
  • 원한다면 얼마든지 다른 로거를 사용 할 수 있다.

JCL (Jakarta Commons Logging)

org.apache.commons.logging.log

JCL을 사용할 때는 debug모드 일때만 사용할 수 있도록

if문을 사용해서 로깅을 했었음 .

예시

if(this.log.isDebugEnabled()){
  this.log.debug("Jakarta Commons Logging")
}

특징

  • 로깅 라이브러리가 아니라 로깅 추상화 라이브러리

  • 로깅 라이브러리 선택권은 애플리케이션 개발자의 것

  • 라이브러리나 프레임워크는 주로 로깅 추상화 라이브러리를 사용한다.

    LOG --> LOG4J

로거 추상화 라이브러리 어떻게 찾을 것인가 ?

JCL이 로깅 구현체를 찾는 방법

  • 설정 파일에서 찾기
  • 애플리케이션 클래스 패스에서 Log4J 구현체 찾아보기
  • 애플리케이션이 JDK 1.4에서 구동중인지 확인하기
  • 아무것도 못찾으면 기본 구현체 사용

JCL 사용시 겪을수 있는 클래스 로더 문제

http://articles.qos.ch/classloader.html

JCL을 사용 안하는이유

  • 자바 클래스로더의 기본 동작방식
    • getClass 등 classloader를 통해서 읽어오는데, deligation이 되어있다. 상위에서 먼저 찾아오고 이후에 없으면 기본 자기자신이 읽어올수 있는 클래스를 읽어온다.
  • 서블릿 컨테이너의 클래스로더 동작 방식
    • 클래스로더가 어떻게 동작해서 어떻게 읽어오는 스펙이 없다. 그리고 구현체(jetty,tomcat) 마다 각자 다 다르다.
    • JCL을 사용할때는 여러가지 classloader문제가 발생 할 수 있다.
    • 같은 클래스를 넣어뒀는데도 불구하고 casting을 할 수 없을 수도 있다.
    • 메모리 누수 문제 발생 할 수 도 있다.
  • JCL은 클래스로더에 의존적인 방법으로 구현체를 찾는다.

Spring은 의존성이 없다. 말은 즉 개발자가 어떤 것을 쓸지는 maven에 optional로 지원한다.

Spring에 JCL의 의존성은 가지고 온다. context.jar에서 가지고 온다.

springboot는 JCL의 의존성을 끊어 두었다.(https://spring.io/blog/2009/12/04/logging-dependencies-in-spring/)

Spring의 필수 로깅 종속성은 Jakarta Commons Logging API (JCL)입니다. JCL에 대해 컴파일하고 스프링 프레임 워크를 확장하는 클래스에 JCL 로그 객체를 표시합니다. 모든 버전의 Spring이 동일한 로깅 라이브러리를 사용하는 것이 중요합니다 .Spring을 확장하는 응용 프로그램과도 역 호환성이 유지되므로 마이그레이션이 쉽습니다.이를 수행하는 방법은 Spring의 모듈 중 하나가 커먼즈 로깅에 명시 적으로 의존하도록하는 것입니다. (JCL의 정식 구현) 다음 다른 모든 모듈을 컴파일 타임에 의존하도록하십시오. 예를 들어 Maven을 사용하고 커먼즈 로깅에 대한 종속성을 어디에서 선택했는지 궁금하다면 Spring에서, 특히 spring-core라는 중앙 모듈에서 가져온 것입니다.
Commons-Logging의 좋은 점은 응용 프로그램을 작동시키기 위해 다른 것이 필요하지 않다는 것입니다. 클래스 경로의 잘 알려진 위치에서 다른 로깅 프레임 워크를 찾고 런타임에 알 맞는 것으로 생각되는 프레임 워크를 사용합니다 (필요한 경우 어떤 프레임 워크인지 알 수 있음). 다른 것이 없다면 JDK (java.util.logging 또는 JUL)에서 아주 멋진 로그를 얻습니다. 대부분의 상황에서 Spring 응용 프로그램이 작동하고 콘솔에서 행복하게 로그에 기록되는 것이 중요합니다.
불행히도 커먼즈 로깅에 대한 최악의 점과 새로운 툴로 인기를 얻지 못한 것은 런타임 발견 알고리즘이기도합니다. 시계를 되돌리고 지금 새 프로젝트로 Spring을 시작할 수 있다면 다른 로깅 종속성을 사용합니다. 아마도 첫 번째 선택은 SLF4J (Simple Logging Facade for Java ) 일 것입니다.이 로깅 은 사람들이 애플리케이션에서 Spring과 함께 사용하는 다른 많은 도구에서도 사용됩니다.
공통 로깅을 해제하는 것은 쉽습니다. 런타임에 클래스 경로에 있지 않은지 확인하십시오. Maven 용어로 종속성을 제외하고 Spring 종속성이 선언되는 방식으로 한 번만 수행하면됩니다.

SLF4J

  • Simple Logging Facade For Java

  • 로깅 라이브러리를 런타임이 아닌 컴파일 시점에 의존성 정보를 판단하여 실행됨

    • dependency에 어떤것이 있으니까 어떤 것을 써야겠구나 하는 것을 결정함.
    • Dependency 설정을 잘해야한다.
  • 세가지 모듈(Bridging, API, Binding) 제공

    • SLF4J API

      • 로깅 인터페이스 : 그냥 껍데기 일 뿐
      • slf4j-api-{version}.jar
      • org.slf4j.Logger
      • Org.slf4j.LoggerFactory
        JCL 과는 달리 if문으로 별도 debug를 설정 하지 않아도 부하가 없다.
    • Binding

      • SLF4J api 인터페이스를 로깅 구현체로 연결
      • 어댑터 역할
        • 여러 로그로 연결 해주는 역할
        • logback, slf4j 의존성등 다양하게 사용이 가능
          아래와 같은 것 중 하나만 사용해야 한다.
          • slf4j-log4j12-{version}.jar
          • slf4j-jdk14-{version}.jar
          • slf4j-nop-{version}.jar
          • slf4j-jcl-{version}.jar
          • logback-classic-{logbook-version}.jar
      • SLF4J 인터페이스를 직접 구현한 구현체도 있다.
      • 라이브러리나 프레임워크는 사용 하지 말기!!!

      API --> Binding


    • Bridge

      • 로거 호출을 slf4j 인터페이스로 연결
        이전의 만들어진 레거시 (jcl, log4j, jul) 코드를 최종적으로 slf4j 로 변경 해주는 것

        • Log4J 호출을 SLF4J API 로 연결하기

          • Log4j-over-slf4j.jar 추가
            • Log4j 호출을 받아서 SLF4J API 호출
            • Log4J 인터페이스를 구현하고 있음
          • 의존성 에서 log4j.jar 제거
          • Slf4j-log12.jar랑 같이 쓰면 안됨
            • 무한루프 생성
        • JCL 호출을 SLF4J 로 연결하기

          • 의존성에 jcl-over-slf4j.jar 추가

            • JCL 호출을 받아서 SLF4J API 호출
            • JCL 인터페이스를 구현하고 있음
          • 의존성에 common-logging.jar 제거

          • Slf4j-jcl.jar랑 같이 쓰면 안됨

            • 무한루프
      Log4J --> Bridge --> API

브릿지랑 바인더랑 같은 종류를 쓰면 안됨 이유는 아래와 같이 Slf4j 브릿지와 slf4j 바인딩을 같이 쓰면 무한 반복이 될수 있기 때문에 같은 것을 쓰면안된다.

    모든 로깅을 logback으로 하려면?

로그백을 제외한 다른 로거에 호출을 다 지워주고 바인더는 logback 바인더만 호출하면 된다.

Springboot 에서는

Springboot-logging 이라는 것을 사용해서 마지막 그림의 설정을 해주었음.

+ Recent posts