글 작성자: beaniejoy
  • Overview
  • Slf4j 정의
    - Facade Pattern
    -Slf4j Facade
  •  Slf4j 사용
  • 결론

 

📌 1. Overview

프로젝트에 log4j2 적용 및 Slf4j를 줄곧 사용해왔는데 문득 log4j2Slf4j 속에 담겨진 개념이라든가 특징에 대해서 찾아본 적이 없었던 것 같습니다. 그래서 해당 내용에 대해 여러 문서들을 찾아보며 정리한 내용을 기록하고자 합니다.
(log4j 및 log4j2 특징은 다른 게시글에 정리해보겠습니다.)

이번 게시글은 Slf4j에 대한 내용만 담아보려 합니다.

 

📌 2. Slf4j 정의

SLF4J는 Simple Logging Facade for Java 의 줄임말입니다. 어떤 단어나 개념을 접할 때 저는 늘 풀네임 자체에 주목을 해서 서칭을 해보는 편입니다.

"Simple".. 간단한, "Logging".. 로깅처리, "Facade".. (찾아봐야겠군), "for Java"... 자바에서 사용하는 - 이런 식으로 접근해보니 다른 것보다 Facade가 눈에 띄어 이와 관련해서 찾아봤습니다.

 

🔖 2-1. Facade Pattern

디자인 패턴에 대해서는 대표적인 케이스에 대해서만 공부했었는데 Facade가 수많은 디자인 패턴 중 하나라는 것을 이번에 처음알았습니다. 위의 링크는 여러 자료들을 봤을 때 제 개인적으로 Facade에 대해서 가장 잘 설명한 게시글이라 생각되어 링크를 걸었습니다.

Facade는 외관이라는 뜻을 가졌는데요. 말 그대로 어떤 복잡한 코드를 내부로 감추고 깔끔한 외관으로 보여줌으로써 사용자가 편리하게 이용할 수 있도록 해주는 디자인 패턴이라고 할 수 있습니다.
위키에서는 "클래스 라이브러리 같은 어떤 소프트웨어의 다른 커다란 코드 부분에 대한 간략화된 인터페이스를 제공하는 객체이다." 라고 정의했는데요. 소프트웨어 측면에서 Facade는 주로 복잡한 라이브러리를 대상으로 간편하게 사용할 수 있는 인터페이스라고 할 수 있습니다. 

class CPU {
	public void freeze() { ... }
	public void jump(long position) { ... }
	public void execute() { ... }
}

class Memory {
	public void load(long position, byte[] data) {
		...
	}
}

class HardDrive {
	public byte[] read(long lba, int size) {
		...
	}
}

/* Façade */
class Computer {
	public void startComputer() {
		CPU cpu = new CPU();
		Memory memory = new Memory();
		HardDrive hardDrive = new HardDrive();
		cpu.freeze();
		memory.load(BOOT_ADDRESS, hardDrive.read(BOOT_SECTOR, SECTOR_SIZE));
		cpu.jump(BOOT_ADDRESS);
		cpu.execute();
	}
}

/* Client */
class You {
	public static void main(String[] args) throws ParseException {
		Computer facade = /* grab a facade instance */;
		facade.startComputer();
	}
}

 

Wiki에 제시된 예제를 그대로 가져왔습니다.
여기서 CPU, Memory, HardDrive는 3rd-party가 제공하는 라이브러리의 클래스 예시라고 생각하고 접근하면 이해가 쉽습니다. 라이브러리를 가져다 사용하는 입장에서 저희가 3rd-party library에 대해서 수정할 수는 없습니다.
(CPU, Memory, HardDrive 클래스에 대한 내용을 simplify할 수 없다는 의미이기도 합니다.)

cpu를 실행시키기 위해서는 해당 클래스들을 가져다가 복잡한 방법에 의한 코드를 작성해야할 것입니다. 문제는 여기에 있습니다.
만약 해당 라이브러리를 다른 것으로 교체했을 때 어떻게 될까요. 교체된 라이브러리 내부의 클래스들 또한 내용이 바뀌었기 때문에 기존에 cpu 실행 코드들을 전부다 수정해야할 것입니다. 단순히 라이브러리 하나 교체했을 뿐인데 모든 코드를 갈아엎어야하는 상황인 것입니다.

여기서 Computer(Facade) 클래스가 등장하는데 라이브러리에 담겨진 클래스들을 이용한 cpu 실행하는 복잡한 코드들을 하나의 메서드로 담았습니다. 이렇게 되면 Client에서는 Computer 클래스의 startComputer 메서드만 적용해도 해당 라이브러리 내부 코드를 몰라도 cpu를 실행시킬 수 있습니다.

즉 Facade 핵심은 공통된 토픽의 여러 라이브러리에 대해서 통일된 방식으로 사용할 수 있는 인터페이스를 제공해준다는 것입니다.

 

🔖 2-2. Slf4j Facade

Slf4j는 위에서 언급했듯이 Logging Facade입니다. 즉 Logging 관련된 여러 라이브러리에 대한 통일된 사용방식(통일된 API)을 제공해준다고 할 수 있습니다. 위 그림과 같이 log4j, logback, log4j2 어떤 라이브러리를 사용하든 Slf4j를 통해서 사용하면 기존 소스코드를 수정할 일이 전혀 없다는 것이 강점이라고 할 수 있습니다.

 

📌 3. Slf4j 사용

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

public class LoggingService {
	private static final Logger logger = LoggerFactory.getLogger(LoggingService.class);

	//...
    
    public void log() {
    	logger.info("Logging");
    }
}

직접 Logger 객체를 생성해서 logging하는 방법이 있습니다. 

compileOnly 'org.projectlombok:lombok'
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class LoggingService {
	
	//...
    
    public void log() {
    	log.info("Logging");
    }
}

Lombok을 이용해서 annotation으로 바로 적용한 내용입니다. 저는 주로 이 방법을 사용해서 logging을 하고 있습니다.

 

📌 4. 결론

주로 사용법보다 Slf4j의 개념과 왜 사용하는지에 대해 정리를 해보았습니다. 원래 log4j > log4j2 사용한 이유에 대해 포스팅을 하려고 했는데 여기서 Slf4j를 사용하다보니 갑작스런 궁금증에 먼저 포스팅을 하게 되었습니다.

제가 찾아본 내용을 이렇게 정리해보니 습관적으로 사용해왔던 Slf4j를 이제는 이유를 알고서 잘 사용하게 될 것 같네요.

 

틀린 내용이 있을 수 있습니다. 이에 대한 코멘트 언제나 환영입니다!