개발 과정에서나 운영 환경에서의 문제 해결에 있어서 로깅의 중요성은 아무리 강조해도 지나치지 않다. 로깅은 시스템의 내부 동작을 이해하고, 문제의 원인을 파악하는데 필수적인 정보를 제공한다. 이를 위해 로깅 시스템은 어플리케이션의 성능에 영향을 주지 않으면서 필요한 정보를 효과적으로 제공할 수 있어야 하며, 다양한 배포 환경과 상황에 따라 로깅의 세부 사항들을 조정할 수 있어야 한다.
Java 개발 생태계에서는 다양한 로깅 프레임워크가 이러한 기술적 요구사항을 해결해 주고 있다. SLF4(Simple Logging Facade for Java)는 이들 프레임워크를 추상화한 표준화된 API로 제공하여, 개발자가 구체적인 로깅 구현체를 변경하고자 할 때 코드를 변경할 필요 없이 의존성만 교체함으로써 유연하게 대응할 수 있게 해준다.
이 포스팅에서는 Java 로깅 프레임워크 중에서도 특히 Log4j, Logback, Log4j2에 대해 간단히 소개와 동시에 예제를 보여주며, 어떤 프레임워크를 사용하면 좋을지 정리해보도록 한다.
Log4j
Log4j는 아파치(Apache Log4j) 프로젝트로 가장 오랜기간 사용한 로깅 프레임워크이며, 개발기간이 좀 된 개발자들은 아직도 Log4J를 쓰는 경우가 종종 있다. 현재에 이른 계층적 로그 레벨과 로거와 같은 기본 개념을 도입한 프로젝트로 2015년에 EOL(End of Life, 개발종료)이 된 사실상 더이상 사용을 하는 것을 권고하지 않는 프레임워크이다.
샘플 코드
import org.apache.log4j.Logger;
public class Log4jExample {
final static Logger logger = Logger.getLogger(Log4jExample.class);
public void performSomeOperation() {
logger.info("로그 내용");
}
}
Log4j를 사용하기 위해서는 'log4j.jar' 파일을 클래스패스에 추가하고 log4j.properties 파일로 로거와 append를 설정해야 한다.
Maven 설정
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
Log4j는 기본적으로 SLF4J를 지원하지 않기에 표준화된 인터페이스를 통해 Log4j를 사용하려면 아래 Dependency를 추가해야 한다.
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<scope>test</scope>
</dependency>
Gradle 설정
implementation 'log4j:log4j:1.2.17'
log4j.properties 예시
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=app.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p [%c] - %m%n
log4j.rootLogger=info, file
# basic log level for all messages
log4j.logger.org.hibernate=info
# SQL statements and parameters
log4j.logger.org.hibernate.SQL=debug
log4j.logger.org.hibernate.type.descriptor.sql=trace
Logback
Logback은 Log4j의 후속으로 성능 향상과 SLF4J에 대한 기본 지원, 로깅 설정의 자동 리로딩 같은 여러 개선 사항을 도입하였다. Logback은 세부분으로 구성되어 있으며 각각 logback-core, logback-classic, logback-access로 되어 있다.
샘플 코드
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogbackExample {
private static final Logger logger = LoggerFactory.getLogger(LogbackExample.class);
public void performSomeOperation() {
logger.info("로그 내용");
}
}
Logback 설정은 XML 형식의 logback.xml 파일을 통해 이루어지며, 기본적으로 DEBUG 레벨 이상의 로그를 표준 출력으로 보낸다.
Maven 설정
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
Gradle 설정
implementation 'ch.qos.logback:logback-classic:1.2.3'
logback.xml 예시
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="STDOUT" />
</root>
</configuration>
이 설정은 로그 메세지를 콘솔에 출력하며, 메세지 포맷은 시간, 스레드 이름, 로그 레벨, 로거 이름, 메세지 순으로 구성된다.
Log4j2
Log4j2는 Log4j와 Logback의 개선 사항을 포함하여 더욱 발전된 기능을 제공하는 로깅 프레임워크이다. 비동기 로깅, 로그 문장의 지연 평가, 가비지 수집기 작업으로 인해 발생하는 대기 시간을 방지하기 위한 garbage-free mode 등을 지원하여 성능과 유연성을 크게 향상 시켰다.
샘플 코드
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Log4j2Example {
private static final Logger logger = LogManager.getLogger(Log4j2Example.class);
public void performSomeOperation() {
logger.info("로그 내용");
}
}
Log4j2이 가장 진일보한 최신 라이브러리지만, 최근 들어 보안 문제가 발생하며 대대적인 이슈를 낳은적이 있다. 우리 회사에서도 라이브러리를 사용한 사람들에게 코드 변경을 권고 했었는데 Log4j와 Log4j2를 사용하지 않아서 개인적으로는 문제가 없었으나, 다른 팀이나 파트 사람들은 코드를 고치느라 작업을 꽤 많이 했던 것으로 기억이 난다.
Maven 설정
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.22.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.22.1</version>
</dependency>
Gradle 설정
implementation 'org.apache.logging.log4j:log4j-api:2.22.1'
implementation 'org.apache.logging.log4j:log4j-core:2.22.1'
취약점 관련 보도
한동안 떠들썩 하던 보안 경고는 사실 끝난 것이 아닐지도 모른다. 그래서, Log4j 혹은 Log4j2보다는 Logback을 사용하길 권고하고 싶다. 특히 Log4j2는 특별한 일이 없으면 웬만하면 사용을 자제하는 것이 좋을 것이다.
'프로그램언어 > 자바(Java)' 카테고리의 다른 글
[Java] OracleJDK 21, 설치 및 세팅하기 (OpenJDK 비교 및 라이센스) (1) | 2024.01.22 |
---|---|
[Java] 자바로 파일 복사하는 3가지 방법 (0) | 2022.04.29 |
[Java] List 데이터 저장 역순 (reverse) (0) | 2022.04.27 |
[Java] 하위 폴더 및 파일 삭제 (재귀 함수 포함) (0) | 2022.04.10 |
[Java] Http URL File download 3가지 방법 (0) | 2021.12.29 |