๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ•Š๏ธ ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๋ฐ๋ธŒ์ฝ”์Šค

SpringBoot Part1-5

by hyeon-z 2023. 6. 26.

 

1. logging

 

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

 

์‹œ์Šคํ…œ์„ ์ž‘๋™ํ•  ๋•Œ ์‹œ์Šคํ…œ์˜ ์ž‘๋™ ์ƒํƒœ์˜ ๊ธฐ๋ก๊ณผ ๋ณด์กด, ์ด์šฉ์ž์˜ ์Šต์„ฑ ์กฐ์‚ฌ ๋ฐ ์‹œ์Šคํ…œ ๋™์ž‘์˜ ๋ถ„์„ ๋“ฑ์„ ํ•˜๊ธฐ ์œ„ํ•ด ์ž‘๋™ ์ค‘์˜ ๊ฐ์ข… ์ •๋ณด๋ฅผ ๊ธฐ๋กํ•ด ๋‘˜ ํ•„์š”๊ฐ€ ์žˆ๋‹ค. ์ด ๊ธฐ๋ก์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ๋กœ๊น…์ด๋ผ ํ•œ๋‹ค.

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

 

println()์œผ๋กœ ๋กœ๊น…์ด ๋ถˆ๊ฐ€๋Šฅํ•œ ์ด์œ 

 

์ƒํ™ฉ ๋ณ„๋กœ ๋กœ๊ทธ๋ฅผ ์กฐ์ •ํ•  ์ˆ˜ ์—†๊ณ  ๋ณ„๋„๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์–ด๋ ต๋‹ค.

๋Œ€๋Ÿ‰์˜ ๋กœ๊ทธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ, ํฐ ์„ฑ๋Šฅ ๋ฌธ์ œ๋ฅผ ์•ผ๊ธฐ์‹œํ‚จ๋‹ค. => ์˜ค๋ฒ„ํ—ค๋“œ ๋ฐœ์ƒ ๊ฐ€๋Šฅ์„ฑ ์กด์žฌ

์šด์˜ ์ƒํƒœ์—์„œ๋Š” ์ ˆ๋Œ€! ์“ฐ๋ฉด ์•ˆ๋œ๋‹ค.

 

Java Logging Framework

 

- java.util.logging (ํ‘œ์ค€ ๋กœ๊น… API)

- Apache Commons logging

- Log4J

- Logback

- SLF4J(Simple Logging Facade for Java)

 

SLF4J

 

Logging Framework๋“ค์„ ์ถ”์ƒํ™”ํ•ด ๋†“์€ ๊ฒƒ

Facade Pattern์„ ์ด์šฉํ•œ Logging Framework์ด๋‹ค.

 

๐Ÿ’ก Facade Pattern

ํ”„๋ž‘์Šค์–ด Façade์—์„œ ์œ ๋ž˜๋œ ๋‹จ์–ด๋กœ ๊ฑด๋ฌผ์˜ ์™ธ๊ด€์ด๋ผ๋Š” ๋œป์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.
๊ฑด๋ฌผ์˜ ์™ธ๋ฒฝ์—์„œ ๋ณด๋ฉด ์•ˆ์˜ ๊ตฌ์กฐ๋Š” ๋ณด์ด์ง€ ์•Š๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋งŽ์€ ์„œ๋ธŒ์‹œ์Šคํ…œ(๋‚ด๋ถ€ ๊ตฌ์กฐ)์„ ๊ฑฐ๋Œ€ํ•œ ํด๋ž˜์Šค(์™ธ๋ฒฝ)๋กœ ๋งŒ๋“ค์–ด ๊ฐ์‹ธ์„œ ํŽธ๋ฆฌํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

https://refactoring.guru/design-patterns/facade

 

SLF4J์˜ Binding ๋ชจ๋“ˆ

 

SLF4J๋Š” ๋ฐ”์ธ๋”ฉ ๋ชจ๋“ˆ์„ ํ†ตํ•ด์„œ ๋‹ค์–‘ํ•œ ๋กœ๊น… ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ง€์›ํ•œ๋‹ค.

๋ฐ”์ธ๋”ฉ ๋ชจ๋“ˆ์€ ๋กœ๊น… ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

 

=> ๋กœ๊น… ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์–ด๋–ค ๊ฒƒ์ด๋“  ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ๋กœ๊ทธ๋ฅผ ๋‚จ๊ธธ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด ์ค€๋‹ค.

 

Log Level

 

๋กœ๊ทธ ๋ฉ”์‹œ์ง€์˜ ์ค‘์š”๋„๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๊ธฐ์ค€

 

1. trace

๋งค์šฐ ์ƒ์„ธํ•œ ๋””๋ฒ„๊ทธ ์ •๋ณด 

๊ฐœ๋ฐœ ์ค‘์— ์ฃผ๋กœ ์‚ฌ์šฉ๋˜๋ฉฐ, ์‹œ์Šคํ…œ์˜ ๋™์ž‘์„ ์ถ”์ ํ•˜๊ณ  ๋ฌธ์ œ๋ฅผ ์ง„๋‹จํ•˜๊ธฐ ์œ„ํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

 

2. debug

๋””๋ฒ„๊ทธ ์ •๋ณด

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋‚ด๋ถ€ ์ƒํƒœ์™€ ์‹คํ–‰ ํ๋ฆ„์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๊ธฐ๋กํ•œ๋‹ค.

 

3. info

์ •๋ณด์„ฑ ๋ฉ”์‹œ์ง€ ์ œ๊ณต

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ฃผ์š” ์ด๋ฒคํŠธ ๋ฐ ์ƒํƒœ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๊ธฐ๋กํ•œ๋‹ค.

 

4. warn

๊ฒฝ๊ณ ์„ฑ ๋ฉ”์‹œ์ง€๋ฅผ ์ œ๊ณต

์ž ์žฌ์ ์ธ ๋ฌธ์ œ ์ƒํ™ฉ์„ ๋‚˜ํƒ€๋‚ด์ง€๋งŒ ์‹ฌ๊ฐํ•œ ์˜ค๋ฅ˜๋กœ ๊ฐ„์ฃผ๋˜์ง€๋Š” ์•Š๋Š” ์ƒํƒœ๋ฅผ ๊ธฐ๋กํ•œ๋‹ค.

์‹œ์Šคํ…œ์€ ๊ณ„์† ์ž‘๋™ํ•˜์ง€๋งŒ ์ฃผ์˜๊ฐ€ ํ•„์š”ํ•œ ์ƒํ™ฉ์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.

 

5. error

์˜ค๋ฅ˜ ์ƒํ™ฉ์„ ๋‚˜ํƒ€๋ƒ„

์‹œ์Šคํ…œ์˜ ๊ธฐ๋Šฅ์— ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Œ์„ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ํ•ด๋‹น ์˜ค๋ฅ˜์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๊ธฐ๋กํ•œ๋‹ค.

์‹œ์Šคํ…œ์ด ์˜ค์ž‘๋™ ์ƒํƒœ์— ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.

 

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

 

Logger

 

๋กœ๊น… ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ๊ฐ์ฒด ๋˜๋Š” ํด๋ž˜์Šค

 

import org.slf4j.Logger;

class OrderTest {
    private static final Logger logger = LoggerFactory.getLogger(OrderTester.class);    
}

๊ตฌํ˜„์ฒด ๋ง๊ณ  slf4j์—์„œ ์ œ๊ณตํ•˜๋Š” Logger๋ฅผ ์‚ฌ์šฉํ•ด๋ผ!

 

+)

logger.info("logger name => {} {}", logger.getName(), logger.getName());

์ž์œ ๋กญ๊ฒŒ placeholder๋ฅผ ์ด์šฉํ•ด์„œ log๋ฅผ ์ถœ๋ ฅํ•  ์ˆ˜ ์žˆ๋‹ค.


2. logback

 

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

 

1. logback-test.xml ํŒŒ์ผ์„ ๋จผ์ € ์ฐพ๋Š”๋‹ค

2. ์—†๋‹ค๋ฉด logback.groovy์„ ์ฐพ๋Š”๋‹ค.

3. ๊ทธ๋ž˜๋„ ์—†๋‹ค๋ฉด logback.xml์„ ์ฐพ๋Š”๋‹ค.

4. ๋ชจ๋‘ ์—†๋‹ค๋ฉด ๊ธฐ๋ณธ ์„ค์ • ์ „๋žต์„ ๋”ฐ๋ฅธ๋‹ค. => BasicConfiguration

 

logback.xml ํ˜•์‹

 

<configuration>
  <appender name = "STDOUT" class = "ch.qos.logback.core.ConsoleAppender">
  </appender>
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  <logger name="org.prgms.kdt.springorder" level="info"/>

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

 

- appender: ๋กœ๊ทธ ์ด๋ฒคํŠธ์˜ ์ถœ๋ ฅ ๋Œ€์ƒ์ธ Appender๋ฅผ ์ •์˜ํ•œ๋‹ค.

- encode: ๋กœ๊ทธ ๋ฉ”์‹œ์ง€์˜ ์ถœ๋ ฅ ํ˜•์‹์„ ์ง€์ •ํ•œ๋‹ค.

- logger: ํŠน์ • ๋กœ๊ฑฐ(logger)์˜ ๋กœ๊ทธ ๋ ˆ๋ฒจ์„ ์„ค์ •ํ•œ๋‹ค.

  => ํ•ด๋‹น ํŒจํ‚ค์ง€ ๋‚ด์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๋กœ๊ทธ ์ด๋ฒคํŠธ ์„ค์ •

- root: ์ตœ์ƒ์œ„(root) ๋กœ๊ฑฐ๋ฅผ ์„ค์ •ํ•œ๋‹ค.

 

+) appender-ref๋ฅผ ํ†ตํ•ด ํ•ด๋‹น Appender๋ฅผ ๋กœ๊ฑฐ์— ์—ฐ๊ฒฐํ•ด์•ผ๋งŒ ์ถœ๋ ฅ์ด ๋œ๋‹ค.

-> ์œ„์—์„œ ์ง€์ •ํ•œ appender name ์‚ฌ์šฉ

 

Appender ์ข…๋ฅ˜

 

- ConsoleAppender: ๋กœ๊ทธ๋ฅผ ์ฝ˜์†”์— ์ถœ๋ ฅ

- FileAppender: ๋กœ๊ทธ๋ฅผ ํŒŒ์ผ์— ์ถœ๋ ฅ

- RollingFileAppender๋กœ๊ทธ๋ฅผ ๋กค๋ง ํŒŒ์ผ ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅ, ์ผ์ • ํฌ๊ธฐ ๋˜๋Š” ์‹œ๊ฐ„ ๋‹จ์œ„๋กœ ํŒŒ์ผ์„ ๋ถ„ํ• ํ•˜์—ฌ ๋กœ๊ทธ๋ฅผ ๊ธฐ๋ก

 

PatternLayout

 

Logback์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋กœ๊ทธ ๋ฉ”์‹œ์ง€์˜ ์ถœ๋ ฅ ํ˜•์‹์„ ์ง€์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ํด๋ž˜์Šค

 

๋กœ๊ทธ ๋ฉ”์‹œ์ง€์˜ ๋‚ ์งœ, ์‹œ๊ฐ„, ๋กœ๊ทธ ๋ ˆ๋ฒจ, ๋กœ๊ฑฐ ์ด๋ฆ„ ๋“ฑ์„ ํฌํ•จํ•œ ์›ํ•˜๋Š” ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅํ•  ์ˆ˜ ์žˆ๋‹ค.
<encoder> ์š”์†Œ ๋‚ด์—์„œ ์‚ฌ์šฉ๋˜๋ฉฐ, <pattern> ์š”์†Œ๋ฅผ ํ†ตํ•ด ์ถœ๋ ฅ ํ˜•์‹์„ ์ •์˜ํ•œ๋‹ค. 

 

๐Ÿ’ก Conversion Word

Logback์˜ PatternLayout์—์„œ ์‚ฌ์šฉ๋˜๋Š” ํŠน์ˆ˜ํ•œ ๋ฌธ์ž์—ด

%d: ๋‚ ์งœ์™€ ์‹œ๊ฐ„์„ ์ถœ๋ ฅํ•œ๋‹ค. ๋‹ค์–‘ํ•œ ๋‚ ์งœ ๋ฐ ์‹œ๊ฐ„ ํ˜•์‹ ์ง€์ • ์˜ต์…˜์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
%t, %thread: ๋กœ๊ทธ๋ฅผ ์ƒ์„ฑํ•œ ์Šค๋ ˆ๋“œ์˜ ์ด๋ฆ„์„ ์ถœ๋ ฅํ•œ๋‹ค.
%logger{length}: ์ผ์ • ๊ธธ์ด ์ด์ƒ์˜ ๋กœ๊ฑฐ ์ด๋ฆ„์„ ์ž˜๋ผ๋‚ด์–ด length๋งŒํผ ์ถœ๋ ฅํ•œ๋‹ค.
%p, %level: ๋กœ๊ทธ ๋ ˆ๋ฒจ์„ ์ถœ๋ ฅํ•œ๋‹ค.
%c: ๋กœ๊ฑฐ์˜ ์ด๋ฆ„์„ ์ถœ๋ ฅํ•œ๋‹ค.
%m: ๋กœ๊ทธ ๋ฉ”์‹œ์ง€ ์ž์ฒด๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.
%n: ์ค„ ๋ฐ”๊ฟˆ ๋ฌธ์ž๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

์ž์„ธํ•œ ๊ฑด ์•„๋ž˜ ๋งํฌ ์ฐธ๊ณ 
https://logback.qos.ch/manual/layouts.html

 

ConversionRule

 

Logback์—์„œ ๋กœ๊ทธ ์ด๋ฒคํŠธ๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ •์˜ํ•˜๋Š” ๊ตฌ์„ฑ ์š”์†Œ

์ด๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž ์ •์˜ ํŒจํ„ด ๋ณ€ํ™˜์ž๋ฅผ ๋“ฑ๋กํ•˜๊ฑฐ๋‚˜ ๊ธฐ๋ณธ ๋ณ€ํ™˜์ž๋ฅผ ์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

<conversionRule conversionWord="๋ณ€ํ™˜์ž" converterClass="๋ณ€ํ™˜์ž ํด๋ž˜์Šค" />

conversionWord: ๋กœ๊ทธ ํŒจํ„ด์—์„œ ์‚ฌ์šฉํ•  ๋ณ€ํ™˜์ž๋ฅผ ์ •์˜ํ•œ๋‹ค. ์ด๋Š” % ๊ธฐํ˜ธ ๋’ค์— ์‚ฌ์šฉ๋˜๋Š” ๋ฌธ์ž๋กœ ํ‘œ์‹œ๋œ๋‹ค.

converterClass: ๋ณ€ํ™˜์ž์˜ ๊ตฌํ˜„ ํด๋ž˜์Šค๋ฅผ ์ง€์ •ํ•œ๋‹ค. ํ•ด๋‹น ํด๋ž˜์Šค๋Š” Logback์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋ณธ ๋ณ€ํ™˜์ž ์ค‘ ํ•˜๋‚˜์ผ ์ˆ˜๋„ ์žˆ๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ๊ตฌํ˜„ํ•œ ๋ณ€ํ™˜์ž์ผ ์ˆ˜๋„ ์žˆ๋‹ค.

 

 

์˜ˆ์‹œ

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

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

Logback์—์„œ ์ œ๊ณตํ•˜๋Š” ColorConverter๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋กœ๊ทธ ๋ฉ”์‹œ์ง€์— ์ƒ‰์ƒ์„ ์ ์šฉํ–ˆ๋‹ค.

%conversionWord() ํ˜•์‹์„ ํ†ตํ•ด ๋กœ๊ทธ ์ด๋ฒคํŠธ์˜ ์ถœ๋ ฅ ํŒจํ„ด์— ๋ณ€ํ™˜์ž๋ฅผ ์ ์šฉํ•˜๊ณ  ์žˆ๋‹ค.


3. SpringBoot

 

SpringBoot Application์˜ ์˜์กด์„ฑ

 

 

๐Ÿ‘† spring-boot-starter

Spring Boot ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ๋ณธ ์˜์กด์„ฑ์„ ์ œ๊ณตํ•œ๋‹ค.
Spring MVC, Spring Data JPA, Spring Security, Thymeleaf ๋“ฑ๊ณผ ๊ฐ™์€ ์ฃผ์š” ๊ธฐ์ˆ ๋“ค์˜ ์˜์กด์„ฑ์„ ์ž๋™์œผ๋กœ ์ถ”๊ฐ€ํ•ด ์ค€๋‹ค.
์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์— ํ•„์š”ํ•œ ๊ธฐ๋ณธ์ ์ธ ์„ค์ •๊ณผ ๋นˆ(Bean) ์„ค์ • ๋“ฑ์ด ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌ๋œ๋‹ค.

 

๐Ÿ‘† spring-boot-starter-test:

Spring Boot ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ์˜์กด์„ฑ์„ ์ œ๊ณตํ•œ๋‹ค.
JUnit, Mockito, AssertJ ๋“ฑ๊ณผ ๊ฐ™์€ ํ…Œ์ŠคํŠธ ๊ด€๋ จ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์˜ ์˜์กด์„ฑ์„ ์ž๋™์œผ๋กœ ์ถ”๊ฐ€ํ•ด ์ค€๋‹ค.
Spring Boot ํ…Œ์ŠคํŠธ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ, ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ, ์Šฌ๋ผ์ด์Šค ํ…Œ์ŠคํŠธ ๋“ฑ์„ ๊ฐ„ํŽธํ•˜๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
ํ…Œ์ŠคํŠธ ์‹คํ–‰ ํ™˜๊ฒฝ ์„ค์ •๊ณผ ํ…Œ์ŠคํŠธ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค ๋“ฑ์ด ํฌํ•จ๋˜์–ด ์žˆ๋‹ค.

 

 

 

Reference

๋„ค์ด๋ฒ„ ์ง€์‹๋ฐฑ๊ณผ - ๋กœ๊น…

 

'๐Ÿ•Š๏ธ ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๋ฐ๋ธŒ์ฝ”์Šค' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

SpringBoot Part2-2  (0) 2023.07.03
SpringBoot Part2-1  (0) 2023.06.27
SpringBoot Part1-4  (0) 2023.06.23
SpringBoot Part1-3  (0) 2023.06.22
SpringBoot Part1-2  (0) 2023.06.21

๋Œ“๊ธ€