Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

Spring Framework에서 SLF4J의 설정 문제

간단하게 Spring MVC설정을 하려고 해서 아주 간단한 프로젝트였으므로 Spring Framework와 로깅, JUnit만으로 간단하게 구성하려고 하였으나 의존성 라이브러리 설정에서 문제를 겪으면서 잘 설정이 되지 않았습니다. 이것때문에 엄청난 삽질을 했는데 일단 해결을 하고 나니 로깅 프레임워크에 대한 지식이 전무했기 때문에 발생한 일이었습니다.(그래도 삽질 해보고 나니 어렴풋이나마 이해를 하게 되었습니다. 역시 개발은 삽질부터인가요? ㅎㅎㅎ)


<!-- Spring dependencies -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>org.springframework.spring-library</artifactId>
    <type>libd</type>
    <version>3.0.5.RELEASE</version>
    <exclusions>
        <exclusion>  <!-- declare the exclusion here -->
            <groupId>javax.servlet</groupId>
              <artifactId>com.springsource.javax.servlet</artifactId>
        </exclusion>
    </exclusions> 
</dependency>

<!-- logging -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>com.springsource.slf4j.org.apache.log4j</artifactId>
    <version>1.6.1</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>com.springsource.slf4j.jcl</artifactId>
    <version>1.6.1</version>
</dependency>

위는 프로젝트에 제가 설정한 pom.xml의 일부입니다. SpringSource Enterprise Bundle Repository에서 Spring Framework 3.0.5.REASE 전체를 가져왔으며 로깅을 위해서 slf4j를 가져왔습니다. 결과적으로는 이상한 의존성을 끌어와 버린 것인데 왜 이런 의존성라이브러리를 가져왔냐 하면 이전에 여러번 했던 프로젝트에 있던 pom.xml을 참고했는데 그 pom.xml에 slf4j가 있었기 때문에 그대로 slf4j를 사용했던 것입니다. 사실 처음에는 앞의 com.springsource.slf4j.org.apache.log4j부분만 있었는데 제가 구성한 것에는 이상하게 LogFactory오류가 나서 그것을 해결하던 와중에 com.springsource.slf4j.jcl을 추가했던 것입니다.

여기서 사용되는 각 로깅 라이브러리에 대한 이해도가 전혀 없다 보니 그냥 문제를 해결하기 위해서 막 끼워넣다보니 위와같은 상황이 발생했고 위와 같이 의존성을 가진 상태에서 WAS를 실행시키면 서버를 실행시키다가 엄청난 랙이 걸린 후에 OutOfMemory : Java Heap Space 오류가 로깅쪽에서 발생하면서 죽어버립니다. Arawn의 도움으로 문제를 파악한 바로는 slf4j와 jcl의 바인딩이 꼬여서 인스턴스 생성이 무한루프에 빠지면서 결국 메모리 오류까지 이어지는 것으로 보입니다.

  • Log4j : Apache의 프로젝트로 Ceki Gulcu가 만든 자바기반의 로깅 유틸리티입니다.
  • JCL (Jakarta Commons Logging) : Log4j, LogKit, JDK1.4같은 다른 로킹툴에 대한 추상화 계층을 제공하는 로그 인터페이스입니다.
  • SLF4J (Simple Logging Facade for Java) : log4j나 logback, java.util.loggin같은 여러가지 로깅프레임워크를 위한 간단한 facade나 추상화를 제공합니다.

각 라이브러리의 특징을 보면 JCL과 SLF4J의 역할이 동일한 것으로 보이는데 (봄싹 메일링에 질문해보니) 저같은 경우에는 slf4j의 log4j와 jcl 바인딩을 둘 다 사용해서 문제가 된 것이었습니다.

log4j바인딩과 jcl바인딩이 모두 존재하는 의존성 그래프

slf4j 의존성 그래프를 보면 JCL에 대한 의존과 Log4j에 대한 의존성이 동시에 존재하는 것을 볼 수 있습니다.(그렇게 셋팅했으니 당연한 얘기지만요 ㅡㅡ;;)

이 부분에 대해서는 Whiteship님의 블로그에 아주 잘 정리가 되어 있습니다. 처음 봤을때는 무슨 말인지 잘 몰랐는데 좀 삽질하고 찾아보고 나니 상당히 명확해 졌습니다. JCL을 사용하던지 Log4j를 사용했어야 했던 것이었는데요. 저같은 경우에는 스프링이 JCL에 의존하고 있는 관계로 SLF4J만 가져왔을때 JCL에 대한 의존성 때문에 오류가 난 것은 해결하려고 JCL을 가져온 것이 문제였던 듯 합니다.

새로 pom.xml을 설정한 뒤의 slf4j 의존성 그래프

Whiteship님의 블로그에 나온대로 의존성을 설정하고 나면 이제 의존성 그래프가 JCL에 대한 의존성은 SLF4j가 받아주고 Log4j만 사용하도록 사용하도록 되었습니다.(아직 다 이해못해서 제대로 설명(?)한건지 잘 모르겠군요.)
2010/12/01 01:43 2010/12/01 01:43