๐ŸŒฟ Spring Boot Logging: Logback ์„ค์ • ์ตœ์ ํ™” ๋Œ€์ž‘์ „! ๐Ÿš€

์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐ŸŒฟ Spring Boot Logging: Logback ์„ค์ • ์ตœ์ ํ™” ๋Œ€์ž‘์ „! ๐Ÿš€

 

 

์•ˆ๋…•ํ•˜์„ธ์š”, ๊ฐœ๋ฐœ์ž ์—ฌ๋Ÿฌ๋ถ„! ์˜ค๋Š˜์€ Spring Boot์˜ ๋กœ๊น… ์‹œ์Šคํ…œ, ํŠนํžˆ Logback ์„ค์ •์„ ์ตœ์ ํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๊นŠ์ด ์žˆ๊ฒŒ ํŒŒํ—ค์ณ๋ณผ ๊ฑฐ์˜ˆ์š”. ๋กœ๊น…์ด ๋ญ ๋ณ„๊ฑฐ๋ƒ๊ณ ์š”? ใ…‹ใ…‹ใ…‹ ์–ด๋ฆผ๋„ ์—†์ฃ ! ๋กœ๊น…์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ˆˆ๊ณผ ๊ท€๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ œ๋Œ€๋กœ ์„ค์ •ํ•˜๋ฉด ๊ฐœ๋ฐœ ์ƒ์‚ฐ์„ฑ๊ณผ ์šด์˜ ํšจ์œจ์„ฑ์ด ์‘ฅ์‘ฅ ์˜ฌ๋ผ๊ฐ„๋‹ค๊ณ ์š”! ๐Ÿ˜Ž

์ž, ์ด์ œ๋ถ€ํ„ฐ Spring Boot์™€ Logback์˜ ์„ธ๊ณ„๋กœ ๋น ์ ธ๋ณผ๊นŒ์š”? ์ค€๋น„๋˜์…จ๋‚˜์š”? ๊ทธ๋Ÿผ ๊ณ ๊ณ ์”ฝ~! ๐Ÿƒโ€โ™‚๏ธ๐Ÿ’จ

๐ŸŒŠ Spring Boot์™€ Logback์˜ ๋งŒ๋‚จ: ๋กœ๊น…์˜ ์ƒˆ๋กœ์šด ์ง€ํ‰

Spring Boot๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ Logback์„ ๋กœ๊น… ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ์‚ฌ์šฉํ•ด์š”. ์™œ ํ•˜ํ•„ Logback์ผ๊นŒ์š”? ๊ทธ๊ฑด ๋ฐ”๋กœ Logback์ด ์„ฑ๋Šฅ๊ณผ ์œ ์—ฐ์„ฑ ๋ฉด์—์„œ ๋‹ค๋ฅธ ๋กœ๊น… ํ”„๋ ˆ์ž„์›Œํฌ๋“ค์„ ์••๋„ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด์—์š”! ๐Ÿ‘‘

Logback์€ Log4j์˜ ํ›„์†์ž‘์œผ๋กœ, ๋” ๋น ๋ฅด๊ณ  ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์ ์ด๋ฉฐ, ์ž๋™ ๋ฆฌ๋กœ๋“œ ๊ฐ™์€ ์ฟจํ•œ ๊ธฐ๋Šฅ๋“ค์„ ์ œ๊ณตํ•ด์š”. Spring Boot์™€ ํ•จ๊ป˜๋ผ๋ฉด ๊ฑฐ์˜ ์™„๋ฒฝํ•œ ์กฐํ•ฉ์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์ฃ ! ๐Ÿ˜

๐Ÿ” Logback์˜ ์ฃผ์š” ํŠน์ง•:

  • ๋น ๋ฅธ ์‹คํ–‰ ์†๋„์™€ ๋‚ฎ์€ ๋ฉ”๋ชจ๋ฆฌ ์ ์œ ์œจ
  • XML, Groovy ๊ธฐ๋ฐ˜์˜ ์„ค์ • ๊ฐ€๋Šฅ
  • ๋กœ๊ทธ ํŒŒ์ผ ์ž๋™ ์••์ถ• ๋ฐ ๋กค์˜ค๋ฒ„
  • ์กฐ๊ฑด๋ถ€ ์ฒ˜๋ฆฌ๋ฅผ ํ†ตํ•œ ์œ ์—ฐํ•œ ์„ค์ •
  • ํ•„ํ„ฐ๋ฅผ ์ด์šฉํ•œ ์„ธ๋ฐ€ํ•œ ๋กœ๊ทธ ์ œ์–ด

์ด๋Ÿฐ ํŠน์ง•๋“ค ๋•๋ถ„์— Logback์€ ๋Œ€๊ทœ๋ชจ ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๋ถ€ํ„ฐ ์†Œ๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ๊นŒ์ง€ ๋‘๋ฃจ๋‘๋ฃจ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์–ด์š”. ์‹ฌ์ง€์–ด ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ์žฌ๋Šฅ ๊ณต์œ  ํ”Œ๋žซํผ์—์„œ๋„ Logback์„ ํ™œ์šฉํ•ด ์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ๋ง๊ณผ ๋””๋ฒ„๊น…์„ ํšจ์œจ์ ์œผ๋กœ ํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ํ•ด์š”! ๐Ÿ‘

์ž, ์ด์ œ Logback์ด ์–ผ๋งˆ๋‚˜ ๋Œ€๋‹จํ•œ์ง€ ์•Œ๊ฒ ์ฃ ? ๊ทธ๋Ÿผ ์ด์ œ๋ถ€ํ„ฐ ๋ณธ๊ฒฉ์ ์œผ๋กœ Logback ์„ค์ •์„ ์ตœ์ ํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ๊ฒŒ์š”. ์ค€๋น„๋˜์…จ๋‚˜์š”? Let's dive in! ๐ŸŠโ€โ™‚๏ธ

๐Ÿ›  Logback ์„ค์ •์˜ ๊ธฐ๋ณธ: logback-spring.xml

Logback ์„ค์ •์˜ ํ•ต์‹ฌ์€ ๋ฐ”๋กœ logback-spring.xml ํŒŒ์ผ์ด์—์š”. ์ด ํŒŒ์ผ๋งŒ ์ œ๋Œ€๋กœ ์ž‘์„ฑํ•˜๋ฉด ์—ฌ๋Ÿฌ๋ถ„์˜ ๋กœ๊น… ์‹œ์Šคํ…œ์€ ๊ทธ์•ผ๋ง๋กœ ๋‚ ๊ฐœ๋ฅผ ๋‹จ ๋“ฏ์ด ๋‚ ์•„์˜ค๋ฅผ ๊ฑฐ์˜ˆ์š”! โœˆ๏ธ

๋จผ์ €, ๊ธฐ๋ณธ์ ์ธ logback-spring.xml ํŒŒ์ผ์˜ ๊ตฌ์กฐ๋ฅผ ์‚ดํŽด๋ณผ๊นŒ์š”?

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="CONSOLE" />
    </root>
</configuration>

์ด๊ฒŒ ๋ฐ”๋กœ ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ Logback ์„ค์ •์ด์—์š”. ํ•˜๋‚˜์”ฉ ๋œฏ์–ด๋ณผ๊นŒ์š”? ๐Ÿ”

  • <configuration>: Logback ์„ค์ •์˜ ๋ฃจํŠธ ์—˜๋ฆฌ๋จผํŠธ์˜ˆ์š”.
  • <appender>: ๋กœ๊ทธ ๋ฉ”์‹œ์ง€๋ฅผ ์–ด๋””์— ์ถœ๋ ฅํ• ์ง€ ์ •์˜ํ•ด์š”. ์—ฌ๊ธฐ์„œ๋Š” ์ฝ˜์†”์— ์ถœ๋ ฅํ•˜๋„๋ก ์„ค์ •ํ–ˆ์–ด์š”.
  • <encoder>: ๋กœ๊ทธ ๋ฉ”์‹œ์ง€์˜ ํ˜•์‹์„ ์ •์˜ํ•ด์š”.
  • <pattern>: ์‹ค์ œ ๋กœ๊ทธ ๋ฉ”์‹œ์ง€์˜ ํŒจํ„ด์„ ์ •์˜ํ•ด์š”. ์‹œ๊ฐ„, ์Šค๋ ˆ๋“œ, ๋กœ๊ทธ ๋ ˆ๋ฒจ, ๋กœ๊ฑฐ ์ด๋ฆ„, ๋ฉ”์‹œ์ง€ ์ˆœ์„œ๋กœ ์ถœ๋ ฅ๋˜๋„๋ก ํ–ˆ์–ด์š”.
  • <root>: ๋ฃจํŠธ ๋กœ๊ฑฐ์˜ ์„ค์ •์ด์—์š”. ๋ชจ๋“  ๋กœ๊ฑฐ์˜ ๋ถ€๋ชจ๊ฐ€ ๋˜๋Š” ๋กœ๊ฑฐ์ฃ .

์ด ๊ธฐ๋ณธ ์„ค์ •๋งŒ์œผ๋กœ๋„ ๋กœ๊ทธ๋ฅผ ์ถœ๋ ฅํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์šฐ๋ฆฌ๋Š” ์—ฌ๊ธฐ์„œ ๋ฉˆ์ถ”์ง€ ์•Š์„ ๊ฑฐ์˜ˆ์š”! ๋” ๋‚˜์€, ๋” ํšจ์œจ์ ์ธ ๋กœ๊น… ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค์–ด๋ณผ ๊ฑฐ๋‹ˆ๊นŒ์š”! ๐Ÿ’ช

๐Ÿ’ก Pro Tip: logback-spring.xml ํŒŒ์ผ์€ src/main/resources ๋””๋ ‰ํ† ๋ฆฌ์— ์œ„์น˜์‹œํ‚ค์„ธ์š”. Spring Boot๊ฐ€ ์ž๋™์œผ๋กœ ์ด ํŒŒ์ผ์„ ์ฐพ์•„ ์„ค์ •์„ ์ ์šฉํ•  ๊ฑฐ์˜ˆ์š”!

์ž, ์ด์ œ ๊ธฐ๋ณธ์ ์ธ ์„ค์ • ํŒŒ์ผ์˜ ๊ตฌ์กฐ๋ฅผ ์•Œ์•˜์œผ๋‹ˆ, ๋ณธ๊ฒฉ์ ์œผ๋กœ ์ด ํŒŒ์ผ์„ ํŠœ๋‹ํ•ด๋ณผ๊นŒ์š”? ์—ฌ๋Ÿฌ๋ถ„์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋‚ ๊ฐœ๋ฅผ ๋‹ฌ์•„์ค„ ์‹œ๊ฐ„์ด์—์š”! ๐Ÿš€

๐ŸŽจ Logback ์„ค์ • ์ตœ์ ํ™”: ๋กœ๊ทธ ๋ ˆ๋ฒจ ์กฐ์ •์˜ ๋งˆ๋ฒ•

๋กœ๊ทธ ๋ ˆ๋ฒจ์€ ๋กœ๊น… ์‹œ์Šคํ…œ์˜ ์‹ฌ์žฅ์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ ์ ˆํ•œ ๋กœ๊ทธ ๋ ˆ๋ฒจ ์„ค์ •์€ ํ•„์š”ํ•œ ์ •๋ณด๋งŒ์„ ํšจ๊ณผ์ ์œผ๋กœ ์ˆ˜์ง‘ํ•˜๊ณ , ๋ถˆํ•„์š”ํ•œ ๋กœ๊ทธ๋กœ ์ธํ•œ ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์ฃ . ๊ทธ๋Ÿผ ์–ด๋–ป๊ฒŒ ๋กœ๊ทธ ๋ ˆ๋ฒจ์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”? ๐Ÿค”

Logback์—์„œ ์ œ๊ณตํ•˜๋Š” ๋กœ๊ทธ ๋ ˆ๋ฒจ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์•„์š” (๋‚ฎ์€ ์ˆœ์„œ๋ถ€ํ„ฐ):

  1. TRACE
  2. DEBUG
  3. INFO
  4. WARN
  5. ERROR

๊ฐ ๋ ˆ๋ฒจ์˜ ํŠน์ง•์„ ์‚ดํŽด๋ณผ๊นŒ์š”?

๐ŸŽญ ๋กœ๊ทธ ๋ ˆ๋ฒจ์˜ ํŠน์ง•:

  • TRACE: ๊ฐ€์žฅ ์ƒ์„ธํ•œ ๋กœ๊ทธ ๋ ˆ๋ฒจ. ๊ฐœ๋ฐœ ์ค‘ ๋งค์šฐ ์ž์„ธํ•œ ์ •๋ณด๊ฐ€ ํ•„์š”ํ•  ๋•Œ ์‚ฌ์šฉํ•ด์š”.
  • DEBUG: ๊ฐœ๋ฐœ ์‹œ ๋””๋ฒ„๊น… ๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉํ•ด์š”. ์šด์˜ ํ™˜๊ฒฝ์—์„œ๋Š” ๋ณดํ†ต ๋น„ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค.
  • INFO: ์ผ๋ฐ˜์ ์ธ ์ž‘๋™ ์ •๋ณด๋ฅผ ๋‚˜ํƒ€๋‚ด์š”. ์šด์˜ ํ™˜๊ฒฝ์˜ ๊ธฐ๋ณธ ๋กœ๊ทธ ๋ ˆ๋ฒจ๋กœ ๋งŽ์ด ์‚ฌ์šฉ๋ผ์š”.
  • WARN: ์ž ์žฌ์ ์ธ ๋ฌธ์ œ๋ฅผ ๋‚˜ํƒ€๋‚ด์ง€๋งŒ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๊ณ„์† ์‹คํ–‰๋  ์ˆ˜ ์žˆ๋Š” ์ƒํ™ฉ์ด์—์š”.
  • ERROR: ์‹ฌ๊ฐํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Œ์„ ๋‚˜ํƒ€๋‚ด์š”. ์ฆ‰์‹œ ์กฐ์น˜๊ฐ€ ํ•„์š”ํ•œ ์ƒํ™ฉ์ด์ฃ .

์ž, ์ด์ œ ์ด ๋กœ๊ทธ ๋ ˆ๋ฒจ์„ ์–ด๋–ป๊ฒŒ ์„ค์ •ํ•˜๋ฉด ์ข‹์„๊นŒ์š”? ์—ฌ๊ธฐ ๋ช‡ ๊ฐ€์ง€ ํŒ์„ ๋“œ๋ฆด๊ฒŒ์š”! ๐Ÿ‘‡

  1. ํŒจํ‚ค์ง€๋ณ„ ๋กœ๊ทธ ๋ ˆ๋ฒจ ์„ค์ •: ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ฐ ํŒจํ‚ค์ง€๋งˆ๋‹ค ๋‹ค๋ฅธ ๋กœ๊ทธ ๋ ˆ๋ฒจ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ด€๋ จ ํŒจํ‚ค์ง€๋Š” ์ข€ ๋” ์ƒ์„ธํ•œ ๋กœ๊ทธ๊ฐ€ ํ•„์š”ํ•  ์ˆ˜ ์žˆ์ฃ .
  2. ํ™˜๊ฒฝ๋ณ„ ๋กœ๊ทธ ๋ ˆ๋ฒจ ์„ค์ •: ๊ฐœ๋ฐœ ํ™˜๊ฒฝ๊ณผ ์šด์˜ ํ™˜๊ฒฝ์˜ ๋กœ๊ทธ ๋ ˆ๋ฒจ์„ ๋‹ค๋ฅด๊ฒŒ ๊ฐ€์ ธ๊ฐ€๋Š” ๊ฒƒ์ด ์ข‹์•„์š”. ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ๋Š” DEBUG ๋ ˆ๋ฒจ๋กœ, ์šด์˜ ํ™˜๊ฒฝ์—์„œ๋Š” INFO ๋ ˆ๋ฒจ๋กœ ์„ค์ •ํ•˜๋Š” ์‹์ด์ฃ .
  3. ๋™์  ๋กœ๊ทธ ๋ ˆ๋ฒจ ๋ณ€๊ฒฝ: ์šด์˜ ์ค‘์—๋„ ๋กœ๊ทธ ๋ ˆ๋ฒจ์„ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•˜๋ฉด ๋งค์šฐ ์œ ์šฉํ•ด์š”. ๋ฌธ์ œ ์ƒํ™ฉ์ด ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ๋กœ๊ทธ ๋ ˆ๋ฒจ์„ ์ผ์‹œ์ ์œผ๋กœ ๋‚ฎ์ถฐ์„œ ๋” ์ž์„ธํ•œ ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๊ฑฐ๋“ ์š”.

์ด๋Ÿฐ ์„ค์ •์„ logback-spring.xml์— ์–ด๋–ป๊ฒŒ ๋ฐ˜์˜ํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”? ๋‹ค์Œ ์˜ˆ์ œ๋ฅผ ๋ด์ฃผ์„ธ์š”:

<configuration>
    <!-- ์ฝ˜์†” ์• ํŽœ๋” ์„ค์ • -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- ๋ฃจํŠธ ๋กœ๊ฑฐ ์„ค์ • -->
    <root level="INFO">
        <appender-ref ref="CONSOLE" />
    </root>

    <!-- ํŒจํ‚ค์ง€๋ณ„ ๋กœ๊ทธ ๋ ˆ๋ฒจ ์„ค์ • -->
    <logger name="com.example.myapp.controller" level="DEBUG"/>
    <logger name="com.example.myapp.service" level="INFO"/>
    <logger name="com.example.myapp.repository" level="WARN"/>

    <!-- ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ ๊ด€๋ จ ๋กœ๊ทธ ๋ ˆ๋ฒจ ์„ค์ • -->
    <logger name="org.springframework" level="INFO"/>
    <logger name="org.hibernate" level="WARN"/>
</configuration>

์ด๋ ‡๊ฒŒ ์„ค์ •ํ•˜๋ฉด ๊ฐ ํŒจํ‚ค์ง€๋งˆ๋‹ค ๋‹ค๋ฅธ ๋กœ๊ทธ ๋ ˆ๋ฒจ์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ปจํŠธ๋กค๋Ÿฌ๋Š” DEBUG ๋ ˆ๋ฒจ๋กœ ์ƒ์„ธํ•˜๊ฒŒ, ์„œ๋น„์Šค ๊ณ„์ธต์€ INFO ๋ ˆ๋ฒจ๋กœ, ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ๊ณ„์ธต์€ WARN ๋ ˆ๋ฒจ๋กœ ์„ค์ •ํ–ˆ๋„ค์š”. ์Šคํ”„๋ง๊ณผ ํ•˜์ด๋ฒ„๋„ค์ดํŠธ ๊ด€๋ จ ๋กœ๊ทธ๋„ ๋”ฐ๋กœ ์„ค์ •ํ–ˆ๊ณ ์š”.

์ด๋Ÿฐ ์‹์œผ๋กœ ๋กœ๊ทธ ๋ ˆ๋ฒจ์„ ์กฐ์ •ํ•˜๋ฉด, ํ•„์š”ํ•œ ์ •๋ณด๋Š” ์ถฉ๋ถ„ํžˆ ์–ป์œผ๋ฉด์„œ๋„ ๋ถˆํ•„์š”ํ•œ ๋กœ๊ทธ๋กœ ์ธํ•œ ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์™„์ „ ์ผ์„์ด์กฐ ์•„๋‹ˆ๊ฒ ์–ด์š”? ๐Ÿ˜‰

๐Ÿ’ก Pro Tip: ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์„ ์šด์˜ํ•  ๋•Œ๋Š”, ์‚ฌ์šฉ์ž ํ™œ๋™๊ณผ ๊ด€๋ จ๋œ ์ค‘์š”ํ•œ ์ด๋ฒคํŠธ(์˜ˆ: ๊ฑฐ๋ž˜ ์„ฑ์‚ฌ, ํšŒ์› ๊ฐ€์ž… ๋“ฑ)๋Š” INFO ๋ ˆ๋ฒจ๋กœ, ์‹œ์Šคํ…œ ๋‚ด๋ถ€ ๋™์ž‘์€ DEBUG ๋ ˆ๋ฒจ๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ค‘์š”ํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์€ ๋†“์น˜์ง€ ์•Š์œผ๋ฉด์„œ๋„, ํ•„์š”ํ•  ๋•Œ ์ƒ์„ธํ•œ ์‹œ์Šคํ…œ ๋™์ž‘๋„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ฑฐ๋“ ์š”!

์ž, ์ด์ œ ๋กœ๊ทธ ๋ ˆ๋ฒจ ์„ค์ •์˜ ๋งˆ๋ฒ•์„ ์ตํ˜”์œผ๋‹ˆ, ๋‹ค์Œ ๋‹จ๊ณ„๋กœ ๋„˜์–ด๊ฐˆ ์ค€๋น„๊ฐ€ ๋˜์—ˆ๋‚˜์š”? ๋กœ๊ทธ ์ถœ๋ ฅ ํ˜•์‹์„ ์˜ˆ์˜๊ฒŒ ๊พธ๋ฏธ๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณผ ์ฐจ๋ก€์˜ˆ์š”! ๐ŸŽจโœจ

๐Ÿ’… ๋กœ๊ทธ ๋ฉ”์‹œ์ง€ ์˜ˆ์˜๊ฒŒ ๊พธ๋ฏธ๊ธฐ: ํŒจํ„ด ๋ ˆ์ด์•„์›ƒ์˜ ๋งˆ๋ฒ•

๋กœ๊ทธ ๋ฉ”์‹œ์ง€๋ฅผ ์˜ˆ์˜๊ฒŒ ๊พธ๋ฏธ๋Š” ๊ฒƒ, ๋‹จ์ˆœํžˆ ๋ฏธ์ ์ธ ์ด์œ ๋งŒ์€ ์•„๋‹ˆ์—์š”. ์ž˜ ๊ตฌ์„ฑ๋œ ๋กœ๊ทธ ๋ฉ”์‹œ์ง€๋Š” ๊ฐ€๋…์„ฑ์„ ๋†’์ด๊ณ  ๋ฌธ์ œ ํ•ด๊ฒฐ ์‹œ๊ฐ„์„ ๋‹จ์ถ•์‹œ์ผœ์ค˜์š”. ๊ทธ๋Ÿผ ์–ด๋–ป๊ฒŒ ๋กœ๊ทธ ๋ฉ”์‹œ์ง€๋ฅผ ๊พธ๋ฐ€ ์ˆ˜ ์žˆ์„๊นŒ์š”? ๋ฐ”๋กœ ํŒจํ„ด ๋ ˆ์ด์•„์›ƒ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฑฐ์˜ˆ์š”! ๐ŸŽญ

Logback์˜ ํŒจํ„ด ๋ ˆ์ด์•„์›ƒ์€ ์ •๋ง ๊ฐ•๋ ฅํ•ด์š”. ์‹œ๊ฐ„, ๋กœ๊ทธ ๋ ˆ๋ฒจ, ์Šค๋ ˆ๋“œ ์ด๋ฆ„, ๋กœ๊ฑฐ ์ด๋ฆ„, ๋ฉ”์‹œ์ง€ ๋“ฑ ๋‹ค์–‘ํ•œ ์ •๋ณด๋ฅผ ์›ํ•˜๋Š” ํ˜•์‹์œผ๋กœ ์กฐํ•ฉํ•  ์ˆ˜ ์žˆ์ฃ . ๋ช‡ ๊ฐ€์ง€ ์œ ์šฉํ•œ ํŒจํ„ด ์š”์†Œ๋ฅผ ์‚ดํŽด๋ณผ๊นŒ์š”?

๐ŸŽจ ์œ ์šฉํ•œ ํŒจํ„ด ๋ ˆ์ด์•„์›ƒ ์š”์†Œ:

  • %d{ํŒจํ„ด}: ๋‚ ์งœ์™€ ์‹œ๊ฐ„์„ ํ‘œ์‹œํ•ด์š”. ์˜ˆ: %d{yyyy-MM-dd HH:mm:ss.SSS}
  • %thread: ํ˜„์žฌ ์Šค๋ ˆ๋“œ ์ด๋ฆ„์„ ํ‘œ์‹œํ•ด์š”.
  • %-5level: ๋กœ๊ทธ ๋ ˆ๋ฒจ์„ 5์ž๋ฆฌ๋กœ ๋งž์ถฐ ํ‘œ์‹œํ•ด์š”. '-'๋Š” ์™ผ์ชฝ ์ •๋ ฌ์„ ์˜๋ฏธํ•ด์š”.
  • %logger{๊ธธ์ด}: ๋กœ๊ฑฐ ์ด๋ฆ„์„ ํ‘œ์‹œํ•ด์š”. ๊ธธ์ด๋ฅผ ์ง€์ •ํ•˜๋ฉด ๊ธด ์ด๋ฆ„์„ ์ถ•์•ฝํ•  ์ˆ˜ ์žˆ์–ด์š”.
  • %msg: ์‹ค์ œ ๋กœ๊ทธ ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์‹œํ•ด์š”.
  • %n: ์ค„๋ฐ”๊ฟˆ์„ ์˜๋ฏธํ•ด์š”.
  • %highlight(ํŒจํ„ด){์ƒ‰์ƒ ์Šคํƒ€์ผ}: ์ง€์ •ํ•œ ํŒจํ„ด์— ์ƒ‰์ƒ์„ ์ž…ํ˜€์š”.

์ด๋Ÿฐ ์š”์†Œ๋“ค์„ ์กฐํ•ฉํ•ด์„œ ๋ฉ‹์ง„ ๋กœ๊ทธ ํŒจํ„ด์„ ๋งŒ๋“ค์–ด๋ณผ๊นŒ์š”? ์—ฌ๊ธฐ ์˜ˆ์‹œ๊ฐ€ ์žˆ์–ด์š”:

<configuration>
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{15}) - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="CONSOLE" />
    </root>
</configuration>

์ด ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋ฉด ๋กœ๊ทธ๊ฐ€ ์ด๋ ‡๊ฒŒ ์ถœ๋ ฅ๋ผ์š”:

2023-06-15 14:30:45.123 [main] INFO  c.e.MyApp - ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹œ์ž‘๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
2023-06-15 14:30:46.234 [http-nio-8080-exec-1] DEBUG c.e.c.UserController - ์‚ฌ์šฉ์ž ๋กœ๊ทธ์ธ ์‹œ๋„: user123
2023-06-15 14:30:46.345 [http-nio-8080-exec-1] WARN  c.e.s.UserService - ์ž˜๋ชป๋œ ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ: user123

์–ด๋•Œ์š”? ํ›จ์”ฌ ๋ณด๊ธฐ ์ข‹๊ณ  ์ •๋ณด๋„ ํ•œ๋ˆˆ์— ๋“ค์–ด์˜ค์ฃ ? ๐Ÿ˜Ž

ํ•˜์ง€๋งŒ ์—ฌ๊ธฐ์„œ ๋์ด ์•„๋‹ˆ์—์š”! ๋” ๋ฉ‹์ง„ ๊ธฐ๋Šฅ๋“ค์ด ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ๋‹ต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, MDC(Mapped Diagnostic Context)๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋กœ๊ทธ์— ์ถ”๊ฐ€์ ์ธ ์ปจํ…์ŠคํŠธ ์ •๋ณด๋ฅผ ๋„ฃ์„ ์ˆ˜ ์žˆ์–ด์š”. ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ๋Š” ์ด๋Ÿฐ ๊ธฐ๋Šฅ์ด ํŠนํžˆ ์œ ์šฉํ•  ๊ฑฐ์˜ˆ์š”. ์‚ฌ์šฉ์ž ID๋‚˜ ์„ธ์…˜ ID ๊ฐ™์€ ์ •๋ณด๋ฅผ ๋ชจ๋“  ๋กœ๊ทธ์— ์ž๋™์œผ๋กœ ํฌํ•จ์‹œํ‚ฌ ์ˆ˜ ์žˆ๊ฑฐ๋“ ์š”!

MDC๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด, ๋จผ์ € ์ฝ”๋“œ์—์„œ MDC์— ๊ฐ’์„ ๋„ฃ์–ด์ค˜์•ผ ํ•ด์š”:

import org.slf4j.MDC;

// ์ปจํŠธ๋กค๋Ÿฌ๋‚˜ ์ธํ„ฐ์…‰ํ„ฐ์—์„œ
MDC.put("userId", user.getId());
MDC.put("sessionId", session.getId());

// ๋กœ์ง ์‹คํ–‰ ํ›„
MDC.clear();  // ๊ผญ ํด๋ฆฌ์–ด ํ•ด์ฃผ์„ธ์š”!

๊ทธ๋ฆฌ๊ณ  ๋กœ๊ทธ ํŒจํ„ด์— MDC ๊ฐ’์„ ํฌํ•จ์‹œํ‚ค๋ฉด ๋ผ์š”:

<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{15}) - %X{userId} %X{sessionId} - %msg%n</pattern>

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋กœ๊ทธ๊ฐ€ ์ด๋Ÿฐ ์‹์œผ๋กœ ์ถœ๋ ฅ๋ผ์š”:

2023-06-15 14:35:12.345 [http-nio-8080-exec-2] INFO  c.e.c.UserController - user123 ABC123XYZ - ์‚ฌ์šฉ์ž๊ฐ€ ํ”„๋กœํ•„์„ ์—…๋ฐ์ดํŠธํ–ˆ์Šต๋‹ˆ๋‹ค.

์–ด๋•Œ์š”? ์ด์ œ ๊ฐ ๋กœ๊ทธ๊ฐ€ ์–ด๋–ค ์‚ฌ์šฉ์ž, ์–ด๋–ค ์„ธ์…˜์—์„œ ๋ฐœ์ƒํ–ˆ๋Š”์ง€ ํ•œ๋ˆˆ์— ์•Œ ์ˆ˜ ์žˆ์ฃ ? ์ด๋Ÿฐ ์‹์œผ๋กœ MDC๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋กœ๊ทธ ๋ถ„์„์ด ํ›จ์”ฌ ์‰ฌ์›Œ์ ธ์š”. ํŠนํžˆ ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ๋‹ค์ค‘ ์‚ฌ์šฉ์ž ํ”Œ๋žซํผ์—์„œ๋Š” ์ •๋ง ์œ ์šฉํ•  ๊ฑฐ์˜ˆ์š”! ๐Ÿ‘

๐Ÿ’ก Pro Tip: ๋กœ๊ทธ ํŒจํ„ด์„ ์„ค๊ณ„ํ•  ๋•Œ๋Š” ํ•ญ์ƒ ๊ฐ€๋…์„ฑ๊ณผ ์„ฑ๋Šฅ์˜ ๊ท ํ˜•์„ ๊ณ ๋ คํ•˜์„ธ์š”. ๋„ˆ๋ฌด ๋งŽ์€ ์ •๋ณด๋ฅผ ํฌํ•จ์‹œํ‚ค๋ฉด ๋กœ๊ทธ ํŒŒ์ผ ํฌ๊ธฐ๊ฐ€ ๋น ๋ฅด๊ฒŒ ์ฆ๊ฐ€ํ•  ์ˆ˜ ์žˆ์–ด์š”. ๊ผญ ํ•„์š”ํ•œ ์ •๋ณด๋งŒ ํฌํ•จ์‹œํ‚ค๊ณ , ๋กœ๊ทธ ๋กœํ…Œ์ด์…˜๊ณผ ์••์ถ• ์ „๋žต์„ ์ž˜ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ด์š”!

์ž, ์ด์ œ ๋กœ๊ทธ ๋ฉ”์‹œ์ง€๋ฅผ ์˜ˆ์˜๊ณ  ์œ ์šฉํ•˜๊ฒŒ ๊พธ๋ฏธ๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์› ์–ด์š”. ๋‹ค์Œ์€ ๋กœ๊ทธ๋ฅผ ์–ด๋””์— ์–ด๋–ป๊ฒŒ ์ €์žฅํ• ์ง€ ์•Œ์•„๋ณผ ์ฐจ๋ก€์˜ˆ์š”. ํŒŒ์ผ ์• ํŽœ๋”์™€ ๋กœ๊ทธ ๋กœํ…Œ์ด์…˜์˜ ์„ธ๊ณ„๋กœ ๋“ค์–ด๊ฐ€๋ณผ๊นŒ์š”? ๐Ÿšชโœจ

๐Ÿ“ ๋กœ๊ทธ ํŒŒ์ผ ๊ด€๋ฆฌ์˜ ๋‹ฌ์ธ๋˜๊ธฐ: ํŒŒ์ผ ์• ํŽœ๋”์™€ ๋กœ๊ทธ ๋กœํ…Œ์ด์…˜

์ฝ˜์†”์— ๋กœ๊ทธ๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ๊ฒƒ๋„ ์ข‹์ง€๋งŒ, ์‹ค์ œ ์šด์˜ ํ™˜๊ฒฝ์—์„œ๋Š” ๋กœ๊ทธ๋ฅผ ํŒŒ์ผ๋กœ ์ €์žฅํ•˜๋Š” ๊ฒƒ์ด ํ›จ์”ฌ ๋” ์œ ์šฉํ•ด์š”. ๊ทธ๋Ÿฐ๋ฐ ์—ฌ๊ธฐ์„œ ํ•œ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒจ์š”. ๋กœ๊ทธ ํŒŒ์ผ์ด ๋ฌดํ•œ์ • ์ปค์ง€๋ฉด ์–ด๋–กํ•˜์ฃ ? ๐Ÿค” ๋ฐ”๋กœ ์ด๋•Œ ํ•„์š”ํ•œ ๊ฒŒ ํŒŒ์ผ ์• ํŽœ๋”์™€ ๋กœ๊ทธ ๋กœํ…Œ์ด์…˜์ด์—์š”!

ํŒŒ์ผ ์• ํŽœ๋”๋Š” ๋ง ๊ทธ๋Œ€๋กœ ๋กœ๊ทธ๋ฅผ ํŒŒ์ผ์— ์ถ”๊ฐ€(append)ํ•˜๋Š” ์—ญํ• ์„ ํ•ด์š”. ๊ทธ๋ฆฌ๊ณ  ๋กœ๊ทธ ๋กœํ…Œ์ด์…˜์€ ๋กœ๊ทธ ํŒŒ์ผ์ด ํŠน์ • ์กฐ๊ฑด(ํฌ๊ธฐ๋‚˜ ์‹œ๊ฐ„)์— ๋„๋‹ฌํ–ˆ์„ ๋•Œ ์ƒˆ๋กœ์šด ํŒŒ์ผ์„ ๋งŒ๋“ค๊ณ  ์ด์ „ ํŒŒ์ผ์„ ๋ณด๊ด€ํ•˜๋Š” ๊ธฐ๋Šฅ์ด์—์š”. ์ด ๋‘ ๊ฐ€์ง€๋ฅผ ์ž˜ ์กฐํ•ฉํ•˜๋ฉด ๋กœ๊ทธ ๊ด€๋ฆฌ๊ฐ€ ํ•œ๊ฒฐ ์ˆ˜์›”ํ•ด์ ธ์š”!

์ž, ๊ทธ๋Ÿผ Logback์—์„œ ์–ด๋–ป๊ฒŒ ํŒŒ์ผ ์• ํŽœ๋”์™€ ๋กœ๊ทธ ๋กœํ…Œ์ด์…˜์„ ์„ค์ •ํ•˜๋Š”์ง€ ์‚ดํŽด๋ณผ๊นŒ์š”? ๐Ÿง

<configuration>
    <property name="LOG_PATH" value="./logs" />
    <property name="LOG_FILE_NAME" value="myapp" />

    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/${LOG_FILE_NAME}.log</file>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/${LOG_FILE_NAME}.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
    </appender>

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

์šฐ์™€, ์ข€ ๋ณต์žกํ•ด ๋ณด์ด์ฃ ? ใ…‹ใ…‹ใ…‹ ํ•˜๋‚˜์”ฉ ๋œฏ์–ด๋ณผ๊ฒŒ์š”! ๐Ÿ˜‰

  • <property>: ๋กœ๊ทธ ํŒŒ์ผ ๊ฒฝ๋กœ์™€ ์ด๋ฆ„์„ ๋ณ€์ˆ˜๋กœ ์ •์˜ํ•ด์š”. ๋‚˜์ค‘์— ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ํŽธํ•˜์ฃ !
  • <appender>: RollingFileAppender๋ฅผ ์‚ฌ์šฉํ•ด์š”. ์ด๊ฒŒ ๋ฐ”๋กœ ๋กœ๊ทธ ๋กœํ…Œ์ด์…˜์˜ ํ•ต์‹ฌ์ด์—์š”!
  • <file>: ํ˜„์žฌ ์ž‘์„ฑ ์ค‘์ธ ๋กœ๊ทธ ํŒŒ์ผ์˜ ๊ฒฝ๋กœ๋ฅผ ์ง€์ •ํ•ด์š”.
  • <encoder>: ๋กœ๊ทธ ๋ฉ”์‹œ์ง€์˜ ํ˜•์‹์„ ์ •์˜ํ•ด์š”. ์•„๊นŒ ๋ฐฐ์šด ํŒจํ„ด ๋ ˆ์ด์•„์›ƒ์„ ์—ฌ๊ธฐ์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋ผ์š”.
  • <rollingPolicy>: ๋กœ๊ทธ ๋กœํ…Œ์ด์…˜ ์ •์ฑ…์„ ์ •์˜ํ•ด์š”. ์—ฌ๊ธฐ์„œ๋Š” ์‹œ๊ฐ„ ๊ธฐ๋ฐ˜ ์ •์ฑ…์„ ์‚ฌ์šฉํ–ˆ์–ด์š”.
  • <fileNamePattern>: ๋กœํ…Œ์ด์…˜๋œ ๋กœ๊ทธ ํŒŒ์ผ์˜ ์ด๋ฆ„ ํŒจํ„ด์„ ์ •์˜ํ•ด์š”. ์—ฌ๊ธฐ์„œ๋Š” ๋‚ ์งœ์™€ ์ธ๋ฑ์Šค๋ฅผ ํฌํ•จํ•˜๊ณ , gz๋กœ ์••์ถ•ํ•˜๋„๋ก ํ–ˆ์–ด์š”.
  • <timeBasedFileNamingAndTriggeringPolicy>: ํŒŒ์ผ ํฌ๊ธฐ ๊ธฐ๋ฐ˜์˜ ํŠธ๋ฆฌ๊ฑฐ ์ •์ฑ…์„ ์ถ”๊ฐ€๋กœ ์„ค์ •ํ–ˆ์–ด์š”. 10MB๋งˆ๋‹ค ์ƒˆ ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด์š”.
  • <maxHistory>: ์ตœ๋Œ€ 30์ผ์น˜์˜ ๋กœ๊ทธ ํŒŒ์ผ๋งŒ ๋ณด๊ด€ํ•˜๋„๋ก ์„ค์ •ํ–ˆ์–ด์š”.

์ด๋ ‡๊ฒŒ ์„ค์ •ํ•˜๋ฉด, ๋กœ๊ทธ ํŒŒ์ผ์ด ํ•˜๋ฃจ์— ํ•œ ๋ฒˆ์”ฉ, ๋˜๋Š” 10MB๊ฐ€ ๋  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ํŒŒ์ผ๋กœ ๋กค์˜ค๋ฒ„๋˜๊ณ , 30์ผ์ด ์ง€๋‚œ ํŒŒ์ผ์€ ์ž๋™์œผ๋กœ ์‚ญ์ œ๋ผ์š”. ์™„์ „ ํŽธ๋ฆฌํ•˜์ฃ ? ๐Ÿ˜Ž

๐Ÿ’ก Pro Tip: ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ๋Œ€๊ทœ๋ชจ ํ”Œ๋žซํผ์—์„œ๋Š” ๋กœ๊ทธ ์–‘์ด ์—„์ฒญ๋‚˜๊ฒŒ ๋งŽ์„ ๊ฑฐ์˜ˆ์š”. ์ด๋Ÿฐ ๊ฒฝ์šฐ์—๋Š” ๋กœ๊ทธ๋ฅผ ์—ฌ๋Ÿฌ ํŒŒ์ผ๋กœ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ์—๋Ÿฌ ๋กœ๊ทธ, ์‚ฌ์šฉ์ž ํ™œ๋™ ๋กœ๊ทธ, ์‹œ์Šคํ…œ ๋กœ๊ทธ ๋“ฑ์œผ๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์ฃ . ๊ฐ๊ฐ์— ๋Œ€ํ•ด ๋ณ„๋„์˜ ์• ํŽœ๋”๋ฅผ ์„ค์ •ํ•˜๋ฉด ๋ผ์š”!

์ž, ์ด์ œ ๋กœ๊ทธ ํŒŒ์ผ ๊ด€๋ฆฌ์˜ ๊ธฐ๋ณธ์„ ๋ฐฐ์› ์–ด์š”. ํ•˜์ง€๋งŒ ์—ฌ๊ธฐ์„œ ๋์ด ์•„๋‹ˆ์—์š”! ๋” ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ๋“ค์ด ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ๋‹ต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋น„๋™๊ธฐ ๋กœ๊น…์„ ์‚ฌ์šฉํ•˜๋ฉด ๋กœ๊น…์œผ๋กœ ์ธํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ์ตœ์†Œํ™”ํ•  ์ˆ˜ ์žˆ์–ด์š”. ํ•œ๋ฒˆ ์‚ดํŽด๋ณผ๊นŒ์š”? ๐Ÿš€

<configuration>
    <!-- ๊ธฐ์กด FILE ์• ํŽœ๋” ์„ค์ • -->

    <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="FILE" />
        <queueSize>512</queueSize>
        <discardingThreshold>0</discardingThreshold>
    </appender>

    <root level="INFO">
        <appender-ref ref="ASYNC" />
    </root>
</configuration>

์ด๋ ‡๊ฒŒ AsyncAppender๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ๋กœ๊ทธ ๋ฉ”์‹œ์ง€๊ฐ€ ๋จผ์ € ๋ฉ”๋ชจ๋ฆฌ ํ์— ์ €์žฅ๋˜๊ณ , ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ์—์„œ ํŒŒ์ผ์— ๊ธฐ๋ก๋ผ์š”. ๋•๋ถ„์— ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ฃผ ์Šค๋ ˆ๋“œ๋Š” ๋กœ๊น… ์ž‘์—…์œผ๋กœ ์ธํ•ด ๋ธ”๋กœํ‚น๋˜์ง€ ์•Š์•„์š”. ์„ฑ๋Šฅ ํ–ฅ์ƒ์˜ ๋งˆ๋ฒ•์ด์ฃ ! โœจ

๊ทธ๋ฆฌ๊ณ  ๋˜ ํ•˜๋‚˜! ๋กœ๊ทธ ํŒŒ์ผ์„ ์••์ถ•ํ•˜๋Š” ๊ฒƒ๋„ ์žŠ์ง€ ๋งˆ์„ธ์š”. ๋กœ๊ทธ ํŒŒ์ผ์€ ๋ณดํ†ต ํ…์ŠคํŠธ๋ผ ์••์ถ•๋ฅ ์ด ๋†’์•„์š”. gzip์œผ๋กœ ์••์ถ•ํ•˜๋ฉด ์ €์žฅ ๊ณต๊ฐ„์„ ํฌ๊ฒŒ ์ ˆ์•ฝํ•  ์ˆ˜ ์žˆ์ฃ . ์œ„์˜ ์„ค์ •์—์„œ ์ด๋ฏธ .gz ํ™•์žฅ์ž๋ฅผ ์‚ฌ์šฉํ•ด ์ž๋™ ์••์ถ•์„ ์ ์šฉํ–ˆ์–ด์š”.

๐ŸŽ“ Advanced Tip: ๋Œ€๊ทœ๋ชจ ์‹œ์Šคํ…œ์—์„œ๋Š” ๋กœ๊ทธ๋ฅผ ์ค‘์•™ ์ง‘์ค‘์‹์œผ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„์š”. ELK ์Šคํƒ(Elasticsearch, Logstash, Kibana)์ด๋‚˜ Splunk ๊ฐ™์€ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์—ฌ๋Ÿฌ ์„œ๋ฒ„์˜ ๋กœ๊ทธ๋ฅผ ํ•œ ๊ณณ์—์„œ ๋ชจ์•„๋ณด๊ณ  ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์–ด์š”. Logback์—์„œ๋Š” SocketAppender๋ฅผ ์‚ฌ์šฉํ•ด ์ด๋Ÿฐ ์‹œ์Šคํ…œ์œผ๋กœ ๋กœ๊ทธ๋ฅผ ์ „์†กํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค!

์ž, ์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์€ ๋กœ๊ทธ ํŒŒ์ผ ๊ด€๋ฆฌ์˜ ๋‹ฌ์ธ์ด ๋˜์—ˆ์–ด์š”! ๐Ÿ† ํŒŒ์ผ ์• ํŽœ๋”์™€ ๋กœ๊ทธ ๋กœํ…Œ์ด์…˜, ๋น„๋™๊ธฐ ๋กœ๊น…๊นŒ์ง€ ๋งˆ์Šคํ„ฐํ–ˆ์œผ๋‹ˆ ์ด์ œ ์–ด๋–ค ์ƒํ™ฉ์—์„œ๋„ ๋กœ๊ทธ ๊ด€๋ฆฌ๋ฅผ ์™„๋ฒฝํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”. ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ๋Œ€๊ทœ๋ชจ ํ”Œ๋žซํผ์—์„œ๋„ ๋ฌธ์ œ์—†์ด ๋กœ๊ทธ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒ ์ฃ ?

๋‹ค์Œ ์„น์…˜์—์„œ๋Š” ๋กœ๊ทธ ํ•„ํ„ฐ๋ง๊ณผ ๋งˆ์Šคํ‚น์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ ๊ฑฐ์˜ˆ์š”. ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ ์–ด๋–ป๊ฒŒ ๋ณดํ˜ธํ•˜๋ฉด์„œ ๋กœ๊น…ํ•  ์ˆ˜ ์žˆ์„์ง€, ํ•จ๊ป˜ ์‚ดํŽด๋ณด์•„์š”! ์ค€๋น„๋˜์…จ๋‚˜์š”? Let's go! ๐Ÿš€

๐Ÿ•ต๏ธโ€โ™€๏ธ ๋น„๋ฐ€ ์š”์›์˜ ํ•„์ˆ˜ ์Šคํ‚ฌ: ๋กœ๊ทธ ํ•„ํ„ฐ๋ง๊ณผ ๋งˆ์Šคํ‚น

์ž, ์ด์ œ ์šฐ๋ฆฌ๋Š” ๋กœ๊ทธ๋ฅผ ์–ด๋””์— ์–ด๋–ป๊ฒŒ ์ €์žฅํ• ์ง€ ์•Œ๊ฒŒ ๋˜์—ˆ์–ด์š”. ํ•˜์ง€๋งŒ ์ž ๊น, ์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ๋ฌธ์ œ๊ฐ€ ํ•˜๋‚˜ ์žˆ์–ด์š”. ๋ฐ”๋กœ ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฃฐ ๊ฒƒ์ธ๊ฐ€ ํ•˜๋Š” ๊ฑฐ์ฃ . ๐Ÿคซ

์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ๋Š” ์‚ฌ์šฉ์ž์˜ ๊ฐœ์ธ์ •๋ณด, ๊ฒฐ์ œ ์ •๋ณด ๋“ฑ ๋ฏผ๊ฐํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃจ๊ฒŒ ๋  ๊ฑฐ์˜ˆ์š”. ์ด๋Ÿฐ ์ •๋ณด๊ฐ€ ๊ทธ๋Œ€๋กœ ๋กœ๊ทธ์— ๋‚จ๋Š”๋‹ค๋ฉด? ํฐ์ผ ๋‚˜๊ฒ ์ฃ ! ๐Ÿ˜ฑ ๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ์—๊ฒ ๋กœ๊ทธ ํ•„ํ„ฐ๋ง๊ณผ ๋งˆ์Šคํ‚น ๊ธฐ์ˆ ์ด ํ•„์š”ํ•ด์š”.

Logback์—์„œ๋Š” ํ•„ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด ํŠน์ • ๋กœ๊ทธ๋ฅผ ์ œ์™ธํ•˜๊ฑฐ๋‚˜, ์ปจ๋ฒ„ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด ํŠน์ • ํŒจํ„ด์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋งˆ์Šคํ‚นํ•  ์ˆ˜ ์žˆ์–ด์š”. ์–ด๋–ป๊ฒŒ ํ•˜๋Š”์ง€ ์‚ดํŽด๋ณผ๊นŒ์š”? ๐Ÿง

1. ๋กœ๊ทธ ํ•„ํ„ฐ๋ง

๋จผ์ €, ํŠน์ • ํŒจํ„ด์˜ ๋กœ๊ทธ๋ฅผ ์•„์˜ˆ ๊ธฐ๋กํ•˜์ง€ ์•Š๋„๋ก ํ•„ํ„ฐ๋งํ•ด๋ณผ๊ฒŒ์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ํฌํ•จ๋œ ๋กœ๊ทธ๋Š” ๋ชจ๋‘ ์ œ์™ธํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์ด๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ์–ด์š”:

<configuration>
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
            <evaluator class="ch.qos.logback.classic.boolex.JaninoEventEvaluator">
                <expression>return message.contains("password");</expression>
            </evaluator>
            <OnMatch>DENY</OnMatch>
        </filter>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="CONSOLE" />
    </root>
</configuration>

์ด ์„ค์ •์€ "password"๋ผ๋Š” ๋‹จ์–ด๊ฐ€ ํฌํ•จ๋œ ๋ชจ๋“  ๋กœ๊ทธ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฌด์‹œํ•ด์š”. ์™„์ „ ๋น„๋ฐ€ ์š”์› ์Šคํƒ€์ผ์ด์ฃ ? ๐Ÿ˜Ž

2. ๋ฐ์ดํ„ฐ ๋งˆ์Šคํ‚น

๋•Œ๋กœ๋Š” ๋กœ๊ทธ๋ฅผ ์™„์ „ํžˆ ์ œ์™ธํ•˜๋Š” ๋Œ€์‹ , ๋ฏผ๊ฐํ•œ ๋ถ€๋ถ„๋งŒ ๊ฐ€๋ฆฌ๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ์–ด์š”. ์ด๋Ÿด ๋•Œ๋Š” ์ปจ๋ฒ„ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ผ์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ด๋ฉ”์ผ ์ฃผ์†Œ์˜ ์ผ๋ถ€๋ฅผ ๊ฐ€๋ฆฌ๊ณ  ์‹ถ๋‹ค๋ฉด:

<configuration>
    <conversionRule conversionWord="maskedMsg" 
                    converterClass="com.example.log.MaskingConverter" />

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %maskedMsg%n</pattern>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="CONSOLE" />
    </root>
</configuration>

์—ฌ๊ธฐ์„œ MaskingConverter๋Š” ์ง์ ‘ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ํด๋ž˜์Šค์˜ˆ์š”. ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์ฃ :

import ch.qos.logback.classic.pattern.MessageConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;

public class MaskingConverter extends MessageConverter {
    private static final String EMAIL_REGEX = "(\\w+)(\\.\\w+)*@(\\w+\\.)(\\w+)(\\.\\w+)*";
    private static final String MASK = "$1****@$3$4";

    @Override
    public String convert(ILoggingEvent event) {
        String message = event.getFormattedMessage();
        return message.replaceAll(EMAIL_REGEX, MASK);
    }
}

์ด ์ปจ๋ฒ„ํ„ฐ๋Š” ์ด๋ฉ”์ผ ์ฃผ์†Œ์˜ ๋กœ์ปฌ ํŒŒํŠธ(@ ์•ž๋ถ€๋ถ„)๋ฅผ ๋งˆ์Šคํ‚นํ•ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, "user.name@example.com"์€ "user****@example.com"์œผ๋กœ ๋ณ€ํ™˜๋˜์ฃ .

๐Ÿ’ก Pro Tip: ๋งˆ์Šคํ‚น ๊ทœ์น™์€ ํšŒ์‚ฌ์˜ ๋ณด์•ˆ ์ •์ฑ…์— ๋”ฐ๋ผ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์–ด์š”. ์‹ ์šฉ์นด๋“œ ๋ฒˆํ˜ธ, ์ฃผ๋ฏผ๋“ฑ๋ก๋ฒˆํ˜ธ ๋“ฑ ๋‹ค์–‘ํ•œ ํ˜•ํƒœ์˜ ๋ฏผ๊ฐ ์ •๋ณด์— ๋Œ€ํ•ด ๊ฐ๊ฐ ๋‹ค๋ฅธ ๋งˆ์Šคํ‚น ๊ทœ์น™์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค. ์ •๊ทœํ‘œํ˜„์‹์„ ์ž˜ ํ™œ์šฉํ•˜๋ฉด ๊ฑฐ์˜ ๋ชจ๋“  ํ˜•ํƒœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋งˆ์Šคํ‚นํ•  ์ˆ˜ ์žˆ์–ด์š”!

์ด๋ ‡๊ฒŒ ํ•„ํ„ฐ๋ง๊ณผ ๋งˆ์Šคํ‚น์„ ์ ์šฉํ•˜๋ฉด, ๋กœ๊ทธ์—์„œ ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๋ณดํ˜ธํ•  ์ˆ˜ ์žˆ์–ด์š”. ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ๋Š” ์‚ฌ์šฉ์ž์˜ ๊ฐœ์ธ์ •๋ณด ๋ณดํ˜ธ๊ฐ€ ์ •๋ง ์ค‘์š”ํ•˜๋‹ˆ๊นŒ, ์ด๋Ÿฐ ๊ธฐ์ˆ ์€ ํ•„์ˆ˜๊ฒ ์ฃ ?

ํ•˜์ง€๋งŒ ์ฃผ์˜ํ•˜์„ธ์š”! ๋กœ๊ทธ ํ•„ํ„ฐ๋ง๊ณผ ๋งˆ์Šคํ‚น์„ ๋„ˆ๋ฌด ๊ณผ๋„ํ•˜๊ฒŒ ์ ์šฉํ•˜๋ฉด ํ•„์š”ํ•œ ์ •๋ณด๊นŒ์ง€ ๋†“์น  ์ˆ˜ ์žˆ์–ด์š”. ํ•ญ์ƒ ๋ณด์•ˆ๊ณผ ์œ ์šฉ์„ฑ ์‚ฌ์ด์˜ ๊ท ํ˜•์„ ์ž˜ ๋งž์ถ”๋Š” ๊ฒŒ ์ค‘์š”ํ•ด์š”. ๐Ÿ˜‰

์ž, ์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์€ ์ง„์ •ํ•œ ๋กœ๊ทธ ๋‹Œ์ž๊ฐ€ ๋˜์—ˆ์–ด์š”! ๐Ÿฅท ๋กœ๊ทธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ €์žฅํ•˜๊ณ , ๊ด€๋ฆฌํ•˜๊ณ , ์‹ฌ์ง€์–ด ๋ฏผ๊ฐํ•œ ์ •๋ณด๋„ ๋ณดํ˜ธํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์œผ๋‹ˆ๊นŒ์š”. ์ด์ œ ๋งˆ์ง€๋ง‰์œผ๋กœ, ๋ชจ๋“  ๊ฒƒ์„ ์ข…ํ•ฉํ•ด์„œ ์‹ค์ œ ์šด์˜ ํ™˜๊ฒฝ์— ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ๊นŒ์š”? ์ค€๋น„๋˜์…จ๋‚˜์š”? ๋งˆ์ง€๋ง‰ ์ŠคํผํŠธ ํ•œ๋ฒˆ ํ•ด๋ด์š”! ๐Ÿ’ช

๐Ÿ ์‹ค์ „ ์ ์šฉ: ์™„๋ฒฝํ•œ Logback ์„ค์ •์˜ ์ •์ 

๋“œ๋””์–ด ๋งˆ์ง€๋ง‰ ๋‹จ๊ณ„์— ๋„๋‹ฌํ–ˆ์–ด์š”! ๐ŸŽ‰ ์ง€๊ธˆ๊นŒ์ง€ ๋ฐฐ์šด ๋ชจ๋“  ๊ฒƒ์„ ์ข…ํ•ฉํ•ด์„œ, ์‹ค์ œ ์šด์˜ ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์™„๋ฒฝํ•œ Logback ์„ค์ •์„ ๋งŒ๋“ค์–ด๋ณผ ๊ฑฐ์˜ˆ์š”. ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ๋Œ€๊ทœ๋ชจ ํ”Œ๋žซํผ์— ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ˆ˜์ค€์˜ ์„ค์ •์ด ๋  ๊ฑฐ์˜ˆ์š”. ์ค€๋น„๋˜์…จ๋‚˜์š”? ๐Ÿ˜Ž

๋จผ์ €, ์šฐ๋ฆฌ์˜ ์ตœ์ข… logback-spring.xml ํŒŒ์ผ์„ ์‚ดํŽด๋ณผ๊ฒŒ์š”:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <property name="LOG_PATH" value="./logs" />
    <property name="LOG_FILE_NAME" value="myapp" />

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{15}) - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/${LOG_FILE_NAME}.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/${LOG_FILE_NAME}.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
    </appender>

    <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="FILE" />
        <queueSize>512</queueSize>
        <discardingThreshold>0</discardingThreshold>
    </appender>

    <conversionRule conversionWord="maskedMsg" 
                    converterClass="com.example.log.MaskingConverter" />

    <logger name="com.example.myapp" level="DEBUG" additivity="false">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="ASYNC" />
    </logger>

    <root level="INFO">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="ASYNC" />
    </root>
</configuration>

์šฐ์™€, ์ •๋ง ์™„๋ฒฝํ•œ ์„ค์ •์ด์ฃ ? ๐Ÿ˜ ์ด ์„ค์ •์ด ์–ด๋–ค ์ผ์„ ํ•˜๋Š”์ง€ ํ•˜๋‚˜์”ฉ ์‚ดํŽด๋ณผ๊ฒŒ์š”:

  1. ์ฝ˜์†”๊ณผ ํŒŒ์ผ ๋‘ ๊ฐ€์ง€ ๋ฐฉ์‹์œผ๋กœ ๋กœ๊ทธ๋ฅผ ์ถœ๋ ฅํ•ด์š”.
  2. ํŒŒ์ผ ๋กœ๊ทธ๋Š” ๋‚ ์งœ๋ณ„, ํฌ๊ธฐ๋ณ„๋กœ ๋กค๋ง๋˜๋ฉฐ, ์••์ถ• ์ €์žฅ๋ผ์š”.
  3. ๋น„๋™๊ธฐ ๋กœ๊น…์„ ์‚ฌ์šฉํ•ด ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ–ˆ์–ด์š”.
  4. ์ปค์Šคํ…€ ๋งˆ์Šคํ‚น ์ปจ๋ฒ„ํ„ฐ๋ฅผ ์ ์šฉํ•ด ๋ฏผ๊ฐ ์ •๋ณด๋ฅผ ๋ณดํ˜ธํ•ด์š”.
  5. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํŒจํ‚ค์ง€๋Š” DEBUG ๋ ˆ๋ฒจ๋กœ, ๊ทธ ์™ธ๋Š” INFO ๋ ˆ๋ฒจ๋กœ ๋กœ๊น…ํ•ด์š”.

์ด ์„ค์ •์„ ์‚ฌ์šฉํ•˜๋ฉด, ๊ฐœ๋ฐœ ์‹œ์—๋Š” ์ฝ˜์†”์—์„œ ์ƒ์„ธํ•œ ๋กœ๊ทธ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ณ , ์šด์˜ ํ™˜๊ฒฝ์—์„œ๋Š” ํŒŒ์ผ๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ๋กœ๊ทธ๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ์–ด์š”. ๊ฒŒ๋‹ค๊ฐ€ ๋ฏผ๊ฐ ์ •๋ณด๋„ ์ž๋™์œผ๋กœ ๋งˆ์Šคํ‚น๋˜๋‹ˆ ๋ณด์•ˆ๋„ ์™„๋ฒฝํ•˜์ฃ !

๐Ÿ’ก Pro Tip: ์‹ค์ œ ์šด์˜ ํ™˜๊ฒฝ์—์„œ๋Š” ๋กœ๊ทธ ๋ ˆ๋ฒจ์„ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„์š”. Spring Boot Actuator๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋Ÿฐํƒ€์ž„์— ๋กœ๊ทธ ๋ ˆ๋ฒจ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค. ๋ฌธ์ œ ์ƒํ™ฉ์ด ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ๋งค์šฐ ์œ ์šฉํ•ด์š”!

์ž, ์ด์ œ ์ •๋ง ์™„๋ฒฝํ•œ Logback ์„ค์ •์ด ์™„์„ฑ๋์–ด์š”. ์ด ์„ค์ •์„ ์‚ฌ์šฉํ•˜๋ฉด ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ๋Œ€๊ทœ๋ชจ ํ”Œ๋žซํผ์—์„œ๋„ ๋กœ๊ทธ ๊ด€๋ฆฌ๋ฅผ ์™„๋ฒฝํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”. ๋กœ๊ทธ ์ƒ์„ฑ๋ถ€ํ„ฐ ์ €์žฅ, ๊ด€๋ฆฌ, ๋ณด์•ˆ๊นŒ์ง€ ๋ชจ๋“  ๊ฒƒ์„ ์ปค๋ฒ„ํ–ˆ์œผ๋‹ˆ๊นŒ์š”! ๐Ÿ‘

๋งˆ์ง€๋ง‰์œผ๋กœ, ๋กœ๊น…์€ ๋‹จ์ˆœํžˆ ๊ธฐ์ˆ ์ ์ธ ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๋ผ๋Š” ์ ์„ ๊ธฐ์–ตํ•˜์„ธ์š”. ์ข‹์€ ๋กœ๊น… ์ „๋žต์€ ๊ฐœ๋ฐœ ์ƒ์‚ฐ์„ฑ์„ ๋†’์ด๊ณ , ๋ฌธ์ œ ํ•ด๊ฒฐ ์‹œ๊ฐ„์„ ๋‹จ์ถ•์‹œํ‚ค๋ฉฐ, ์‹œ์Šคํ…œ์˜ ์•ˆ์ •์„ฑ์„ ๋†’์—ฌ์ค˜์š”. ์—ฌ๋Ÿฌ๋ถ„์˜ ๋กœ๊น… ์ „๋žต์ด ์ด ๋ชจ๋“  ๊ฒƒ์„ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž„๊ฒŒ์š”! ๐ŸŒŸ

์—ฌ๊ธฐ๊นŒ์ง€ ๊ธด ์—ฌ์ •์„ ํ•จ๊ป˜ ํ•ด์ฃผ์…”์„œ ์ •๋ง ๊ฐ์‚ฌํ•ด์š”. ์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์€ Logback ๋งˆ์Šคํ„ฐ๊ฐ€ ๋˜์—ˆ์–ด์š”! ๐Ÿ† ์•ž์œผ๋กœ ์—ฌ๋Ÿฌ๋ถ„์˜ ํ”„๋กœ์ ํŠธ์—์„œ ๋กœ๊น… ๋ฌธ์ œ๋กœ ๊ณ ๋ฏผํ•˜๋Š” ์ผ์€ ์—†์„ ๊ฑฐ์˜ˆ์š”. ํ™”์ดํŒ…! ๐Ÿ’ช๐Ÿ˜„