과제를 하면서 프로젝트를 만드는 중,
log 기능을 만들다가 아래와 같은 에러를 만났다.
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/Users/USER/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-simple/1.7.36/a41f9cfe6faafb2eb83a1c7dd2d0dfd844e2a936/slf4j-simple-1.7.36.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/Users/USER/.gradle/caches/modules-2/files-2.1/ch.qos.logback/logback-classic/1.2.11/4741689214e9d1e8408b206506cbe76d1c6a7d60/logback-classic-1.2.11.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.SimpleLoggerFactory]
Exception in thread "restartedMain" java.lang.reflect.InvocationTargetException
⠀⠀
Caused by: java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on the classpath. Either remove Logback or the competing implementation (class org.slf4j.impl.SimpleLoggerFactory loaded from file:/C:/Users/USER/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-simple/1.7.36/a41f9cfe6faafb2eb83a1c7dd2d0dfd844e2a936/slf4j-simple-1.7.36.jar). If you are using WebLogic you will need to add 'org.slf4j' to prefer-application-packages in WEB-INF/weblogic.xml: org.slf4j.impl.SimpleLoggerFactory
위 에러 메세지를 대충 해석해보면 아래와 같다.
LoggerFactory가 Logback LoggerContext가 아닌데 Logback이 클래스 경로에 있습니다.
Logback 또는 경쟁 구현체를 제거합니다.
WebLogic을 사용하는 경우 애플리케이션 패키지에 'org.slf4j'를 추가해야 합니다.
이 에러는 SLF4J가 두 개의 바인딩을 발견했음을 알려주는 것 !
( 하나는 slf4j-log4j12-1.7.21.jar
에 / 다른 하나는 logback-classic-1.1.7.jar
에 )
위 에러 코드가 무슨 말인가 ~~ 하면 !
보통 Spring boot로 프로젝트를 만들게 되면 의존성으로 spring-boot-starter-web
과 같은 스타터를 추가하는데
그렇게 되면 내부적으로 Logback이 설정되어 로깅을 수행하고,
이 Logback은 SLF4J의 구현체 중 하나로,
@Slf4j
애너테이션이 적용된 클래스는 Lombok이 컴파일 시간에 해당 클래스에 로거 필드를 자동으로 추가하여 Logback을 사용하도록 한다고 한다.
따라서 @Slf4j
애너테이션을 사용하면 내부적으로 Logback이 로거로 동작하며, 로그 메시지를 출력한다.
그런데 로그 기능을 만들면서 build.gradle
에 SLF4J와 log4j 두개 모두 dependency를 추가하면서,
SLF4J는 한 번에 하나의 로깅 프레임워크에만 바인딩되는데,
클래스 경로에 둘 이상의 바인딩이 있어 에러가 발생한 것이었다.
✔ SLF4J
- facade 디자인 패턴을 사용한 로깅 프레임워크
- Log4j, LogBack 이 SLF4J 를 구현한 구현체
✔ facade 패턴
- 여러개의 클래스가 하나의 역할을 수행할 때, 대표적인 인터페이스만을 다루는 클래스를두어 원하는 기능을 처리할 수 있게 도와주는 패턴
build.gradle
의 configurations 부분에 표시해둔 부분을 추가하면 된다.
configurations {
compileOnly {
extendsFrom annotationProcessor
}
// 여기부터
configureEach {
exclude group: 'org.slf4j', module: 'slf4j-log4j12'
exclude group: 'log4j', module: 'log4j'
exclude group: 'org.slf4j', module: 'slf4j-jdk14'
exclude group: 'org.slf4j', module: 'slf4j-simple'
}
// 여기까지
asciidoctorExtensions
}
근데 나는 log4j 의존성 추가 안했는데 왜 났는지 모르겠지만 일단 저렇게 해결했다 !
< 참고한 사이트 >