코딩 개발/Spring

Spring Logging 1탄 - Slf4j, logback-classic, jcl-over-slf4j, <exclusion>

호소세 2023. 7. 9. 19:25
728x90
반응형

AOP 관점 지향 프로그래밍에서 공통 관심사(Cross Cutting Concern)로 많이 사용되는 로깅 로직에 대하여 알아보도록 하겠습니다.

 

Maven pom.xml을 이용하여 제목에 작성되어 있는 몇 가지 라이브러리를 가져와서 사용할 예정입니다.

 

사용 예시는 라이브러리를 설명하고 보여드릴 예정입니다.

Maven repo에서 라이브러리 가져오기

https://mvnrepository.com/

 

이곳에서 라이브러리 검색해서 pom.xml에 붙여주시면 됩니다. 물론 코드도 보여드릴게요.

 

1. slf4j-api

저는 1.7.25 버전을 가져왔습니다.

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

sl4j-api 설명

slf4j-api는 자바 프로그래밍에서 로깅을 지원하는 간단하고 일관된 인터페이스를 제공하는 라이브러리입니다. slf4j는 Simple Logging Facade for Java의 약자로, 다양한 로깅 시스템과의 연동을 가능하게 해 줍니다.

 

slf4j-api는 로깅 작업을 수행하기 위한 메서드를 정의하는 인터페이스를 제공합니다. 이 인터페이스를 사용하면 애플리케이션 코드에서 실제로 어떤 로깅 시스템을 사용할지에 대해 결정하지 않아도 됩니다. 

대신에 slf4j를 구현하는 로깅 바인딩(로깅 시스템과의 연결)을 선택하면 됩니다. 

 

slf4j는 로깅에 대한 일반적인 작업을 수행하기 위해 다양한 로깅 수준(Level)을 제공합니다. 

로깅 수준에는 TRACE, DEBUG, INFO, WARN, ERROR 등이 있으며, 애플리케이션에서 발생하는 이벤트의 중요도에 따라 적절한 로깅 수준을 선택하여 메시지를 기록할 수 있습니다. 

 

slf4j를 사용하면 애플리케이션의 로깅 코드를 유연하게 관리할 수 있습니다. slf4j를 구현하는 다양한 로깅 바인딩들을 사용하여 원하는 로깅 시스템으로의 전환을 쉽게 수행할 수 있습니다. 예를 들어, Logback, Log4 j, JUL (Java Util Logging) 등의 로깅 시스템과 연동할 수 있습니다.

 

slf4j는 인터페이스만 제공하는 것을 보니 아마 DBCP 랑 비슷한 맥락 같죠?

 

2. logback-classic

로깅 바인딩 중 logback-classic을 사용하려고 합니다. Log4j 후속버전으로 더욱 향상된 성능과 유연성을 제공한다고 합니다.

 

logback-classic은 slf4j를 구현하는 로깅 바인딩 중 하나로, slf4j-api를 사용하여 애플리케이션 코드에서 로깅 작업을 수행하고, logback-classic을 로깅 시스템으로 선택하여 실제 로그 메시지를 기록합니다. logback-classic은 로깅 작업을 위해 LoggerContext, Logger, Appender, Layout 등의 핵심 구성 요소를 제공합니다.

 

logback-classic은 강력하면서도 유연한 로깅 설루션으로, 로깅 작업을 효율적으로 관리하고 성능을 향상할 수 있습니다. logback-classic의 구성 파일인 logback.xml을 사용하여 로깅 설정을 지정할 수 있으며, 다양한 로깅 기능과 옵션을 제공하여 애플리케이션의 로깅을 조정할 수 있습니다.

 

logback.xml 파일 예시

저도 아직 정확하게 뭔지를 모르겠지만 한번 알아보도록 할게요. 더 알게 되면 다음에도 알아보고요... ㅠ

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds">
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <Pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n</Pattern>
        </encoder>
    </appender>
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>report.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>report-%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <Pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n</Pattern>
        </encoder>
    </appender>
    <logger name="org.springframework" level="warn"/>
    <logger name="myproject" level="debug"/>
    <root level="info">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
    </root>
</configuration>

1. configuration scan

 

주기적으로 configuration 파일을 읽어 Logback의 성정을 재구성합니다.

Application 실행중일 때도 별도의 재시작 없이 설정 파일을 수정하고 적용가능합니다.

scanPeriod는 작성하지 않으면 default 1분입니다.

<configuration scan="true" scanPeriod="30 seconds">

2. 콘솔 로깅

 

로깅 작업이 진행될 때 Console 창에 내용이 작성되기 위한 설정입니다.

% d {HH:mm} - 로그 출력 시간 포맷

 %-5 level - 로그 레벨  5 고정폭  출력

% logger - logger의 이름 출력

{ } - 이름 출력 최대 length

% msg - 사용자 메시지 출력

% n - 줄 바꿈

<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <Pattern>%d{HH:mm} %-5level %logger{36} - %msg%n</Pattern>
    </encoder>
</appender>

시간, 로깅 수준, log 메시지를 출력하는 클래스의 이름, 메시지가 잘 나오게 됩니다.

 

3. 파일 로깅<appender>

 

appender 요소를 정의하여 파일로 로그를 저장할 수 있습니다.

 

ch.qos.logback.core.rolling.RollingFileAppender 클래스를 사용하여 파일로 로그를 출력합니다. 로그 파일의 경로는 <file> 요소에 지정되어 있으며, "report.log"로 설정되어 있습니다.

 

ch.qos.logback.core.rolling.TimeBasedRollingPolicy 클래스를 사용하여 시간 기반으로 롤링하는 정책을 사용합니다.

<fileNamePattern> 요소 - 롤링된 파일 이름 패턴을 지정하며, "report-%d {yyyy-MM-dd}. log"로 설정되어 있습니다.

<maxHistory> 요소 - 유지할 롤링된 파일의 최대 개수를 설정합니다.

<encoder> 요소 - console에 있는 것과 같습니다.

 

4. 특정 패키지나 클래스에 대한 로깅 레벨 설정

    <logger name="org.springframework" level="warn"/>
    <logger name="myproject" level="trace"/>

org.springframework 패키지에 속하는 클래스들에 대해서는 로깅 레벨 'warn'부터 로그메시지를 출력하고,

myproject 패키지에 속하는 클래스들은  로깅 레벨 'trace'부터 로그메시지를 출력합니다.

 

5. 모든 로거에 대한 기본 로깅 레벨

<root level="info">
  <appender-ref ref="CONSOLE"/>
  <appender-ref ref="FILE"/>
</root>

모든 로거에 대해 로깅 레벨 'info'부터 로그 출력합니다.

 

또한 콘솔과 file 저장 둘 다 출력하게 합니다.

요기서 제거하면 console 출력이 되지 않게 하거나 file 저장이 되지 않게 할 수 있습니다.

 

기본적인 것들을 배웠으니 

 

3.  jcl-over-slf4j

jcl-over-slf4j는 Jakarta Commons Logging (JCL) API를 slf4j-api로 전환해 주는 라이브러리입니다. 

JCL은 자바 로깅을 위한 인터페이스로, 여러 로깅 시스템 (예: Log4 j, JUL)과의 연결을 지원합니다. 그러나 JCL은 종종 클래스로더 충돌이나 의존성 충돌 문제를 일으킬 수 있습니다. 

 

jcl-over-slf4j는 이러한 문제를 해결하기 위해 JCL API를 사용하는 코드를 slf4j API로 전환합니다. 즉, jcl-over-slf4j는 JCL API를 호출하는 코드를 그대로 유지하면서 실제로는 slf4j를 통해 로깅 작업을 수행하도록 해줍니다. 

 

jcl-over-slf4j를 사용하면 기존에 JCL을 사용하는 코드를 수정하지 않고도 slf4j를 사용하는 로깅 시스템으로 전환할 수 있습니다. 이를 통해 JCL과 관련된 문제를 해결하고, slf4j의 성능과 유연성을 활용할 수 있습니다.

 

4. <exclusion>

Maven pom.xml 에서 exclusion 태그가 있는데, 이것의 사용 용도는 특정 의존성을 제외하고 사용하도록 지정하는 기능입니다.

 

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>5.3.20</version>
	<exclusions>
		<exclusion>
			<groupId>commons-logging</groupId>
			<artifactId>commons-logging</artifactId>
		</exclusion>
	</exclusions>
</dependency>

위의 코드에서 exclusion 태그는 spring-context 의존성에 대한 설정을 나타내고 있습니다. 

exclusion 태그 내부에는 <groupId>와 <artifactId> 요소가 포함되어 있으며, 여기서는 commons-logging 의존성을 제외하고 사용하도록 지정하고 있습니다.

 

간단한 사용 예제

위의 설정들을 잘 마무리 짓고 이제 가벼운 예제를 보고 글을 마무리 짓도록 하겠습니다.

<LoggingDemoService.java>

public class LoggingDemoService {
	private Logger logger=LoggerFactory.getLogger(getClass());
	public void testLog() {
		// 로깅 레벨별로 실행 
		logger.trace("trace test");
		logger.debug("debug test");
		logger.info("info test");
		logger.warn("warn test");
		ArrayList<String> list=new ArrayList<String>();
		try {
		list.get(1);
		}catch(Exception e) {
			logger.error("error test",e);
		}
	}
}

1. slf4 j를 사용하여 클래스의 로거(logger)를 초기화하는 코드입니다.

LoggerFactory는 slf4j의 LoggerFactory 클래스를 참조하는 것이며, getLogger() 메서드를 호출하여 로거 인스턴스를 생성합니다. getClass()는 해당 코드를 포함하는 클래스의 Class 객체를 반환하는 메서드입니다.

 

2. 로깅 수준에 따른 메시지를 남기고 있습니다.

3. 에러 로깅도 한번 내보겠습니다.

<TestLoggingDemoService.java>

public class TestLoggingDemoService {
	public static void main(String[] args) {
		LoggingDemoService service=new LoggingDemoService();
		service.testLog();
	}
}

19:17 TRACE o.k.m.model.LoggingDemoService - trace test

19:17 DEBUG o.k.m.model.LoggingDemoService - debug test

19:17 INFO o.k.m.model.LoggingDemoService - info test

19:17 WARN o.k.m.model.LoggingDemoService - warn test

19:17 ERROR o.k.m.model.LoggingDemoService - error test

java.lang.IndexOutOfBoundsException: Index 1 out of bounds for length 0

......................................

저희가 설정파일에서 저장한 대로 잘 나왔죠?

 

소감

이렇게 로깅에 대하여 간단? 하게 알아보았는데요. 아직 끝이 아닙니다! 어노테이션에 대해서도 공부해 봐야겠죠.

설정 파일 및 기본 개념에 대해 열심히 작성했지만 아직 부족한 부분이 많아서 뭔가 빠진 내용이 있을 수도 있습니다. 하지만 점점 채워지는 것이 공부라고 생각하기 때문에 더 많은 것을 알게 되면 다시 한번 글을 수정하거나 작성하도록 하겠습니다.

반응형