성실한 사람이 되자

성실하게 글쓰자

This is spear

JAVA_SPRING

스프링에서 로깅

Imaspear 2022. 1. 18. 13:54
728x90
✔️

스프링에서 로깅

 

로그 사용 장점

  1. 쓰레드 정보와 클래스 이름 같은 부가 정보를 함께 볼 수 있고, 출력 모양을 조절할 수 있다.
    17:38:15.243 [main] INFO hello.springmvc.LogTest - info 로그가 출력이 됩니다.
  1. 로그 레벨에 따라 출력할 수 있어 로그를 상황에 맞게 사용할 수 있다.설정 파일에서 지정한 로깅 레벨이 아닌 경우 로그는 출력되지 않지만, System.out은 설정이 불가능하다.
  2. System.out.println("error 로그가 출력이 됩니다.");
  1. 시스템 아웃 콘솔에만 출력하는 것이 아니라 파일이나 네트워크 등, 로그를 별도의 위치에 남길 수 있다. 특히 파일로 남길 때, 일별, 특정 용량에 따라 로그를 분할하는 것도 가능하다.
  1. 내부 버퍼링, 멀티 쓰레등 등과 같은 성능도 일반 System.out보다 좋다.

 

로그 선언

private Logger log = LoggerFactory.getLogger(getClass());

 

private static final Logger log = LoggerFactory.getLogger(Xxx.class)

 

@Slf4j

 

로그 사용

로그를 설정할 수 있는 파일에 접근해 로깅 레벨을 설정해준다면 로깅 레벨에 맞게 로그가 출력이 된다. 개발 환경에서 로깅 레벨을 debug로 맞춰서 사용하면 debug 레벨 이상의 로그들이 출력이 되고, trace 로그는 출력이 되지 않는다. 개발 환경과 다른 실제 환경에서는 로깅 레벨을 info로 맞추면 debug 이하의 로그들을 출력이 되지 않고, info, warn, error 레벨의 로그들이 출력이 된다. 로깅 레벨 설정과 로깅 레벨에 관련한 내용은 아래에 적혀있다.

 

로깅 레벨을 warn으로 설정

log.warn("로그가 출력이 됩니다.");

로깅 레벨을 error으로 설정

log.error("error 로그가 출력이 됩니다.");

 

로깅 라이브러리

스프링 부트 라이브러리를 사용하면 스프링 부트 로깅 라이브러리( spring-boot-starter-logging )가 함께 포함된다.

 

스프링 부트 로깅 라이브러리는 기본으로 다음 로깅 라이브러리를 사용한다.

💡
SLF4J - http://www.slf4j.org Logback - http://logback.qos.ch

로그 라이브러리는 Logback, Log4J, Log4J2 등등 수 많은 라이브러리가 있는데, 그것을 통합해서 인터페이스로 제공하는 것이 바로 SLF4J 라이브러리다.

 

 

SLF4J 라이브러리

slf4j를 이용해 객체를 생성했다. slf4j는 다양한 Logger 호출까지 처리해주는 어댑터 역할을 하는 라이브러리다.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

 

slf4j가 나온 배경은 아직 업데이트되지 않은 이전 레거시 로깅 프리엠워크를 위한 라이브러리다. 쉽게 이야기해서 SLF4J는 인터페이스이고, 그 구현체로 Logback 같은 로그 라이브러리를 선택하면 된다. 실무에서는 스프링 부트가 기본으로 제공하는 Logback을 대부분 사용한다.

 

로그 레벨

로그 레벨은 TRACE > DEBUG > INFO > WARN > ERROR 순이다. 만약 로그 레벨이 INFO라면 TRACE 레벨의 로그는 실행이 되지 않는다.

 

application.properties 파일 에서 로깅 레벨을 지정하면 된다. 로깅 레벨을 지정하는 방법은 두가지다.

 

    1. 디렉토리 범위 내에서 로깅 레벨을 설정하는 방법지정한 패키지(hello.springmvc) 범위 내에서 로깅 레벨을 설정하면 현재 개발하고 있는 폴더 내에 자신이 설정한 로그들을 확인할 수 있다.
logging.level.hello.springmvc = trace
  #logging.level.hello.springmvc = debug
  #logging.level.hello.springmvc = info
  #logging.level.hello.springmvc = warn
  #logging.level.hello.springmvc = error
  
  •  프로젝트 전체의 로깅 레벨을 설정하는 방법
logging.level.root = trace
#logging.level.root = debug
#logging.level.root = info
#logging.level.root = warn
#logging.level.root = error

 

 

올바른 로그 사용 방법

아래 방식을 사용하면 로그 출력 레벨을 info로 설정해도 해당 코드에 있는 "data="+data 로직이 실제 실행이 되어 해당 문자열을 만들어 더하기 연산이 발생한다.

log.debug("data="+data)

 

아래와 같은 방식을 사용하면 해당 로그를 출력하는 레벨이 아닐 때, 더하기 연산이 일어나지 않는다.

log.debug("data={}", data)

 

메인 메서드에서 실행

@Component
public class LogTest {

    private Logger log = LoggerFactory.getLogger(getClass());

    public LogTest() {
        logTrace();
        logDebug();
        logInfo();
        logWarn();
        logErr();
    }

    public void logInfo() {
        log.info("info 로그가 출력이 됩니다.");
    }

    public void logDebug() {
        log.debug("debug 로그가 출력이 됩니다.");
    }

    public void logTrace() {
        log.trace("trace 로그가 출력이 됩니다.");
    }

    public void logWarn() {
        log.warn("warn 로그가 출력이 됩니다.");
    }

    public void logErr() {
        log.error("error 로그가 출력이 됩니다.");
    }
}

 

@SpringBootApplication
public class SpringmvcApplication {


    public static void main(String[] args) {
        LogTest logTest = new LogTest();
   
        SpringApplication.run(SpringmvcApplication.class, args);
    }

}

 

 

17:51:36.730 [main] DEBUG hello.springmvc.LogTest - debug 로그가 출력이 됩니다.
17:51:36.733 [main] INFO hello.springmvc.LogTest - info 로그가 출력이 됩니다.
17:51:36.733 [main] WARN hello.springmvc.LogTest - warn 로그가 출력이 됩니다.
17:51:36.733 [main] ERROR hello.springmvc.LogTest - error 로그가 출력이 됩니다.

 

 

 

💡
처음에는 로그를 간단하게 출력하려고 스프링 메인 메서드에 생성자를 통해 시도했다.

 

application.properties 파일에는로깅 레벨이 trace인데도 불고하고 debug 레벨까지만 출력이 됐고, 스프링이 로깅에 대해 인식하지 못하는 듯 했다.

 

메인 메서드에서 스프링을 실행하기 전에 로깅 생성자가 실행이 되다 보니 일어나는 일이라 생각한다.

 

 

스프링 빈으로 등록해서 사용

@Component
public class LogTest {

    private Logger log = LoggerFactory.getLogger(getClass());

    public LogTest() {
        logTrace();
        logDebug();
        logInfo();
        logWarn();
        logErr();
    }

    public void logInfo() {
        log.info("info 로그가 출력이 됩니다.");
    }

    public void logDebug() {
        log.debug("debug 로그가 출력이 됩니다.");
    }

    public void logTrace() {
        log.trace("trace 로그가 출력이 됩니다.");
    }

    public void logWarn() {
        log.warn("warn 로그가 출력이 됩니다.");
    }

    public void logErr() {
        log.error("error 로그가 출력이 됩니다.");
    }
}

 

2022-01-17 17:52:46.830 TRACE 16712 --- [           main] hello.springmvc.LogTest                  : trace 로그가 출력이 됩니다.
2022-01-17 17:52:46.830 DEBUG 16712 --- [           main] hello.springmvc.LogTest                  : debug 로그가 출력이 됩니다.
2022-01-17 17:52:46.831  INFO 16712 --- [           main] hello.springmvc.LogTest                  : info 로그가 출력이 됩니다.
2022-01-17 17:52:46.831  WARN 16712 --- [           main] hello.springmvc.LogTest                  : warn 로그가 출력이 됩니다.
2022-01-17 17:52:46.831 ERROR 16712 --- [           main] hello.springmvc.LogTest                  : error 로그가 출력이 됩니다.

 

그냥 간단하게 스프링 빈을 수동 등록하여 스프링이 시작할 때, 생성자를 호출할 수 있도록 설정했다. 스프링은 application.properties 파일에서 설장한 로깅 레벨에 맞게 로그들을 출력했다.

 

 

롬복을 이용한 로그 사용(@Slf4j 애너테이션 사용)

@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE})
public @interface Slf4j {
    String topic() default "";
}

 

@Slf4j
public class LogTest {


    public void logInfo() {
        log.info("info 로그가 출력이 됩니다.");
    }

    public void logDebug() {
        log.debug("debug 로그가 출력이 됩니다.");
    }

    public void logTrace() {
        log.trace("trace 로그가 출력이 됩니다.");
    }

    public void logWarn() {
        log.warn("warn 로그가 출력이 됩니다.");
    }

    public void logErr() {
        log.error("error 로그가 출력이 됩니다.");
    }
}

 

17:38:15.243 [main] INFO hello.springmvc.LogTest - info 로그가 출력이 됩니다.
17:38:15.247 [main] DEBUG hello.springmvc.LogTest - debug 로그가 출력이 됩니다.
17:38:15.247 [main] ERROR hello.springmvc.LogTest - error 로그가 출력이 됩니다.
17:38:15.247 [main] WARN hello.springmvc.LogTest - warn 로그가 출력이 됩니다.

 

롬복을 이용해서 사용하면 Logger 구현체를 만들 필요 없이 변수 명이 log라는 객체를 마음껏 사용하면 된다.