본 내용은 개발 환경이 아닌 운영 환경에서 프로그램의 동작을 확인할 수 있도록 도와주고 Error를 찾아낼 수 있는 Log의 개요와 Logging이 무엇인지, Log가 가지는 특징에 대해 설명하고 있습니다.
해당 내용은 실질적인 로그 구현을 다루고 있지는 않아, 서버 개발자가 아니더라도 이해할 수 있는 내용으로 담았습니다.
프로그램을 개발하고 실행해보면, 다들 이런 형식의 프로그램의 동작에 대해서 설명해주는 Log 정보들을 볼 수 있었을 겁니다.
제 경우 Spring framework를 사용 했었는데요.
이러한 로그들이 보이는 이유는, 해당 framework를 만든 사람들이, 프로그램 실행 시 해당 로그들이 출력될 수 있도록 만들었기 때문입니다.
우리는 이러한 로그들을 통해서, 프로그램이 정상동작을 하고 있는지, 아니면 프로그램이 Error를 발생시켜서 예상하지 못한 동작을 하고 있는지를 판단할 수 있습니다.
이렇게 로그가 잘 작성된 프로그램들을 통해서 우리는 프로그램의 동작이 우리의 예상과 맞는지 확인하면서 프로그램을 작성할 수 있게 됩니다.
넵, 이렇게 로그를 통해서 이해할 수 있도록 만든 프로그램은 유지보수나 오류를 찾아내는데 훨씬 수월하겠죠?
그럼 내가 만든 서비스도 해야겠죠?
😒
그러면 Log에 대해서 조금 더 깊게 알아볼 수 있도록 하겠습니다.
로그는 컴퓨터의 이용 상황이나 데이터 통신 등 기록 및 정보의 기록을 가지고 있는 것 또는 그 기록을 가르킵니다.
이러한 기록을 통해, 해당 프로그램이 잘 실행되고 있는지 정보를 전달해줄 수 있습니다. 😃
로깅은 해당 로그를 보면서, 프로그램의 동작이 정상적인지, 혹은 예기치 못한 오류가 발생하는지를 확인하는 것을 말합니다.
로깅을 하기 위해서를 생각해보면, 우리는 특정한 오류가 발생하는지만 확인하고 싶은데 프로그램 동작이나, DB에서 값을 가져오는 것 등 더 세부적인 로그들을 볼 필요는 없습니다.
그래서 로그레벨이라는 것을 통해서, 원하는 수준의 로그까지만 볼 수 있게 만들었습니다.
trace: debug보다 세분화된 정보
debug: 디버깅하는데 유용한 정보
info: 진행상황 같은 일반 정보
warn: 오류는 아지만 잠재적인 오류 원인이 될 수 있는 경고성 정보
error: 요청을 처리하는 중 문제가 발생한 오류 정보
fatal: 종료가 발생할 정도로 치명적인 오류 정보
해당 로그 레벨을 통해서, 사용자는 필요한 수준의 로그까지만 볼 수 있습니다.
로그파일/DB 생명주기 & 저장소 용량
로그가 저장되는 저장소의 용량을 관리할 수 있어야 합니다. 이러한 부분을 미리 명확하게 계획을 수립해야, 디스크 용량 부족과 같은 갑작스러운 장애를 방지할 수 있습니다.
개인 정보, 시스템 주요 정보(시스템 보안, 계정 정보)
로그에는 개인정보, 시스템 계정 정보가 작성되는 경우가 많기 때문에 각별히 주의가 필요합니다.
로그를 직접 사용하기 위해서는 Logging framework를 이해하고 있어야 합니다.
저는 Java 진영의 Logging framework를 소개하고자 합니다.
slf4J는 로깅 파사드(facade)로서 log4j, logback, commons-logging과 같은 로깅 프레임워크를 위한 추상화를 제공해줍니다.
이는 로깅 프레임워크 간 이동을 자유롭게 해줍니다.
❓ 그러면 로그 프레임워크는 어떤 것을 써야 할까요?
로그 프레임워크는 log4j → logback → log4j2 순서로 나오게 되었는데, 이 중에서, log4j는 개발이 중단되어 사용하지 않습니다.
logback, log4j2은 다음과 같습니다.
logback
: log4j를 구현한 개발자가 logback을 개발했습니다. log4j와 유사하면서도 향상된 성능과 필터링 옵션을 제공하며 slf4j도 지원합니다. 그리고 자동 리로드도 가능합니다.log4j2
: log4j2는 앞서 살펴본 log4j와 logback과 비교했을 때 가장 최근에 등장했습니다. logback과 동일하게 자동 리로드 기능과 필터링 기능을 제공합니다.멀티스레드 환경에서 비동기 로거의 경우 log4j2가 다른 로거보다 처리량이 몇배나 더 높다고 합니다.
그리고 람다 표현식과 사용자 정의 로그 레벨도 지원하므로 log4j2를 사용하는게 좋을 것 같습니다.
일반적으로는 웹 프로그램을 만들면서 log를 사용하면 Spring framework환경이겠지만, 그 경우는 다음에 소개하고, 순수한 Java Project에서 어떻게 log4j2를 사용하는지 알아보도록 하겠습니다.
Logging Framework를 의존으로 추가해줍니다.
Logging Framework를 의존 추가하는 방법은, 직접 다운 받아서 라이브러리에 추가해도 되고, gradle, maven을 이용해서 의존을 추가해줘도 됩니다.
해당 Logger를 import한 후 Logger를 가져와 사용합니다.
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, "ALL LOG TEST");
logger.trace("TRACE LOG TEST");
logger.info("INFO LOG TEST");
logger.debug("DEBUG LOG TEST");
logger.warn("WARN LOG TEST");
logger.error("ERROR LOG TEST");
logger.fatal("FATAL LOG TEST");
System.out.println(logger.getLevel());
System.out.println(logger.getLevel().intLevel());
}
}
이렇게 하고 console에서 결과를 보면, 결과는 다음과 같습니다.
결과를 보면, error와 fatal log만 출력된 것을 볼 수 있는데, default logger는 기본적으로 error 이상의 log만 출력합니다.
이를 수정하기 위해서 설정 파일을 통해서 이를 수정하겠습니다.
resources/log4j2.xml 파일을 만들어서 해당 로그에 대한 설정을 추가합니다.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<!-- Appender, Layout 설정 -->
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout/>
</Console>
<File name="file" fileName="./logs/file/sample.log" append="false">
<PatternLayout pattern="%d %5p [%c] %m%n"/>
</File>
</Appenders>
<!-- Logger 설정 -->
<Loggers>
<Logger name="Main" level="DEBUG" additivity="false">
<AppenderRef ref="console"/>
<AppenderRef ref="file"/>
</Logger>
<Root level="ERROR">
<AppenderRef ref="console"/>
</Root>
</Loggers>
</Configuration>
해당 설정 후 다시 출력을 해보면,
😃
해당 설정파일을 통한 설정 방식과, 스프링부트에서 사용 방식에 대해서는 추후 업로드 하겠습니다.
읽어주셔서 감사합니다.