๐Ÿ’ป Back-End

[Spring Batch] Logback ์„ค์ •ํ•˜๊ธฐ

์˜ฌใ„น1๋ธŒ 2019. 11. 14. 16:19
๋ฐ˜์‘ํ˜•

ํ˜„์žฌ Spring Batch๋ฅผ ํ†ตํ•œ ๊ฐ„๋‹จํ•œ ๋ฐฐ์น˜ ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“ค๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

API๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ DB์— ์—…๋ฐ์ดํŠธ๋ฅผ ํ•˜๋Š” ์ž‘์—…์„ ์ง„ํ–‰ํ•˜๋Š”๋ฐ, ํ˜„์žฌ ํ…Œ์ŠคํŠธ ๊ธฐ๊ฐ„์ด๋ผ ํ•ด๋‹น ํ”„๋กœ๊ทธ๋žจ์ด ์ž˜ ๋™์ž‘ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ํ™•์ธ์ด ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ ํšŒ์‚ฌ์—์„œ ์‚ฌ์šฉํ•˜๋Š” slf4j๋ฅผ ์‚ฌ์šฉํ• ๊นŒ ๊ณ ๋ฏผํ•˜์˜€์ง€๋งŒ, ์ €๋งŒ์˜ ์‚ฌ์ด๋“œ ํ”„๋กœ์ ํŠธ๊ธฐ๋„ ํ•˜๊ณ , logback์— ๋Œ€ํ•œ ์„ฑ๋Šฅ์ด slf4j๋ณด๋‹ค ์•ž์„œ๋‹ค๋Š” ๊ธ€์„ ๋ณด์•˜์Šต๋‹ˆ๋‹ค. ๊ณต๋ถ€ํ•  ๊ฒธ logback๋ฅผ ์ด์šฉํ•˜์—ฌ ๋กœ๊ทธ๋ฅผ ์Œ“๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ Spring Boot์—์„œ Logback์„ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•, ์‹ค์ œ๋กœ ์ ์šฉํ•˜๋ฉด์„œ ๋ฐœ์ƒํ•˜์˜€๋˜ ์ด์Šˆ์— ๋Œ€ํ•ด ๊ฐ„๋žตํ•˜๊ฒŒ ์„œ์ˆ ํ•˜๋ ค ํ•ฉ๋‹ˆ๋‹ค.
์ •์ •์ด ํ•„์š”ํ•œ ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ๋Š” ์•„๋‚Œ ์—†๋Š” ๋Œ“๊ธ€ ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค.
(Spring Boot์— ๋Œ€ํ•œ ํฌ์ŠคํŒ…์€.. ์–ธ์  ๊ฐ€..)

์‚ฌ์šฉํ•˜๋Š” ๊ธฐ์ˆ  ๋ฒ„์ „

  • Spring Batch 4.2 (Spring Boot 2.2)
  • Logback 1.2.3

1. Logback ์„ค์ •ํ•˜๊ธฐ

(์ œ๊ฐ€ ์•Œ๊ธฐ๋กœ๋Š”) spring-boot-starter-batch์˜ ์˜์กด์„ฑ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

spring-boot-starter
ใ„ด spring-boot-starter-batch

spring-boot-starter๋‚ด์—๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋กœ๊ทธ ์‹œ์Šคํ…œ(logback, slf4j ๋“ฑ)์„ ์ œ๊ณตํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
(๊ทธ๋ž˜์„œ ํ˜„์žฌ ํ•„์ž์˜ ํ”„๋กœ์ ํŠธ์—๋Š” logback-core-1.2.3.jar, logback-classic-1.2.3.jar๊ฐ€ depend๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.)

๋งŒ์•ฝ logback์˜ ๋‹ค๋ฅธ ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜๋ ค๊ฑฐ๋‚˜, ํ˜น์€ spring-boot-starter-batch ๋‚ด์— ํฌํ•จ์ด ๋˜์–ด์žˆ์ง€ ์•Š๋‹ค๋ฉด,
pom.xml์— ๋‹ค์Œ dependency๋ฅผ ์ ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
(๋ฌผ๋ก  <repository />๋กœ ์„ค์ •ํ•ด๋‘” ๋ ˆํŒŒ์ง€ํ† ๋ฆฌ ์ฃผ์†Œ ๋‚ด์— logback์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.)

...(์ค‘๋žต)
<dependencies>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
    </dependency>
</dependencies>
...(ํ›„๋žต)

2. logback-spring.xml ์ƒ์„ฑํ•˜๊ธฐ

logback๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š”, ๊ทธ์— ํ•ด๋‹นํ•˜๋Š” ์„ค์ •ํŒŒ์ผ์„ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
${ํ”„๋กœ์ ํŠธ๊ฒฝ๋กœ}/src/main/resources ๊ฒฝ๋กœ์— logback-spring.xml ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด์ฃผ๋ฉด, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๊ตฌ๋™ ๋  ๋•Œ logback์—์„œ ํ•ด๋‹น ํŒŒ์ผ์„ ์ฝ์–ด์˜ต๋‹ˆ๋‹ค.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <!-- ๋กœ๊ทธ๊ฐ€ ์ €์žฅ๋  ๊ฒฝ๋กœ -->
  <property name="LOG_PATH" value="/log" />

  <!-- ํŒŒ์ผ๋กœ ๋กœ๊ทธ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ -->
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>log/ldata.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <fileNamePattern>log/ldata.%d{yyyy-MM-dd}.log</fileNamePattern>
      <maxHistory>30</maxHistory>
    </rollingPolicy>
    <encoder>
      <pattern>%date %level [%thread] %msg%n</pattern>
    </encoder>
  </appender>

  <!-- ์ฝ˜์†”์—์„œ ๋กœ๊ทธ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ -->
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
     <!--  <pattern>%msg%n</pattern> -->
      <pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
    </encoder>
  </appender>

  <!-- ํ”„๋กœ๊ทธ๋žจ์—์„œ ์ ์šฉ๋  ๋กœ๊ทธ ๋ ˆ๋ฒจ -->
  <root level="INFO">
    <appender-ref ref="FILE" />
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

<configuration/>, <appender/>์— ๊ด€๋ จ๋œ ์„ค๋ช…์€ ๊ณต์‹ ํ™ˆํŽ˜์ด์ง€์— ์ž˜ ๋‚˜์™€์žˆ๋‹ต๋‹ˆ๋‹ค. (์˜์–ด๋ผ์„œ ๋ฌธ์ œ..)
์œ„์— ์ž‘์„ฑ๋œ logback-spring.xml์— ๋Œ€ํ•œ ํ•ด์„์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. ํŒŒ์ผ๋กœ ๋กœ๊ทธ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ
    • file์˜ ์ด๋ฆ„์€ ldata.log๋กœ ์ž‘์„ฑํ•œ๋‹ค.
    • ์˜ค๋Š˜ ์ดํ›„, ํ•˜๋ฃจ๊ฐ€ ์ง€๋‚˜๊ฐˆ ๋•Œ๋งˆ๋‹ค ์ด๋ฆ„์„ ๋‹ค๋ฅด๊ฒŒ ์ž‘์„ฑํ•œ๋‹ค.
      • ํŒŒ์ผ๋ช…์˜ ํŒจํ„ด์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ง€์ •ํ•œ๋‹ค : ldata.2019-11-15.log
      • ์ด ํŒŒ์ผ๋“ค์€ ์ตœ๋Œ€ 30์ผ๊นŒ์ง€๋งŒ ๋ณด์œ ํ•˜๋ฉฐ, ์ดํ›„ ์ž๋™์œผ๋กœ ์‚ญ์ œํ•œ๋‹ค.
    • file ๋‚ด์— ์ ํ˜€์งˆ ๋กœ๊ทธ๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•œ๋‹ค : 2019-11-14 [INFO] step : [updateStep] executed in 529ms
  2. ์ฝ˜์†”์—์„œ ๋กœ๊ทธ๋ฅผ ๋ณด์—ฌ์ค„ ๋•Œ
    • console ๋‚ด์—์„œ ๋ณด์—ฌ์ค„ ๋กœ๊ทธ๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•œ๋‹ค : 2019-11-14 [INFO] [main] o.s.b.c.l.s.JobLauncher [JobLauncher.java:149] Job: [SimpleJob: [name=updateJob]] status: [COMPLETED] in 698ms
  3. ํ˜„์žฌ ์ด ํ”„๋กœ์ ํŠธ์˜ ๋กœ๊ทธ ๋ ˆ๋ฒจ์€ INFO

3. logback ์‚ฌ์šฉํ•˜๊ธฐ

์ด์ œ logback์— ๋Œ€ํ•œ ์„ค์ •๊นŒ์ง€ ๋งˆ์ณค๋‹ค๋ฉด, ์‹ค์ œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋‹จ๊ณ„์—์„œ ๋กœ๊ทธ๋ฅผ ์ฐธ์กฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
(ํ•ด๋‹น ๋ถ€๋ถ„์— ๋Œ€ํ•œ ์„ค๋ช…์ด ํ‹€๋ฆด ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์ด ๊ธ€์„ ํ™•์ธํ•˜์‹œ๋Š” ๋ถ„์ด์‹œ๋ผ๋ฉด ์•„๋‚Œ ์—†๋Š” ํ”ผ๋“œ๋ฐฑ์„ ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค...)

์‹ค์ œ๋กœ ์ž‘์„ฑํ•˜๊ณ  ์žˆ๋Š” Application๋‹จ์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@EnableBatchProcessing
@SpringBootApplication
public class Application {
    private static final Logger logger = LoggerFactory.getLogger(Application.class);
    public static void main (String[] args) {
        logger.info("INFO...");
        logger.error("ERROR...");
    }
}

์œ„ ์ฝ”๋“œ์— ๋Œ€ํ•œ ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ„๋žตํ•˜๊ฒŒ ์ ์ž๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

2019-11-15 [INFO] INFO...
2019-11-15 [ERROR] ERROR...

4. ์ด์Šˆ..๋ผ๊ธฐ ๋ณด๋‹ค๋Š” ๋ฐœ์ƒํ–ˆ๋˜ ๋ฌธ์ œ์ 

1.XML์„ ์ž‘์„ฑํ–ˆ๋”๋‹ˆ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ตฌ๋™์‹œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•จ

 1.1 ๋‚ด๊ฐ€ ์ž‘์„ฑํ–ˆ๋˜ ์ฝ”๋“œ

    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>ldata.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <!-- daily rollover -->
      <fileNamePattern>ldata-%d{yyyy-MM-dd}.log</fileNamePattern>
      <!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
      <maxFileSize>100MB</maxFileSize> 
      <!-- keep 30 days' worth of history capped at 3GB total size -->
      <maxHistory>30</maxHistory>
      <totalSizeCap>2GB</totalSizeCap>
    </rollingPolicy>
    <encoder>
      <pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
    </encoder>
  </appender>

 1.2 ๋‚˜ํƒ€๋‚ฌ๋˜ ์˜ค๋ฅ˜

    2019-11-14 16:12:45,568 ERROR [main] o.s.b.SpringApplication [SpringApplication.java:826] Application run failed
java.lang.IllegalStateException: Logback configuration error detected: 
ERROR in ch.qos.logback.core.joran.spi.Interpreter@11:20 - no applicable action for [maxFileSize], current ElementPath  is [[configuration][appender][rollingPolicy][maxFileSize]]
    at org.springframework.boot.logging.logback.LogbackLoggingSystem.loadConfiguration(LogbackLoggingSystem.java:169)
    at org.springframework.boot.logging.AbstractLoggingSystem.initializeWithConventions(AbstractLoggingSystem.java:80)
    at org.springframework.boot.logging.AbstractLoggingSystem.initialize(AbstractLoggingSystem.java:60)
    at org.springframework.boot.logging.logback.LogbackLoggingSystem.initialize(LogbackLoggingSystem.java:118)
    at org.springframework.boot.context.logging.LoggingApplicationListener.initializeSystem(LoggingApplicationListener.java:312)
    at org.springframework.boot.context.logging.LoggingApplicationListener.initialize(LoggingApplicationListener.java:287)
    at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEnvironmentPreparedEvent(LoggingApplicationListener.java:245)
    at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:222)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127)
    at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:76)
    at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:53)
    at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:345)

- no applicable action for [maxFileSize] ๊ฐ€ ํ•ต์‹ฌ ๋ฌธ๊ตฌ

1.3 ์˜ค๋ฅ˜์˜ ์›์ธ ๋ฐ ํ•ด๊ฒฐ๋ฐฉ์•ˆ
- ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ๋ณด๋ฉฐ ์˜ˆ์ œ๋ฅผ ๋ถ™์ด๋Š” ๊ณผ์ •์—์„œ, `TimeBasedRollingPolicy` ํด๋ž˜์Šค๊ฐ€ ํ‹€๋ฆฐ ๊ฒƒ์„ ํ™•์ธํ•˜๊ฒŒ ๋จ. (^^)
- ํ˜„์žฌ rollingPolicy์˜ class๋Š” `TimeBasedRollingPolicy`์ด๋‚˜ ๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ์†์„ฑ๋“ค(`maxFileSize`, `totalSizeCap`)`์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด class๋ฅผ `SizeAndTimeBasedRollingPolicy`๋กœ ์ง€์ •ํ•ด์ฃผ์–ด์•ผ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค!

- ๊ทธ๋Ÿฌ๋ฏ€๋กœ ์ €์™€ ๋น„์Šทํ•œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์˜€๋‹ค๋ฉด
    1. XML์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘์„ฑํ•˜์˜€๋Š”์ง€ (์—ด์–ด๋†“๊ณ  ๋‹ซ์€ ํƒœ๊ทธ๋Š” ์—†๋Š”์ง€, / ๊ฐ€ ๋น ์กŒ๋‹ค๋˜์ง€ ๋“ฑ๋“ฑ..)
    2. ๊ฐ Class์— ํ•ด๋‹นํ•˜๋Š” ์†์„ฑ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘์„ฑํ•˜์˜€๋Š”์ง€
  ๊ผญ ํ™•์ธ์„ ํ•ด์ฃผ์„ธ์š”.

๋ฐ˜์‘ํ˜•

'๐Ÿ’ป Back-End' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

DuckDuckGoSearchAPIWrapper.run HTTPError  (0) 2025.01.26
[Excel] Spring์—์„œ ์—‘์…€์„ ์ถœ๋ ฅํ•˜๋Š” ๋ฐฉ๋ฒ•  (0) 2020.11.24
Telegram Bot API  (0) 2019.10.01
[JEUS] Session Timeout ์„ค์ •  (1) 2019.02.13
[Web] #Servlet #GET #POST  (0) 2018.07.24