디버그의 단점?
- 앱의 영향을 준다.
- 오류는 잡을 수 있지만 타이밍 오류는 잡을 수 없다.
Logging과 sysout의 차이
- Logging이 더 융통성 있다.
- 선택한 레벨 이상만 볼 수 있는 기능
- 전체도 가능하고 특정 모듈 또는 특정 클래스에 대해서 메시지를 출력할 수 있다.
- 메시지를 어떻게 모맷할지 설정할 수 있다.
- 메시지를 어디로 보낼 것인지 설정할 수 있다.
Logging Frameworks
- native java.util.logging: 많이 사용 안 함
- Log4J: 몇 년 전까지 표준
- Logback: Log4J 다음에 나온 제품(같은 개발자가 개발)
- SLF4J(Simple Logging Facade for Java): Log4J 나 Logback 같은 백앤드 logger framework를 위한 facade pattern
여러 개의 Logging Framework를 사용해야 하는 경우
- 여러 개의 Logging Framework는 각각의 API를 가지고 있다.
- 사용자의 상황에 따라 Logging Framework가 달라질 수 있는데 그때마다 API를 바꿔줘야 하는 불편함이 존재했다.
- facade pattern은 하나의 API로 여러 개의 Logging Framework를 사용할 수 있게 해 준다.
- SLF4J는 facade pattern이다. -> 따라서 SLF4J의 API만 알면 다른 Logging Framework를 다 사용 가능
※ Facade pattern
- 클라이언트는 요청을 'Facade'로 보내 서브 시스템과 통신한다.
- 이 요청은 적절한 Subsystem object로 요청을 전달.
- Subsystem object가 실제 작업을 수행하지만 'Facade'는 인터페이스를 Subsystem 인터페이스로 변환하기 위해 자체 작업을 수행해야 할 수도 있다.
- 'Facade'를 사용하는 클라이언트는 subSystem object에 직접 액세스 할 필요가 없다.
실제 적용)
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HelloWorld {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(HelloWorld.class);
logger.info("Hello World");
}
}
결과:
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
경고 이유:
- class path에서 SLF4J가 바인딩을 찾을 수 없기 때문
-> 바인딩 추가 필요! - 빌드를 할 때 Facade의 API를 이용하기 때문에 subsystem을 사용하지 않지만 실제로 running할 때는 subsystem이 필요하다. -> 따라서 Facade와 Subsystem과의 바인딩이 필요하다.
- SLF4J보다 Log4J가 먼저 나왔기 때문에 서로 다른 API를 사용한다.
-> 둘을 연결해주는 Adaptation이 필요! - SLF4J와 Logback은 서로 같은 API를 사용한다.
-> Adaptation 필요 X - Logging Framework를 변경하려면 class path에서 SLF4J의 바인딩을 바꿔주어야 한다.
예시) java.util.logging -> log4j ===> slf4j-jdk14.jar -> slf4j-log412.jar - 코드에서, sslf4j-api.jar 외에도, 원하는 class path 위치에 단 하나의 바인딩만 넣으면 된다.
- class path에 둘 이상의 바인딩을 넣으면 안 된다.
SLF4J binding with logback
- pom.xml에 dependency 하나만 추가해주면 된다.
-> maven의 장점(의존성을 파악해서 의존성이 있는 라이브러리까지 같이 다운로드하여준다.)
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
SLF4J를 이용하여 Logging 통합
- app에는 많은 모듈(라이브러리)이 포함되어있다. (controller, service, dao, slf4j, logback 등등)
- bridging 모듈을 사용하여 JCL, java.util.logging, log4j을 slf4j로 통합시키는 과정이 필요
-> 그래야 logback 사용 가능!
Logback
- log4j의 후임자 -> 더 빠르고 더 작은 자원 사용
- 요구사항
- slf4j-api.jar, logback-core.jar, logback.classic.jar( classpath에 추가 )
예시)
package chapters.introduction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HelloWorld1 {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger("chapters.introduction.HelloWorld1");
logger.debug("Hello world.");
}
- 위 코드는 lockback class를 참조하지 않는다.
- class는 SLF4J class들만 가져와야한다.
- 따라서 클래스는 SLF4J API를 사용하며 logback이 존재 X
- default configuration 파일이 없으면 logback은 default configuration policy를 제공한다.( logback.xml )
Log Printing Method ( 밑으로 갈수록 레벨 UP )
- trace
- debug
- info
- warn
- error
Parameterized Logging
//1번
logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]) );
//2번
if(logger.isDebugEnabled()) {
logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]) );
}
//3번
Object[] paramArray = {newVal, below, above};
logger.debug("Value {} was inserted between {} and {}.", paramArray);
- 1번 방식은 로그가 사용할 수 없는 경우에도 매개 변수 구성에 비용이 사용된다.
- 2번 방식은 if문으로 사용할 수 있는 logging인지 체크하여 1번 방식을 보완하지만 logger를 두 번 사용해야 하는 오버헤드가 발생한다.
- logging에 매개 변수를 주어 디버그 하는 동안에 합쳐질 수 있도록 하여 2번 방식을 보완했다.
References
http://logback.qos.ch/manual/index.html
http://www.slf4j.org/manual.html
http://www.slf4j.org/legacy.html
'Spring > 이론' 카테고리의 다른 글
Hibernate (0) | 2020.04.10 |
---|---|
Apache Tiles (0) | 2020.04.08 |
Spring Security (0) | 2020.03.30 |
Spring Web Form (0) | 2020.03.25 |
MVC(Model-View-Controller) (0) | 2020.03.17 |
댓글