Spring - Log4j

개미는뚠뚠·2023년 6월 3일
1

Spring

목록 보기
3/4
post-thumbnail

일단 Log4j가 Spring의 카테고리가 맞는지는 의문이다. 하지만 내가 현재 스프링으로 개발중이고, 실제 여기서 쓰고 있기 떄문에 해당 카테고리로 뺐다. 왜? 내 블로그니까!!!! 암턴 내가 Spring을 통해 처음 개발을 진행했을 때 console로 결과 값을 찍기 다음과 같이 항상 결과값을 찍었다.

System.out.println("data", data);

하지만 선배 개발자의 말로는 좋은 방식이 아니다!!!!! 앞으로는

log.info("data"+data);

이걸 사용하도록 해!!!!!라면서 강조하셨고 나는 일단 "네...?네..."하면서 여태 사용하고 있다. 그러나 이번 주말을 확용하여 그 이유를 개인적으로 찾아보고 공부하기로 하였다.

평소에 잘 신경을 안 쓰는 기초적인 부분이라고 생각하지만 뭐든 알아가면 좋은거니까!

System.out.println() 과 Log4j

어쨰서 System.out.println()으로 로기을 하는 것이 문제가 되는 것일까?

그 내용은 다음과 같다.

1.휘발성

System.out.println() 은 로그가 표준 출력으로 출력된다.
이 말이 무엇이냐면 파일로 저장되지 않고 없어진다는 얘기이다. 우리가 로그를 찍는 이유는 단순히 결과값을 찍기 위함일까? 아니다. 로그는 시스템 운영 중 발생한 에러 상황을 기록하고, 추후 문제를 진단하고 디버깅을 위해 사용된다. 하지만 한번 출력되고 기록이 남지 않는다면 그것은 로그의 제 역할을 할 수 없다고 생각한다.

2.출력 단계 구분을 할 수 없다.
우리가 개발할 때에는 디버깅을 위해 많은 정보를 출력한다. 하지만, 프로덕션에서 동작하는 코드는 에러/장애가 발생할 때 불필요한 정보를 제외하고 문제를 진단할 수 있는 정보만을 남겨야한다. 이후 설명할 로깅 라이브러리는 Logback이라는 라이브러리에서는 TRACE, DEBUG, INFO, WARN, ERROR, FATAL 등 log단계를 구분하여 정보를 출력하는 기능이 있다. 하지만 System.out.println()은 이와 같은 기능을 제공하지 않는다. 즉 불필요한 정보를 동시에 제공하거나, 찾고자 하는 정보를 찾을 때 구분이 없어 불편함을 느낄 것이다.

3.성능저하

선배 개발자가 나에게 log.info를 사용하라고 했던 것은 이 이유가 가장 컸다. 성능저하를 강조하시면서 이게 좋아요!!! 알겠죠?!라고 영업하셨기 떄문에 일단 썼다...일단 어리버리한 표정으로 선배를 바라보았지만 뭐,,,3개월차 신입이 어쩌겠어!?!?!!써야지....
서론을 떠나서 표준 프레임워크 퍼스트북에 설명이 나와있다.표준 프레임워크 퍼스트북에도
"System.out.println()을 호출하게 되면 디스크 I/O 동기화 처리가 되기 때문에 전체적인 시스템의 성능이 저하 될 수 있다 라는 말이 있다.
다른 블로그를 읽었을 때 newLine()을 호출하고 자세하게 설명이 되어있었지만 현재 레벨이서는 무슨 말인지 잘 모르겠다ㅎ..근데 대충 어떤 개념인지는 인지하였다.
암턴 println은 CPU 리소스를 점유하게 된다. 뭐 중간중간 결과값을 잠깐 찍는 것은 상관 없겠지만 안 그래도 트래픽이 많고, 처리하는 데이터 양이 많을 때 저런 짜잘한 로깅 때문에 시스템에 영향이 간다는데 안 쓰는게 맞지 않을까?

뭐 대충 ㅇㅋ System.out.println()은 위와 같은 이유로 쓰지말래요. 안 쓸건데 그럼 뭘 써요?
개인적으로 현재 내가 쓰고 있는 Log4j 를 많이 사용한다고 들었다.

그렇다면 이 Log4j 가 대체 뭔데? 지금부터 알아보자.

Log4j란?

Log4j : Log for Java
로그문의 출력을 다양한 대상으로 할 수 있도록 도와주는 도구(오픈소스)

라고 한다.
오픈소스로 접근성도 쉽고 사용자도 많을 것이다. 그렇다고 들었다.

Log4j 특징

  • log4j는 속도에 최적화
  • log4j는 이름있는 로그 계층에 기반
  • log4j는 fail-stop이지만 신뢰성은 없음
  • log4j는 thread-safe(멀티스레드 환경에서 사용해도 안전하다:역주).
  • log4j는 융통성이 풍부
  • 설정 파일은 property 파일과 XML 형식으로 실행 중 수정 적용 가능
  • log4j는 처음부터 자바의 예외를 처리하기 위해 디자인
  • log4j는 출력을 파일, 콘솔, java.io.OutputStream, java.io.Writer, TCP를 사용하는 원격서버, 원격 Unix Syslog 데몬, - 원격 JMS 구독자, 윈도우NT EventLog로 보낼 수 있고, 심지어는 e-mail로 보낼 수도 있음
  • log4j는 다음 6단계의 장애레벨을 사용. < TRACE(추가), DEBUG, INFO, WARN, ERROR, FATAL >
  • 로그 출력의 형식은 Layout 클래스를 확장함으로써 쉽게 바꿀 수 있음
  • 로그가 출력될 대상과 출력 방법은 Appender 인터페이스로 할 수 있음
  • log4j는 로거 하나에 다수의, 출력을 담당하는 appender를 할당할 수 있음
  • log4j는 국제화를 지원

Log4j 레벨

나도 평소 개발할 때 해당 규칙을 다 지켜가면서 개발하는 것은 아니지만 글을 정리하면서 상황에 맞게 해당 레벨을 인지하고, "구분해서 사용해야겠다" 생각했다. 내가 평소에 계속 썼던 거 = log.info만 주구장창

FATAL
아주 심각한 에러가 발생한 상태. 시스템적으로 심각한 문제가 발생해서 어플리케이션작동이 불가능할 경우가 해당하는데, 일반적으로는 어플리케이션에서는 사용할 일이 없음

ERROR
요청을 처리하는 중 문제가 발생한 상태를 나타냄

WARN
처리 가능한 문제이지만, 향후 시스템 에러의 원인이 될 수 있는 경고성 메시지를 나타냄

INFO
로그인, 상태변경과 같은 정보성 메시지를 나타냄

DEBUG
개발시 디버그 용도로 사용한 메시지를 나타냄

TRACE
log4j1.2.12에서 신규 추가된 레벨로서, DEBUG 레벨이 너무 광범위한 것을 해결하기 위해서 좀 더 상세한 상태를 나타냄

솔직히 Log4j 를 집중해서 쓰려던게 아니라 개념, 장정, 레벨 정도만 정리하고 실제 프로젝트에 어떻게 사용하는지만 정리하고 글을 마무리 하려고 한다.

그렇다면 우리는 이 좋다는 Log4j를 어떻게 프로젝트에서 사용할 것인가?

프로젝트에서 Log4j 사용방법

1.pom.xml - Log4j라이브러리 추가

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

2.log4j.xml / log4j.properties 작성

log.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
    <!-- 콘솔 로그 -->
    <appender name="infoConsole" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[%5p] %d{hh\:mm s} (%F\:%L) %c{1}.%M \: %m%n" />
        </layout>  
    </appender>
    <!-- root 설정 -->
    <root>
        <level value="INFO" />
        <appender-ref ref="infoConsole" />
    </root>
</log4j:configuration>

log4j.properties

####### Global logging configuration
log4j.rootLogger=INFO, stdout
####### stdout Appender
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%5p] %d{hh\:mm s} (%F\:%L) %c{1}.%M \: %m%n

3.web.xml 작성

    <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>
            classpath:project/config/log4j.xml
        </param-value>
    </context-param>
    <!-- Log4j -->
    <listener>
        <listener-class>
            org.springframework.web.util.Log4jConfigListener
        </listener-class>
    </listener>

모든 작업을 마무리하고, 실제 코드에서 다음과 같이 log를 테스트 해보았다.

물론 나도 아직 Log4j에 대해서 그렇게 자세히 알지는 못한다. System.out.println() 이 정확히 어떤 영향을 미치는지도 100퍼센트 알지도 못하고...하지만 이렇게 시간을 내어 글을 정리할 수 있어서 의미있는 시간이였다고 생각한다. 아직도 많이 부족하지만 더 열심히 공부해보자구🔥

0개의 댓글