๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Back-end ๋ฐ๋ธŒ์ฝ”์Šค/week 03 - 05 TIL (Spring)

[TIL] 221104 - SpringBoot Part1 : logging, SpringBoot

by young-ji 2022. 11. 6.

SpringBoot Part1 (5)

 

logging

๋กœ๊น…์ด๋ž€ ?

: ๋กœ๊ทธ ์‹œ์Šคํ…œ์˜ ์‚ฌ์šฉ์— ๊ด€๊ณ„๋œ ์ผ๋ จ์˜ ์‚ฌ๊ฑด์„ ์‹œ๊ฐ„์˜ ๊ฒฝ๊ณผ์— ๋”ฐ๋ผ ๊ธฐ๋กํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

 

Java Logging Framework

  • java.util.logging → ๊ธฐ๋Šฅ์ด ๋ถ€์กฑํ•ด์„œ ์ž˜ ์•ˆ์‚ฌ์šฉํ•œ๋‹ค.
  • Apache Commons logging
  • Log4J
  • Logback → ํ˜„์žฌ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋จ. Log4J ์„ฑ๋Šฅ ํ–ฅ์ƒ ๋ฒ„์ „. springboot๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•จ
  • SLF4J(Simple Logging Facade for Java)

! println์€ ๋‚ด๋ถ€์— synchronized๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. → ์šด์˜ํ• ๋•Œ ์“ฐ๋ฉด ์•ˆ๋œ๋‹ค.

 

 

SLF4J

Logging Framework๋“ค์„ ์ถ”์ƒํ™”ํ•ด ๋†“์€ ๊ฒƒ์ž…๋‹ˆ๋‹ค. Facade ํŒจํ„ด์„ ์ด์šฉํ•œ ํ”„๋ ˆ์ž„์›Œํฌ

Facade Patten : ๊ฑด๋ฌผ์˜ ์™ธ๋ฒฝ์ด๋ผ๋Š” ๋œป์œผ๋กœ, ๋งŽ์€ ์„œ๋ธŒ ์‹œ์Šคํ‹ˆ์„ ๋‚ด๋ถ€ ๊ตฌ์กฐ๋กœ ๋‘๊ณ  ๊ฑฐ๋Œ€ํ•œ ํด๋ž˜์Šค(์™ธ๋ฒฝ)๋ฅผ ๋งŒ๋“ค์–ด ๊ฐ์‹ธ์„œ ํŽธ๋ฆฌํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•ด ์ฃผ๋Š” ํŒจํ„ด

 

  • Binding ๋ชจ๋“ˆ ์ œ๊ณต

logging ํ”„๋กœ๊ทธ๋žจ์ด ๋ณ€๊ฒฝ๋ ๋•Œ ๋งˆ๋‹ค ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•  ํ•„์š” ์—†์ด binding๋งŒ ๋ณ€๊ฒฝํ•ด์ฃผ๋ฉด ๋‹ค์–‘ํ•œ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋™์ผํ•˜๊ธฐ ์ฒ˜๋ฆฌํ•ด์ค€๋‹ค. ๋กœ๊น… ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

 

 

Log Level

๋กœ๊ทธ๋ฅผ ์–ด๋Š ์ •๋„ ๊นŒ์ง€ ๋‚จ๊ธธ์ง€ ๊ธฐ์ค€์„ ์ •ํ•˜๊ธฐ

  1. trace
  2. debug
  3. info
  4. warm
  5. error

https://logback.qos.ch/manual/architecture.html

 

 

Logger

: logger๋“ค์€ ์ด๋ฆ„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ƒ์„ฑ๋œ๋‹ค.

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

public class OrderTester {

    // static์œผ๋กœ ์ƒ์„ฑํ•ด์•ผ ๋‹จ ํ•˜๋‚˜์˜ logger๋งŒ ๋งŒ๋“ค์–ด์ง€๊ฒŒ ํ•œ๋‹ค.
    // org.prgrms.kdt.OrderTester
    private static final Logger logger = LoggerFactory.getLogger(OrderTester.class); //๋ฉ”์†Œ๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ class ๋‹จ์œ„์—์„œ ์ƒ์„ฑ
    public static void main(String[] args) throws Exception{

        var applicationContext = new AnnotationConfigApplicationContext(AppConfiguration.class);        

        var orderProperties = applicationContext.getBean(OrderProperties.class);
        logger.info("logger name => {}",logger.getName());
        logger.info("version : {}",orderProperties.getVersion());
        logger.info("minimumOrderAmount : {}",orderProperties.getMinimumOrderAmount());
        logger.info("SupportVendors : {}",orderProperties.getSupportVendors());
        logger.info("Description : {}",orderProperties.getDescription());

        applicationContext.close(); // ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก๋œ ๋ชจ๋‘” Bean ์†Œ๋ฉธ
    }
}

 

Logback

logback ์„ค์ •ํ•˜๊ธฐ

lagback ์„ค์ • ํŒŒ์ผ ์ฐพ๋Š” ์ˆœ์„œ

https://logback.qos.ch/manual/configuration.html

  1. logback-test.xml ํŒŒ์ผ ์ฐพ๊ธฐ
  2. ์—†์œผ๋ฉด logback.groovy ์ฐพ๊ธฐ
  3. ๊ทธ๋ž˜๋„ ์—†์œผ๋ฉด logback.xml ์ฐพ๊ธฐ
  4. ๋ชจ๋‘ ์—†์œผ๋ฉด ๊ธฐ๋ณธ ์„ค์ • ์ „๋žต์„ ๋”ฐ๋ฅธ๋‹ค. BasicConfiguration

 

BasicConfiguration

<configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!-- encoders are assigned the type
             ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="debug"> <!--root๋Š” ๋ชจ๋“  ๋ ˆ๋ฒจ-->
        <appender-ref ref="STDOUT" />
    </root>
</configuration><configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!-- encoders are assigned the type
             ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="debug"> <!--root๋Š” ๋ชจ๋“  ๋ ˆ๋ฒจ-->
        <appender-ref ref="STDOUT" />
    </root>
</configuration>
  • logger : ํด๋” ๋‹จ์œ„๋กœ ๋ ˆ๋ฒจ ์ง€์ • ๊ฐ€๋Šฅ
  • patten : property ํƒœ๊ทธ๋กœ layout ์ง€์ •๊ฐ€๋Šฅ
    • %-5level : ๋ ˆ๋ฒจ 5์ž๋ฆฌ ์™ผ์ชฝ ์ •๋ ฌ ์ถœ๋ ฅ
    • %logger{36} : ๋กœ๊ฑฐ 36์ž
    • %n : ๊ฐœํ–‰
  • FileAppender
<configuration>

    <property name="LOG_PATTERN" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" />

    <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"></timestamp>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>
    </appender>

    <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>

    <logger name="org.prgrms.kdt" level="info">
        <appender-ref ref="FILE"/>
    </logger>
    <root level="warn"> <!--root๋Š” ๋ชจ๋“  ๋ ˆ๋ฒจ-->
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

 

  • RollingFileAppender

: ํŠธ๋ฆฌ๊ฑฐ์— ๋”ฐ๋ผ ํŒŒ์ผ ์ƒ์„ฑ

<configuration>

    <property name="LOG_PATTERN" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" />

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>
    </appender>

    <appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender" >
        <file>logs/access.log</file> <!-- access.log๊ฐ€ ๋งŒ๋“ค์–ด์ง€๊ณ  ๋‚ ์งœ๊ฐ€ ๋ณ€ํ•˜๋ฉด ํŒŒ์ผ๋ช…์ด access-%d{yyyy-MM-dd}.log๋กœ ๋ณ€๊ฒฝ๋˜๋Š” ํŒจํ„ด : ์ตœ์‹  ํŒŒ์ผ์€ ์–ธ์ œ๋‚˜ access.log&ndash;&gt;-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logs/access-%d{yyyy-MM-dd}.log</fileNamePattern>
        </rollingPolicy>
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>
    </appender>

    <logger name="org.prgrms.kdt" level="debug">
        <appender-ref ref="ROLLING_FILE"/>
    </logger>

    <root level="warn"> <!--root๋Š” ๋ชจ๋“  ๋ ˆ๋ฒจ-->
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

 

 

  • Conversion

: ์ƒ‰์ƒ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ

: file์€ ์ƒ‰์ƒ์ด ๊ธฐ๋ก๋˜์„œ ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์ง€๋‹ˆ property๋กœ ํŒจํ„ด์„ ๋‚˜๋ˆ  ์ ์šฉํ•ด์ค€๋‹ค.

: ์ ์šฉ์ด ์ž˜ ๋˜์ง€์•Š์œผ๋ฉด main ๋ฉ”์†Œ๋“œ์—

AnsiOutput.setEnabled(AnsiOutput.Enabled.ALWAYS);  ์ถ”๊ฐ€

<configuration>

    <conversionRule conversionWord="clr"
                    converterClass="org.springframework.boot.logging.logback.ColorConverter"/>

    <property name="CONSOLE_LOG_PATTERN" value="%clr(%d{HH:mm:ss.SSS}){yellow} [%thread] %clr(%-5level) %logger{36} - %msg%n" />
    <property name="FILE_LOG_PATTERN" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" />

    <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"></timestamp>
    
		<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
        </encoder>
    </appender>

    <appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender" >
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logs/access-%d{yyyy-MM-dd}.log</fileNamePattern>
        </rollingPolicy>
        <encoder>
            <pattern>${FILE_LOG_PATTERN}</pattern>
        </encoder>
    </appender>

    <logger name="org.prgrms.kdt" level="debug">
        <appender-ref ref="ROLLING_FILE"/>
    </logger>

    <root level="warn"> <!--root๋Š” ๋ชจ๋“  ๋ ˆ๋ฒจ-->
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

์ถœ๋ ฅ

 


SpringBoot ์‹œ์ž‘ํ•˜๊ธฐ

(๋“œ๋””์–ด)

@SpringBootApplication

: ์ตœ์ƒ์˜ Configuration์„ ํฌํ•จํ•œ๋‹ค. ๋‹จ ํ•˜๋‚˜์˜ class ๋งŒ ํ—ˆ์šฉํ•œ๋‹ค.

: ComponentScan

: EnableAutoConfiguation

: ๊ธฐ๋ณธ์ ์œผ๋กœ resources ํด๋”์— application.properties/ application.YAML ํŒŒ์ผ์„ ์ฝ๋Š”๋‹ค. (PropertySource ์„ค์ •์ด ํ•„์š”์—†์Œ)

 

⇒ CoC ํŒจ๋Ÿฌ๋‹ค์ž„

https://medium.com/@dlaudtjr07/convention-over-configuration-๋ž€-694345d2447f

 

 

SpringBoot Banner

https://patorjk.com/software/taag/#p=display&f=Graffiti&t=Type Something

resources > banner.txt ํŒŒ์ผ์— ์ถ”๊ฐ€

 

 

Logging

logback ํŒŒ์ผ์ด ์—†์–ด๋„ yaml์—์„œ ํŽธํ•˜๊ฒŒ logging level์„ ์ •ํ• ์ˆ˜์žˆ๋‹ค.

logging:
  level:
    root: warn

kdt:
  version: "v1.0"
  minimum-order-amount: 1
  support-vendors:
    - a
    - b
    - c
    - d
  description: |
    line 1 hello world
    line 2 xxx
    line 3

logback.xml์„ ์‚ฌ์šฉํ•˜๋•Œ๋„ springboot์˜ ๊ธฐ๋Šฅ์„ ์ƒ์† ๋ฐ›์„ ์“ธ์ˆ˜์žˆ๋‹ค. <include resuorce>

 

 

์™ธ๋ถ€์—์„œ ์„ค์ • ๊ฐ€์ ธ์˜ค๊ธฐ

https://www.latera.kr/reference/java/2019-09-29-spring-boot-config-externalize/

  1. ํ™ˆ ๋””๋ ‰ํ„ฐ๋ฆฌ(๊ฐœ๋ฐœ ๋„๊ตฌ๊ฐ€ ํ™œ์„ฑํ™”๋œ ๊ฒฝ์šฐ ~/.spring-boot-devtools.properties )์˜ ๊ฐœ๋ฐœ ๋„๊ตฌ ์ „์—ญ ์„ค์ • ํ”„๋กœํผํ‹ฐ
  2. ํ…Œ์ŠคํŠธ์˜ @TestPropertySource ์–ด๋…ธํ…Œ์ด์…˜.
  3. ํ…Œ์ŠคํŠธ์˜ properties ์• ํŠธ๋ฆฌ๋ทฐํŠธ. @SpringBootTest ์™€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํŠน์ • ๋ถ€๋ถ„์„ ํ…Œ ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•œ ํ…Œ์ŠคํŠธ ์–ด๋…ธํ…Œ์ด์…˜์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ.
  4. ์ปค๋งจ๋“œ ๋ผ์ธ ์ธ์ž.
  5. SPRING_APPLICATION_JSON ์˜ ํ”„๋กœํผํ‹ฐ(ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋‚˜ ์‹œ์Šคํ…œ ํ”„๋กœํผํ‹ฐ์— ์‚ฝ์ž…๋œ ์ธ๋ผ์ธ JSON).
  6. ServletConfig ์ดˆ๊ธฐ ํŒŒ๋ผ๋ฏธํ„ฐ.
  7. ServletContext ์ดˆ๊ธฐ ํŒŒ๋ผ๋ฏธํ„ฐ.
  8. java:comp/env ์˜ JNDI ์• ํŠธ๋ฆฌ๋ทฐํŠธ.
  9. Java ์‹œ์Šคํ…œ ํ”„๋กœํผํ‹ฐ( System.getProperties() ).
  10. OS ํ™˜๊ฒฝ ๋ณ€์ˆ˜
  11. random.* ์— ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฐ€์ง„ RandomValuePropertySource .
  12. ํŒจํ‚ค์ง€๋œ jar ์™ธ๋ถ€์˜ ํ”„๋กœํŒŒ์ผ ์ง€์ • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋กœํผํ‹ฐ( application- {profile}.properties ์™€ YAML ํ˜•์‹).
  13. ํŒจํ‚ค์ง€๋œ jar ๋‚ด๋ถ€์˜ ํ”„๋กœํŒŒ์ผ ์ง€์ • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋กœํผํ‹ฐ( application- {profile}.properties ์™€ YAML ํ˜•์‹).
  14. ํŒจํ‚ค์ง€๋œ jar ์™ธ๋ถ€์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋กœํผํ‹ฐ( application-{profile}.properties ์™€ YAML ํ˜•์‹).
  15. ํŒจํ‚ค์ง€๋œ jar ๋‚ด๋ถ€์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋กœํผํ‹ฐ( application-{profile}.properties ์™€ YAML ํ˜•์‹).
  16. @Configuration ํด๋ž˜์Šค์˜ @PropertySource ์–ด๋…ธํ…Œ์ด์…˜
  17. ( SpringApplication.setDefaultProperties ์— ์˜ํ•ด ๋ช…์‹œ๋œ) ๊ธฐ๋ณธ ํ”„๋กœํผํ‹ฐ

 

 

์‹คํ–‰ ๊ฐ€๋Šฅํ•œ jarํŒŒ์ผ ์ƒ์„ฑํ•˜๊ธฐ

pom.xml → plugins์„ ์ด์šฉํ•ด์„œ jar๋ฅผ ๋งŒ๋“ ๋‹ค.

mvn clean package spring-boot:repackage   -> jar package๋งŒ๋“ค๊ธฐ

ll taget   -> ๋งŒ๋“ค์–ด์ง„ ํŒŒ์ผ ํ™•์ธ

java -jar target.kdt-0.0.1-SNAPSHOT.jar   -> jar ์‹คํ–‰(๊ตฌ๋™)

 

 

  • intelliJ์—์„œ SpringBootApplication์‹คํ–‰์‹œ ํŽธ๋ฆฌํ•˜๊ฒŒ SpringBoot ์„ค์ •์ด ๊ฐ€๋Šฅํ•˜๋‹ค.profiles ์„ค์ • ๊ฐ€๋Šฅ

 

 


 

Daily Mission

  • ๋กœ๊ทธ๋ฐฑ ์„ค์ •์„ ํ•ด์„œ ์—๋Ÿฌ๋Š” ํŒŒ์ผ๋กœ ๊ธฐ๋ก๋˜์–ด์•ผํ•œ๋‹ค.
  • springBoot ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ๋ณ€์…ฉํ•œ๋‹ค.
  • ์‹คํ–‰๊ฐ€๋Šฅํ•œ jar ํŒŒ์ผ์„ ์ƒ์„ฑํ•œ๋‹ค.

 

 

์ถœ์ฒ˜ - ํ•ด๋ฆฌ : SpringBoot Part1

 

๋Œ“๊ธ€