티스토리 뷰

❓ 로깅, 왜 필요한데?

  • 버그에 대한 유용한 정보 제공
  • 프로그램 성능에 관한 통계와 정보 제공

 

💁🏻‍♀️ 그냥 println으로 로깅하면 안되나요?

  • 상황별로 로그를 조정, 처리 ❌
  • 로그를 별도로 저장 ❌
  • 대량의 로그를 print하면 성능↓

 

🔎 로깅 프레임워크

  • java,util.logging
  • Apache Commons logging
  • Log4J
  • Logback
  • SLF4J (Simple Logging Facade for Java)

 

✔️ SLF4J

 : 로깅 라이브러리들을 추상화해 놓은 것 (퍼사드 패턴 사용)

 : SLF4J의 구상체로 Logback, Log4J2 등을 사용할 수 있음

💡 Logback과 Log4J2와 같은 로깅 프레임워크를 번갈아 싶을 때, 코드를 바꾸지 않기 위해서 나온 것

 

 

🔎 로그 레벨

 : 어떠한 환경에 로그를 어느정도까지 남길까?를 결정하는 것

trace > debug > info > warn > error

❕ 로그를 남기는 것도 프로그램 성능에 어느정도 영향을 끼침

 

 

📌 Logger를 만들어보자 (by 로그 팩토리)

import org.slf4j.*;

public class OrderTester {

    private static final Logger logger = LoggerFactory.getLogger(OrderTester.class);
//  private final Logger logger = LoggerFactory.getLogger(this.getClass());
//  private static final Logger logger = LoggerFactory.getLogger("com.example.demo.OrderTester");
    ...
}

❕ 로거 구현체를 직접 import해서 쓰면 안됨

❕ OrderTester가 로거의 이름이 되고, 나중에 이 이름으로 로깅을 제어

 

 

📌 Logger를 써보자

logger.info("logger name ⇒ {}", logger.getName()); // logger name ⇒ com.example.demo.OrderTester

❕ 스프링 부트를 이용하면 SLF4J가 자동으로 설정됨

 

 

📌 로깅 설정을 해보자 (Logback 설정)

 : 보통 기본설정을 복사한 뒤 프로젝트에 맞게 수정

<!-- main.resources.logback.xml -->
<configuration>
  <!-- appender는 어디(지금은 Console)에 어떤 포맷으로 로그를 남길 수 있는지 설정 -->
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n</pattern>
    </encoder>
  </appender>
  
  <!-- logger는 기본적으로 root를 따름 -->
  <logger name="com.example.demo.OrderTester" level="warn" additivity="false">
    <!-- appender-ref를 추가하면 root와 중첩되어 로그가 2번 찍힘 (해결책: additivity를 false로 설정) -->
    <appender-ref ref="STDOUT" />
  </logger>

  <!-- root는 application class path 상에 있는 모든 로그에 적용 -->
  <root level="debug">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

 

✔️ pattern 태그 더 알아보기

 : 패턴을 작성할 때 공식 문서에서 Conversion Word(로깅 이벤트를 문자열로 변환) 참고

<configuration>
   <!-- property를 설정 -->
  <property name="CONSOLE_LOG_PATTERN" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n"/>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <!-- property를 가져와서 사용 -->
      <pattern>${CONSOLE_LOG_PATTERN}</pattern>
    </encoder>
  </appender>

  <root level="debug">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>
  • %d : 로깅 이벤트의 날짜 출력 (ex. %date{ISO8601})
  • %thread : 현재 Thread name
  • %-5level : 로그 레벨을 왼쪽 정렬(-), 최대 글자는 5
  • %logger{length} : 로그이름을 축약, length는 최대 자릿수
  • %msg : 로그 메시지
  • %n : 개행

 

📌 파일에 로그를 저장해보자 (feat. appender 태그 더 알아보기)

<configuration>
  <property name="LOG_PATTERN" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n"/>
  
  <!-- 타임스템프 설정 -->
  <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss" />
  
  <!-- FileAppender 사용 -->
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <!-- 로그 파일이 저장될 위치 + 재시작할때마다 파일을 새로 생성 -->
    <file>logs/kdt_${bySecond}.log</file>
    <!-- 프로그램을 재시작하면 다 지우고 다시 -->
    <append>false</append>
    <encoder>
      <pattern>${LOG_PATTERN}</pattern>
    </encoder>
  </appender>

  <root level="debug">
    <appender-ref ref="FILE" />
  </root>
</configuration>

 

<configuration>
  <property name="LOG_PATTERN" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n"/>
  
  <!-- RollingFileAppender 사용 -->
  <appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <!-- 로그 파일이 저장될 위치 -->
    <file>logs/access.log</file>
    <!-- 무슨 로그 파일을 어떻게 만들 것이냐를 설정 -->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingFilePolicy">
      <fileNamePattern>logs/access-d%{yyyy-MM-dd}.log</fileNamePattern>
    </rollingPolicy>
    <!-- 프로그램을 재시작하면 다 지우고 다시 -->
    <append>false</append>
    <encoder>
      <pattern>${LOG_PATTERN}</pattern>
    </encoder>
  </appender>

  <root level="debug">
    <appender-ref ref="ROLLING_FILE" />
  </root>
</configuration>

❕ 원래 RollingFileAppender를 사용하면 RollingPolicy와 TriggeringPolicy를 설정 해야 되는데 TimeBasedRollingFilePolic에는 이 2가지가 모두 정의되어 있음

<file>logs/access.log</file>을 넣어줌으로써 최신 파일은 access.log에서 접근 가능

 

 

✔️ logback 설정파일을 찾는 순서

logback-test.xml → logback.groovy → logback.xml → BasicConfiguration (기본 설정 전략)
  • logback 설정은 보통 resources 폴더 아래에 넣어줌
  • test폴더는 main폴더를 import할 수 있음으로 main > logback.xml과 test > logback-test.xml이 충돌날 수 있음, 이럴 때 logback-test.xml를 적용하기 위해서 logback-test.xml이 1순위로 찾아짐

 

📌 로그가 예쁘게 찍히게 해보자

<configuration>
  <!-- clr을 사용할 수 있게 설정 -->
  <conversionRule
    conversionWord="clr"
    converterClass="org.springframework.boot.logging.logback.ColorConverter"/>

  <!-- clr 적용 -->
  <property name="LOG_PATTERN" value="%clr(%d{HH:mm:ss.SSS}){red} [%thread] %-5level %logger{36} -%kvp- %msg%n">
  
  <appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>logs/access.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingFilePolicy">
      <fileNamePattern>logs/access-d%{yyyy-MM-dd}.log</fileNamePattern>
    </rollingPolicy>
    <append>false</append>
    <encoder>
      <pattern>${LOG_PATTERN}</pattern>
    </encoder>
  </appender>

  <root level="debug">
    <appender-ref ref="ROLLING_FILE" />
  </root>
</configuration>

❕ 컬러 변경이 되지 않는다면 해당 로그를 쓰는 클래스로 가서 AnsiOutput을 true로 변경

AnsiOutput.setEnabled(AnsiOutput.Enable.ALWAYS);

 

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함