
로그는 프로그램 실행 중 발생하는 다양한 사건 (이벤트)들을 기록하는 것이다.
예를 들어, 프로그램이 제대로 동작하는지, 어디서 문제가 발생했는지 등을 추적할 수 있도록 돕는다.
로그의 주요 활용처는 다음과 같다.
1. 이벤트 기록
2. 문제 해결
3. 운영 모니터링
4. 보안 감사
로그는 간단히 말해, 프로그램이 '무슨 일을 언제 어떻게' 했는지를 남기는 기록부라고 생각될 것이다.
로깅 (Logging)은 애플리케이션의 오류를 추적할 수 있는 기능을 제공하는 API이다. 애플리케이션이 로깅 호출을 생성하면 Logger가 LogRecordfile에 이벤트를 기록한다. 그런 다음 해당 핸들러 (handler) 또는 어펜더 (appender)로 이벤트를 보낸다. 콘솔이나 파일로 보내기 전에 어펜더는 포맷터 또는 레이아웃을 사용하여 로그 기록을 포맷한다.
Java 로깅 라이브러리 / 프레임워크

SLF4J는 Java를 위한 Simple Logging Facade 또는 SLF4J로 알려져 있다. 다양한 로깅 프레임워크를 위한 추상화 계층으로, 개발 시점이 아닌 배포 시점에 사용자가 로깅 프레임워크를 선택할 수 있다.
따라서 필요할 때 원하는 로깅 프레임워크를 빠르고 쉽게 변경할 수 있다.
(애플리케이션에서는 SLF4J 인터페이스만 사용하면 되고, 실제 어떤 로깅 라이브러리를 쓸지는 SLF4J가 알아서 연결해 주는 구조이다.)
java.util.logging 패키지는 Java 핵심 로깅 기능을 위한 클래스와 인터페이스를 제공한다.
Java 개발 키트와 함께 번들로 제공되며 Java 1.4 이후 Java를 사용하는 모든 개발자가 사용할 수 있다.
Log4j는 가장 널리 알려진 Java 로깅 라이브러리 중 하나이며 Logback 또는 Log4j 2와 같은 프로젝트의 전신다.
그러나 Log4j는 2015년 8월 5일에 수명이 종료되었으며 사용자는 Log4j 2를 사용할 것을 권장한다.
Logback은 Log4j의 첫 번째 버전의 후속 버전으로 시작되었다.
세 가지 주요 모듈로 구성되어 있으며, Tomcat 또는 Jetty와 같은 서블릿 컨테이너와 통합되어 HTTP 액세스 로그 기능을 제공한다.
Log4j 2는 앞서 언급한 모든 Java 로깅 프레임워크 목록에서 가장 최신 버전이다.
이전 버전에 비해 많은 개선 사항이 포함되어 있으며 일부 아키텍처 문제를 해결하면서 Logback 개선 사항을 제공할 것을 약속한다. 새 프로젝트를 시작하면서 선택할 라이브러리를 찾고 있다면 Log4j 2를 중점적으로 고려한다.
프로그램 실행 중에 발생하는 여러 이벤트나 정보를 기록하는 도구이다. SLF4J나 Log4j, Logback 같은 로깅 프레임워크를 통해, 로그 레벨 (TRACE, DEBUG, INFO, WARN, ERROR)에 맞춰서 로그를 남길 수 있다.
로그를 통해 에러 상황을 파악하거나, 프로그램 흐름을 추적하고, 운영 환경에서 모니터링하는 데 도움을 준다.
주요 메서드는 다음과 같다.
| 메서드 | 로그 레벨 | 설명 |
|---|---|---|
| trace() | TRACE | 가장 상세한 로그, 주로 개발 중 상세한 디버깅이 필요할 때 사용 |
| debug() | DEBUG | 디버깅 목적으로, 개발 단계에서 주로 사용 |
| info() | INFO | 운영 환경에서 유용한 정보나 정상 동작을 알리는 로그 |
| warn() | WARN | 잠재적 위험이 될 수 있는 상황을 알리는 로그 |
| error() | ERROR | 치명적인 오류나 예외 상황에 대한 로그 |
LoggerFactory는 SLF4J에서 제공하는 팩토리 클래스로 애플리케이션 코드에서 직접 Logger 인스턴스를 생성하지 않고, LoggerFactory의 메서드를 통해 Logger 인스턴스를 얻음으로써, 뒤에 연결된 실제 로깅 구현체(Logback, Log4J 등)와의 결합도를 낮출 수 있다.
팩토리 패턴 : LoggerFactory는 팩토리 패턴을 사용해서 Logger 인스턴스를 생성한다. 즉, 인스턴스 생성을 캡슐화하여, 코드가 구체적인 Logger 생성 로직에 의존하지 않도록 한다.
추상화 제공 : LoggerFactory를 사용하면, 로깅 구현체를 변경하더라도 코드의 변경 없이 동일한 Logger 인터페이스를 통해 로깅할 수 있다. 이는 애플리케이션의 유지보수성과 유연성을 높여준다.
중앙 관리 : Logger 인스턴스를 생성하는 책임을 중앙화하여, 각 클래스별로 일관된 로깅 구성을 적용할 수 있게 해준다.
| 메서드 | 설명 |
|---|---|
| getLogger(Class<?> clazz) | 지정한 클래스 이름을 기반으로 Logger 인스턴스를 반환 |
| getLogger(String name) | 지정한 이름으로 Logger 인스턴스를 반환 |
✍️ 예제 코드 작성
package com.example.logging;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LoggerExample {
// Logger 인스턴스 생성 (클래스별 구분)
private static final Logger logger = LoggerFactory.getLogger(LoggerExample.class);
public static void main(String[] args) {
// trace(): 가장 상세한 로그
String param = "TestParam";
logger.trace("Entering method X with param={}", param);
// debug(): 디버깅 목적으로 사용하는 로그
String userData = "sampleUserData";
logger.debug("User data: {}", userData);
// info(): 정상 동작 상황을 알리는 로그
logger.info("Application started successfully");
// warn(): 잠재적인 문제를 경고하는 로그
logger.warn("Disk space is running low");
// error(): 치명적인 오류 상황을 기록하는 로그
try {
int result = 10 / 0;
} catch (Exception e) {
logger.error("An unexpected error occurred", e);
}
}
}
[Java] Logger 이해
멋쟁이사자처럼 강의자료