SLF4J는 commons-loggin이 갖는 몇 가지 문제점(이 글에서 다룬 문제+클래스 로딩 문제 등)을 해결하면서 등장한 로깅 API입니다.
commons-loggin을 활용하는 방법은 간단하죠^^.
이 예는 DEBUG 수준의 로그를 남기게 됩니다. 하지만 이렇게 작성하면 큰 문제를 일으킵니다. 일반적으로 DEBUG 수준의 로그는 개발시나 디버깅 시에만 남기는데, 이렇게 코드를 해놓으면 로깅 수준에 관계 없이 항상 debug() 파라미터로 넘기는 문자열을 구성하게 됩니다.
위 예에서는 i와 String.valueOf(entry[i])라는 두 개의 파라미터를 받는데, 이 두 개의 인자를 처리해서 완성된 문자열로 만드는 작업에 드는 비용이 만만치 않습니다. 자바에서 String 처리는 상당한 비용을 사용하게 되죠..
이런 문제를 해결하는 방법으로 다음처럼 코드를 작성하게 됩니다.
실제로 로깅 메소드를 호출하기 전에, 해당 수준의 로깅을 해야할지 여부를 먼저 따져보게 됩니다. 그래서 로깅이 필요하면 남기고, 필요 없으면 남기지 않게 됩니다.
이렇게 하면 로깅을 하지 않아도 될 때는 파라미터를 구성하면서 문자열을 처리할 필요가 없게 됩니다. isDebugEnabled() 자체도 수행되는데 무시할 정도의 시간밖에 걸리지 않습니다.
하지만 그럼에도 아쉬운 점이 있습니다. 로깅을 하지 않아도 될 때는 isDebugEnabled()만 거치면 되지만, 실제 로깅을 남겨야 할 때는 isDebugEnabled() -> debug() 로 두 개의 메소드 호출이 일어 납니다.(아무리 작은 시간이 소모되더라도요..)
그리고 제가 생각하는 더 안 좋은 점은 코드가 상당히 껄끄러워 집니다. DEBUG와 INFO, WARN 수준의 로그를 연달아 남기고, DEBUG가 여러번 겹쳐서 나오기라도 하면 아주 정신이 다 없어 집니다@@.
SLF4J는 별도의 파라미터 포매팅 개념을 도입했습니다! 이른바 Parameterized loggin method.
코드를 보시면,
인자로 넘기는 코드는 없다치면, 실제로 로그를 남기는 코드만 남게 됩니다. isXXXEnabled() 메소드가 없어졌습니다. 대신 이른바 Formatting anchor로 불리는 '{}'가 등장했습니다. SLF4J는 로깅을 남겨야할 필요가 있을 때 {}를 메소드의 파라미터로 받은 값으로 교체하게 됩니다. 로깅을 남길 필요가 없는 상황에서는 문자열을 구성하지 않는 것이지요^^.
여기서 로깅을 남겨야하는 여부를 결정하는 행위의 주체가 SLF4J로 넘어가게 됐습니다.
이 두 로깅 코드는 거의 동일한 코드고, 완전 같은 로그 메세지를 남기지만, 성능은 30배 정도의 차이가 나게 됩니다. SLF4J는 별도의 파라미터 포매팅 구현을 사용합니다. 일반 포매팅 방법보다 10배 정도 빠르다고 합니다. 그래서 {}를 메소드 인자로 매핑하는데 크게 부하가 걸리지 않는다고 하네요..
SLF4J를 적용하면 바로 로깅 메소드를 호출해도 됩니다.^^
OSGi 환경에서는 클래스 로딩 문제로 commons-loggin 대신에 SLF4J를 사용하는데 그것 말고도 다양한 장점이 있네요. 많은 오픈소스들이 commons-loggin과 결별을 고하고, SLF4J로 갈아타고 있습니다.
함께 동참하시겠어요^^.
SLF4J에 대한 더 많은 궁금증은 FAQ에서 해결하실 수 있습니다.
commons-loggin을 활용하는 방법은 간단하죠^^.
logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
이 예는 DEBUG 수준의 로그를 남기게 됩니다. 하지만 이렇게 작성하면 큰 문제를 일으킵니다. 일반적으로 DEBUG 수준의 로그는 개발시나 디버깅 시에만 남기는데, 이렇게 코드를 해놓으면 로깅 수준에 관계 없이 항상 debug() 파라미터로 넘기는 문자열을 구성하게 됩니다.
위 예에서는 i와 String.valueOf(entry[i])라는 두 개의 파라미터를 받는데, 이 두 개의 인자를 처리해서 완성된 문자열로 만드는 작업에 드는 비용이 만만치 않습니다. 자바에서 String 처리는 상당한 비용을 사용하게 되죠..
이런 문제를 해결하는 방법으로 다음처럼 코드를 작성하게 됩니다.
if(logger.isDebugEnabled()) {
logger.debug("Entry number: " + i + " is " + String.valueOf(entry
[i]));
}
logger.debug("Entry number: " + i + " is " + String.valueOf(entry
[i]));
}
실제로 로깅 메소드를 호출하기 전에, 해당 수준의 로깅을 해야할지 여부를 먼저 따져보게 됩니다. 그래서 로깅이 필요하면 남기고, 필요 없으면 남기지 않게 됩니다.
이렇게 하면 로깅을 하지 않아도 될 때는 파라미터를 구성하면서 문자열을 처리할 필요가 없게 됩니다. isDebugEnabled() 자체도 수행되는데 무시할 정도의 시간밖에 걸리지 않습니다.
하지만 그럼에도 아쉬운 점이 있습니다. 로깅을 하지 않아도 될 때는 isDebugEnabled()만 거치면 되지만, 실제 로깅을 남겨야 할 때는 isDebugEnabled() -> debug() 로 두 개의 메소드 호출이 일어 납니다.(아무리 작은 시간이 소모되더라도요..)
그리고 제가 생각하는 더 안 좋은 점은 코드가 상당히 껄끄러워 집니다. DEBUG와 INFO, WARN 수준의 로그를 연달아 남기고, DEBUG가 여러번 겹쳐서 나오기라도 하면 아주 정신이 다 없어 집니다@@.
SLF4J는 별도의 파라미터 포매팅 개념을 도입했습니다! 이른바 Parameterized loggin method.
코드를 보시면,
Object entry = new SomeObject();
logger.debug("The entry is {}.", entry);
logger.debug("The entry is {}.", entry);
인자로 넘기는 코드는 없다치면, 실제로 로그를 남기는 코드만 남게 됩니다. isXXXEnabled() 메소드가 없어졌습니다. 대신 이른바 Formatting anchor로 불리는 '{}'가 등장했습니다. SLF4J는 로깅을 남겨야할 필요가 있을 때 {}를 메소드의 파라미터로 받은 값으로 교체하게 됩니다. 로깅을 남길 필요가 없는 상황에서는 문자열을 구성하지 않는 것이지요^^.
여기서 로깅을 남겨야하는 여부를 결정하는 행위의 주체가 SLF4J로 넘어가게 됐습니다.
commons-loggin: logger.debug("The new entry is "+entry+".");
SLF4J: logger.debug("The new entry is {}.", entry);
SLF4J: logger.debug("The new entry is {}.", entry);
이 두 로깅 코드는 거의 동일한 코드고, 완전 같은 로그 메세지를 남기지만, 성능은 30배 정도의 차이가 나게 됩니다. SLF4J는 별도의 파라미터 포매팅 구현을 사용합니다. 일반 포매팅 방법보다 10배 정도 빠르다고 합니다. 그래서 {}를 메소드 인자로 매핑하는데 크게 부하가 걸리지 않는다고 하네요..
SLF4J를 적용하면 바로 로깅 메소드를 호출해도 됩니다.^^
OSGi 환경에서는 클래스 로딩 문제로 commons-loggin 대신에 SLF4J를 사용하는데 그것 말고도 다양한 장점이 있네요. 많은 오픈소스들이 commons-loggin과 결별을 고하고, SLF4J로 갈아타고 있습니다.
함께 동참하시겠어요^^.
SLF4J에 대한 더 많은 궁금증은 FAQ에서 해결하실 수 있습니다.
-
-
-
-
산골소년 2008/12/17 14:20
방금 자바 소스 튜닝중..이문제로 골치썩다가...드디어 해결책을 발견했네요..
검색으로 우연히 들어왔는데..덕분에 해결되어 감사합니다..
그리고 결혼도 축하드립니다. ^ ^

Prev
Rss Feed


