SLF4J 라이브러리 - 추상 Logging Framework


SLF4J추상화된 Logging Framework다. 따라서, 단독으로는 사용이 불가능하고 일관된 인터페이스를 맞추기 위해 사용된다.

(로깅에 대한 추상 레이어를 제공하는 역할)

보통 로깅 구현체로 Log4J Logback을 많이 사용한다.

 

과거에는 Log4J를 많이 사용했으나, 후속 버전인 Logback이 나오면서 현재는 Logback을 사용하는 추세.

 

SLF4J는 3가지 모듈을 제공한다.

  1. SLF4J API : SLF4J 인터페이스 사용을 위한 라이브러리
  2. SLF4J Binding : SLF4J와 로깅 구현체(Log4J | Logback)를 연결하는 어댑터 역할을 하는 라이브러리
  3. SLF4J Bridging : 인터페이스간 다리 역할을 하는 라이브러리. 예) JCL-over-SLF4J

 

SLF4J라는 로깅을 위한 공통된 인터페이스를 둠으로써 로깅 구현체를 유연하게 변경할 수 있다.

Spring은 내부적으로 로깅 인터페이스로 JCL(자카르타 공통 로깅)을 사용하기 때문에 이를 SLF4J로 교체하는 작업이 필요.

 

결론적으로 SLF4J를 사용하기 위해 해야할 작업들은 다음과 같다.

  1. Spring에서 내부적으로 사용하는 JCL 빼버리기 (사용 안 할거니까 굳이 무겁게 추가할 필요는 없겠지?)
  2. JCL-over-SLF4J 추가
  3. SLF4J API 추가
  4. SLF4J-log4j 추가
  5. log4j 추가

 

먼저, JCL 관련 설정부터 해주자.

Spring 프레임워크 내부에 존재하는 JCL 라이브러리를 빼는 이유는 JCL을 사용하지 않기 때문.

그로인해 JCL 라이브러리에 의존하는 클래스들이 에러가 날텐데, 그걸 jcl-over-slf4j를 이용해 겉은 JCL이지만 내부적으론 SLF4J API를 호출하도록 하는 SLF4J Bridge 라이브러리를 추가한다.

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${org.springframework.version}</version>
    
    <exclusions>
        <!-- Exclude Commons Logging in favor of SLF4j -->
        <exclusion>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jcl-over-slf4j</artifactId>
    <version>${org.slf4j.version}</version>
    <scope>runtime</scope>
</dependency>

 

SLF4J를 사용하기 위해 의존 라이브러리에 추가하자

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.25</version>
</dependency>

 

다음으로 SLF4J와 사용할 로깅 구현체를 바인딩하자. ( 반드시 하나의 구현체와 바인딩해야 한다. )

여기에선 Log4J의 1.2버전에 대해 바인딩하겠다. ( log4j12Log4J 1.2버전이란 뜻 )

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>${org.slf4j-version}</version>
    <scope>runtime</scope>
</dependency>

 

당연히 log4j 모듈도 의존에 추가해줘야겠지?

<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.12.1</version>
</dependency>

 

 

 

Log4J 설정


Log4J의 로그레벨은 총 6가지

  1. FATAL : 치명적인 에러
  2. ERROR : 요청을 처리하는 도중 에러 발생
  3. WARN : 지금은 처리 가능한 문제지만, 향후 에러의 원인이 될 수 있는 문제
  4. INFO : 로그인, 상태변경과 같은 정보성 메시지
  5. DEBUG : 개발시 디버그 용도로 사용
  6. TRACE : DEBUG 레벨보다 더 세심한 디버그 용도로 사용

 

Log4J 설정은 프로퍼티 파일이나 XML 파일로 가능한데, 보통 XML 파일을 이용해 설정함.

설정이라하믄, 로그를 어디에 어떤 포맷으로 출력할지를 명시하는 것.

 

<appender> 태그를 이용해 로그를 어디에 출력할지를 명시할 수 있고, 선택할 수 있는 출력 위치는 다음과 같다.

  • ConsoleAppender : 콘솔에 출력
  • FileAppender : 파일에 출력
  • RollingFileAppender : 조건에 따라 파일에 출력
  • DailyRollingFileAppender : 매일 조건에 따라 파일에 출력
  • JDBCAppender : RDB 테이블에 출력

 

콘솔에 출력하는 설정 예

<appender name="console" class="org.apache.log4j.ConsoleAppender">
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d{yyyy-MM-dd} [%p] (%C{1}.%M:%L) %m%n"/>
    </layout>
</appender>

 

위에서 <layout> 태그로 패턴을 통해 로그를 어떤 포맷으로 출력할지를 지정했는데, 지원하는 패턴은 다음과 같다.

 

마지막으로 <logger> 태그를 이용해 어떤 패키지에서 어떤 appender를 사용할지를 명시해주면 된다.

<level> 태그는 value 속성값에 지정한 로그 레벨 이상의 로그만 출력한다는 뜻

<!-- Application Loggers -->
<logger name="com.pangtrue">
    <level value="INFO"/>
    <appender-ref ref="console">
</logger>

<!-- 3rdparty Loggers -->
<logger name="org.springframework">
    <level value="INFO"/>
    <appender-ref ref="console">
</logger>

<!-- Root Logger -->
<root>
    <priority value="INFO"/>
    <appender-ref ref="console"/>
</root>

 

 

 

JCL (Jakarta Commons Logging)


SLF4J와 같이 JCL도 로깅에 대한 추상 레이어를 제공하는 인터페이스다.

Spring은 내부적으로 JCL을 사용한다.

 

JCL이 실제 Logging Framework를 선택하는 시점이 런타임이라 클래스 로더 문제 및 오버헤드가 발생할 여지가 있음.

따라서, 이를 개선한 SLF4J로 대체해서 사용.

 

 

 

참고자료


[1] https://gmlwjd9405.github.io/2019/01/04/logging-with-slf4j.html

[2] https://whiteship.tistory.com/2541

[3] https://sjh836.tistory.com/161