Logging

마이바티스는 내부 로그 팩토리를 사용하여 로깅 정보를 제공한다. 내부 로그 팩토리는 로깅 정보를 다른 로그 구현체 중 하나에 전달한다.

  • SLF4J
  • Apache Commons Logging
  • Log4j 2
  • Log4j
  • JDK logging

로깅 솔루션은 내부 마이바티스 로그 팩토리의 런타임 체크를 통해 선택된다. 마이바티스 로그 팩토리는 가능하면 첫번째 구현체를 사용할 것이다(위 로깅 구현체의 나열 순서는 내부적으로 선택하는 우선순위이다). 만약 마이바티스가 위 구현체중 하나도 찾지 못한다면 로깅을 하지 않을 것이다.

많은 환경은 애플리케이션 서버(좋은 예는 톰캣과 웹스피어)의 클래스패스의 일부로 JCL 을 사용한다. 이러한 환경을 아는 것이 중요하다. 마이바티스는 로깅 구현체로 JCL 을 사용할 것이다. 웹스피어와 같은 환경에서 Log4J 설정은 무시될 것이다. 왜냐하면 웹스피어는 자체 JCL 구현체를 제공하기 때문이다. 이러한 사항은 불만스러울수 있다. 왜냐하면 마이바티스는 당신의 Log4J 설정을 무시하는 것처럼 보일수도 있기 때문이다. (사실 마이바티스는 당신의 Log4J 설정을 무시한다. 왜냐하면 마이바티스는 이러한 환경에서 JCL 을 사용할 것이기 때문이다.) 만약 당신의 애플리케이션이 클래스패스에 JCL 을 포함한 환경에서 돌아가지만 다른 로깅 구현체 중 하나를 더 선호한다면 다음의 메소드 중 하나를 호출하여 다른 로깅 구현체를 선택 할 수 있다.

org.apache.ibatis.logging.LogFactory.useSlf4jLogging();
org.apache.ibatis.logging.LogFactory.useLog4JLogging();
org.apache.ibatis.logging.LogFactory.useJdkLogging();
org.apache.ibatis.logging.LogFactory.useCommonsLogging();
org.apache.ibatis.logging.LogFactory.useStdOutLogging();

마이바티스가 메소드를 호출하기 전에 위 메소드 중 하나를 호출해야 한다. 이 메소드들은 런타임 클래스패스에 구현체가 존재하면 그 로그 구현체를 사용하게 한다. 예를들어 Log4J 로깅을 선택했지만 런타임에 Log4J 구현체가 클래스패스에 없다면 마이바티스는 Log4J 구현체의 사용을 무시하고 로깅 구현체를 찾아 다시 사용할 것이다.

SLF4J, Jakarta Commons 로깅, Log4J 그리고 JDK 로깅 API 에 대한 설명은 이 문서의 범위를 벗어난다. 이러한 로깅 관련 프레임워크에 대해 좀더 알고 싶다면 개별 위치에서 좀더 많은 정보를 얻을 수 있을 것이다.

Logging Configuration

마이바티스 로깅 구문을 보기 위해서 패키지, 매퍼의 전체 경로, 구문명의 명명공간에 대해 활성화해주어야 할것이다.

다시 얘기해서 사용할 로깅 구현체에 따라야 하고 우리는 Log4J를 사용하는 방법을 보여줄 것이다. 로깅 설정은 대부분 하나 이상의 설정파일(예를들면, log4j.properties)과 몇개의 새로운 jar파일(예륻를면, log4j.jar)을 다룬다. 다음의 설정예제는 Log4J를 사용하여 설정하고 2단계로 설정한다.

첫번째 단계 : Log4J JAR 파일 추가하기

Log4J를 사용하기 때문에 애플리케이션에 JAR 파일이 있어야 한다. Log4J 를 사용하기 위해 애플리케이션의 클래스패스에 JAR 파일을 추가할 필요가 있다. 위 URL 에서 Log4J 를 다운로드 할 수 있다.

웹이나 기업용 애플리케이션에서는 WEB-INF/lib 디렉터리에 log4j.jar 파일을 추가할 수 있다. 단독으로 실행되는 애플리케이션에서는 JVM의 -classpath 시작 파라미터에서 간단히 추가할 수 있다.

두번째 단계 : Log4J 설정하기

Log4J 를 설정하는 것은 간단하다. 다음의 매퍼를 위한 로깅을 활성화하려고 한다고 해보자.

package org.mybatis.example;
public interface BlogMapper {
  @Select("SELECT * FROM blog WHERE id = #{id}")
  Blog selectBlog(int id);
}

아래처럼 log4j.properties파일을 만들어서 클래스패스에 두자.

# Global logging configuration
log4j.rootLogger=ERROR, stdout
# 마이바티스 로딩 설정...
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# 콘솔 출력...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

위 파일은 org.mybatis.example.BlogMapper의 상세한 로그와 애플리케이션의 에러들을 출력할 것이다.

finer레벨로 로깅을 하고자 한다면 전체 매퍼 파일대신 특정 구문만을 로깅할 수 있다. 다음 줄은 selectBlog구문의 로그를 출력하도록 한다.

log4j.logger.org.mybatis.example.BlogMapper.selectBlog=TRACE

반대로 특정 매퍼들에 대해 로깅을 원할 수 있다. 이 경우 매퍼의 가장 상위 패키지에 로거를 추가할 수 있다.

log4j.logger.org.mybatis.example=TRACE

큰 결과를 리턴할 수 있는 쿼리가 있다. 이 경우 결과가 아닌 SQL구문만을 보고자 할 수 있다. 이러한 목적으로 SQL구문은 DEBUG레벨(JDK로깅에서는 FINE)로 지정하고 결과에 대해서는 TRACE레벨(JDK로깅에서는 FINER)로 지정한다. 결과가 아닌 구문만 보고자 하는 경우에는 DEBUG로 레벨을 설정하자.

log4j.logger.org.mybatis.example=DEBUG

다음처럼 매퍼 인터페이스가 아닌 매퍼 XML을 사용하다면 어떻게 해야 할까?

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.mybatis.example.BlogMapper">
  <select id="selectBlog" resultType="Blog">
    select * from Blog where id = #{id}
  </select>
</mapper>

이런 경우에는 아래처럼 명명공간을 추가해서 XML파일 전체를 로깅할 수 있다.

log4j.logger.org.mybatis.example.BlogMapper=TRACE

또는 특정 구문만을 로깅하기 위해서는

log4j.logger.org.mybatis.example.BlogMapper.selectBlog=TRACE

앞서 언급한것처럼 매퍼 인터페이스와 XML매퍼 파일간의 차이는 없다.

log4j.properties 파일의 나머지는 어펜더(appender)를 설정하기 위해 사용했다. 어펜더는 이 문서의 범위를 넘어선다. Log4J 웹사이트에서 좀더 많은 정보를 얻을 수 있다. 설정파일간의 차이는 실행을 해보면 간단히 확인할 수 있다.