728x90

학부생 시절에는 로그에 대해서 별 관심 없는 경우가 많았다.

그건 필자 뿐만이 아니라 대부분 사람이 아마 그럴 것이다.

 

하지만 실무 환경으로 들어가면 로그가 중요하다.

로그가 중요한 이유는 크게 보면 2가지로 이야기할 수 있을것 같다.

 

1. 로그는 개발자가 생각하기에 중요한 내용들을 "어떠한 형태로든" 기록할 수 있다.
2. 1번에서 말한 "어떠한 형태로든"이라는 부분은 아주 중요하다. 로그는 경우에 따라서 콘솔이 아니라 파일 등에 기록할 수 있어야한다.

 

로그가 중요한줄 알겠느데 그게 라이브러리 까지 필요한 이야기냐?

그냥 System.out.println하면 안되냐라고 생각할 수 있다.

당연히 시간이 많으면 그래도 되지만 우리는 시간이 많이 없고

로그를 콘솔에 보낼지, 파일에 보낼지, DB에 보낼지, 메세지 큐에 보낼지에 따라 로직이 달라지고

게다가 로그를 작성할때 현재 시각은 몇시인지 어떤 함수에서 동작한건지지도 로직이 달라진다.

 

로그들을 통합해서 만들어 놓은것들을 Logging Service 혹은 Logging Framework라고 한다.

자바에서는 꽤 많은 Logging Service들이 있으나 가장 많이 쓰고 중요하게 다루는 것은 Log4j2이다.

 

 

https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core

 

아니 적혀있기는 Log4j아닌가? 왜 Log4j2라고 부르는가 라고 묻는다면 간단히 버전이 2로 올라서 그렇다.

지금 작성시점에서는 2가 최신이지만 나중에 3이 등장할지도 모르겠다.

최신버전은 2021년 11월 13일 기준으로 2이다.

 

버전이 바뀌면서 많이 바뀌었느냐라고 물으면 많이 바뀌긴했다.

앞으로의 진행에서 Log4j의 사용법은 일체 언급을 안할것이기 때문에 보시는 분의 회사의 상사가 Log4j 버전 1을 사용한다면

이 글은 참고로만 사용하는게 좋다(그냥 참고도 안하고 다른거 보는게 나을수도 있겠다)

 

이제 이야기가 길어졌으므로 시작해보자

 

1. 의존성 추가

dependencies {
    implementation 'org.apache.logging.log4j:log4j-core'
    implementation 'org.apache.logging.log4j:log4j-api'
}

제일 먼저할일은 의존성을 추가하는 것이다. 제일 중요한건 core랑 api이므로 이 둘을 추가한다.

gradle에 의존성을 추가하는데 여러분은 maven을 사용하거나 아니면 그런거 없이 쌩 intelliJ나 Eclipse를 사용할 수도 있다.

뭐 이걸 볼정도의 사람은 그 방법쯤은 다 알고 있을거라 생각하지만 혹시나 모르니 링크를 걸어두겠다.

 

IntelliJ 외부 라이브러리 추가
Eclipse 외부 라이브러리 추가
Maven 외부 라이브러리 추가

필자가 과거에 작성해 놓았던 글들이 있으니 참고해서 하면 될 것이다.

문제는 좀 날짜가 오래됬는데 상했는지 안상했는지는 여러분이 알아서 잘 판단하길 바란다.

 

2. 바로 예제 실행

초간단 시작이라고 했으니 여기서 시작하는게 맞지 않나 싶다. 예제를 보자.

 

import org.apache.logging.log4j.Level;
import
org.apache.logging.log4j.LogManager;
import
org.apache.logging.log4j.Logger;

public class
Main {
   
final static Logger logger = LogManager.getLogger(Main.class);

    public static void
main(String[] args) {
       
logger.log(Level.ALL,"LOG TEST");
       
logger.trace("TRACE TEST");
       
logger.info("INFO TEST");
       
logger.debug("DEBUG TEST");
       
logger.warn("WARN TEST");
       
logger.error("ERROR TEST");
       
logger.fatal("FATAL TEST");
       
System.out.println(logger.getLevel());
       
System.out.println(logger.getLevel().intLevel());
   
}
}

 전체 코드인데 잘라서보자.

 

final static Logger logger = LogManager.getLogger(Main.class);

 Logger는 객체가 여러개일 이유가 없으므로 보통 static으로 만든다.

여기서 getLogger의 경우 파라메터 없이 호출할 수 있는데 이 경우 default로거를 호출한다.

이해가 안갈 수 있는데 Log4j2의 컨셉이 로거마다 이름을 붙힐 수 있다.

지금우리는 Main.class의 이름을 로거로 만든것이다. 이는 여기서 말하기 보다 추후에 이야기하도록하겠다.

 

https://logging.apache.org/log4j/2.x/manual/customloglevels.html

 

그 다음은 로그를 호출해주기 전에 로그레벨에 대해서 알아보자.

이게 어떻게보면 살짝 복잡한 개념인데 로그들은 크게 보면 레벨과 이름으로 정의되어 있다.

이 컨셉은 추후에 더 자세히 알려주겠다. 중요한건 레벨은 값을 가진다는 것이다.

 

현재 우리는 Main로거가 정의가 되있지 않으므로 default로거를 가져온다.

default로거는 레벨이 ERROR이다.

위의 표를 보면 레벨마다 값이 있는걸 알 수 있는데 이 값은 굉장히 중요하다.

왜냐하면 메세지(로그)의 정수레벨이 로거의 정수레벨보다 높으면 출력하지 않기 때문이다.

무슨말인지 모르겠으면 그냥 아래 예제들을 보면 바로 이해할 수 있다.

 

실전에서 아무래도 많이 쓰는건 INFO랑 ERROR인거 같다.

나머지도 취향과 상황에 따라 갈리긴 하기에 확답은 못하겠다.

 

logger.log(Level.ALL,"LOG TEST");

이렇게 log메소드로 호출하면 첫번째 파라메터에는 레벨을, 두번째 파라메터에는 출력할 메세지를 적으면 된다.

여기서는 level.ALL로 호출했다. level.ALL은 가장 낮은 레벨이다.

심지어 사용자가 만든 레벨도 넣을 수 있는데 그렇게 사용할 일은 없으므로 생략하겠다.

 

logger.trace("TRACE TEST");
logger.info("INFO TEST");
logger.debug("DEBUG TEST");
logger.warn("WARN TEST");
logger.error("ERROR TEST");
logger.fatal("FATAL TEST");

로그들을 출력할때 실제로는 log메소드보단 각각의 이름으로 정의된 메소드를 사용하는 편이다.

이제 잘 출력되는지만 확인하면 된다.

 

System.out.println(logger.getLevel());
System.out.println(logger.getLevel().intLevel());

마지막으로는 현제 로거의 레벨을 확인해보자.

이게 꽤 중요한데 이걸 알아야 나머지들을 이해할 수 있기 때문이다.

자 그럼 실행시켜보자.

 

실행 결과

 

실행결과를 보면 로그가 잘 출력?되는걸 알 수 있다.

근데 보면 ERROR와 FATAL만 출력되고 나머지는 출력되지 않고 있다.

그 이유는 다시 이야기하자면 현재 로거의 레벨이 ERROR로 되어있기 때문이다.

그렇기 때문에 ERROR보다 큰 값의(높은 레벨의) 로그들은 출력되지 않는다. 더 정확히 말하면 정의되지 않았다고 보는게 맞을 것이다.

그런데 모든 상황이 에러만 있는것은 아니기 때문에 이를 해결하는 방법도 알아야한다.

다음 화에서는 이를 해결하는 방법에 대해서 알아보자.

+ Recent posts