๐ Logback: ๋ก๊น ์ ๋ํ์, ์ด๊ฑฐ ํ๋๋ฉด ๋ค ๋๋ค! ๐

์๋ ํ์ธ์, ์ฌ๋ฌ๋ถ! ์ค๋์ Java ๊ฐ๋ฐ์๋ค์ ํ์ ์น๊ตฌ, Logback์ ๋ํด ๊น~์ํ ํํค์ณ๋ณผ ๊ฑฐ์์. ๋ก๊น ์ด ๋ญ ๊ทธ๋ ๊ฒ ์ค์ํ๋๊ณ ์? ใ ใ ใ ์์ด~ ๊ฐ๋ฐ์๋ผ๋ฉด ๋ก๊ทธ ์์ด ์ด๋ป๊ฒ ์ด์์! ๋ก๊ทธ๋ ์ฐ๋ฆฌ์ ๋๊ณผ ๊ท์์. ์ฑ์ด ๋ญ ํ๋์ง, ์ด๋์ ๋ฌธ์ ๊ฐ ์๊ฒผ๋์ง ๋ค ์๋ ค์ฃผ๋ ๋ ๋ ํ ์กฐ๋ ฅ์๋ผ๊ณ ์! ๐
๊ทธ๋ฐ๋ฐ ๋ง์ ๋๋ค, ๋ก๊น ํ๋ ์์ํฌ ์ค์์๋ Logback์ด ํน๋ณํ ์ด์ ๊ฐ ๋ญ๊น์? ์ ์ด๋ ๊ฒ ์ธ๊ธฐ๊ฐ ๋ง์๊น์? ์, ์ด์ ๋ถํฐ Logback์ ์ธ๊ณ๋ก ํ~๋ฉ ๋น ์ ธ๋ด ์๋ค! ๐โโ๏ธ
๐ก TMI: Logback์ Log4j์ ํ์์์ด์์. Log4j๋ฅผ ๋ง๋ ๊ฐ๋ฐ์๊ฐ "๋ ์ข์ ๊ฑธ ๋ง๋ค์ด๋ณด์!"ํ๊ณ ๋ง๋ ๊ฑฐ์ฃ . ๊ทธ๋์ Log4j์ ์ฅ์ ์ ๋ค ๊ฐ์ ธ์ค๊ณ , ๋จ์ ์ ๋ณด์ํ๋ต๋๋ค. ์งํ์ ๊ฒฐ์ ์ฒด๋ผ๊ณ ํ ์ ์์ฃ !
์, ์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก Logback์ ๋ํด ์์๋ณผ ํ ๋ฐ์. ์ฌ๋ฌ๋ถ, ์ค๋น๋์ จ๋์? ๋ก๊น ์ ์ธ๊ณ๋ก ๋ ๋๋ด ์๋ค! ๐
๐ Logback์ด ๋ญ๊ธธ๋? ๐
Logback์ Java ์ง์์์ ๊ฐ์ฅ ์ธ๊ธฐ ์๋ ๋ก๊น ํ๋ ์์ํฌ ์ค ํ๋์์. ๊ทธ๋ฅ ์ธ๊ธฐ์๋ ๊ฒ ์๋๋ผ, ์ด์ด์ด์ธ๊ธฐ๋๋๋ค! ์ ๊ทธ๋ฐ์ง ํจ๊ป ์์๋ณผ๊น์?
- ๐ ๋น ๋ฅธ ์๋: Logback์ ๋ค๋ฅธ ๋ก๊น ํ๋ ์์ํฌ๋ณด๋ค ํจ์ฌ ๋น ๋ฅด๋์. ๋ก๊ทธ ์ฐ๋ ์๋๊ฐ ๊ด์์ด๋ผ๋๊น์?
- ๐ง ์ ์ฐํ ์ค์ : XML, Groovy, Java ์ฝ๋๋ก ์ค์ ํ ์ ์์ด์. ์ทจํฅ๊ป ๊ณจ๋ผ ์ฐ์ธ์!
- ๐จ ๋ค์ํ ์ถ๋ ฅ ์ต์ : ์ฝ์, ํ์ผ, ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ฑ ์ด๋๋ ๋ก๊ทธ๋ฅผ ๋จ๊ธธ ์ ์์ด์.
- ๐ ์๋ ๋ฆฌ๋ก๋: ์ค์ ํ์ผ์ด ๋ฐ๋๋ฉด ์์์ ๋ค์ ๋ก๋ํด์. ๊ฐ๋ฐ์ ์ฌ๋ฌ๋ถ, ์ด์ ์๋ฒ ์ฌ์์์ ์๋ ~
์ด๋ ๊ฒ ์ข์ ๊ธฐ๋ฅ๋ค์ด ์์ผ๋, Java ๊ฐ๋ฐ์๋ค์ด Logback์ ์ฌ๋ํ ์๋ฐ์ ์๊ฒ ์ฃ ? ๐
๐ ๊ฐ๋ฐ์ TMI: Logback์ SLF4J(Simple Logging Facade for Java)์ ์ฐฐ๋ก๊ถํฉ์ด์์. SLF4J๋ ๋ก๊น ํ๋ ์์ํฌ๋ฅผ ์ํ ์ถ์ํ ๊ณ์ธต์ธ๋ฐ, Logback๊ณผ ํจ๊ป ์ฐ๋ฉด ์ง์ง ์๋ฒฝํด์!
์, ์ด์ Logback์ด ๋ญ์ง ๋์ถฉ ๊ฐ์ด ์ค์๋์? ใ ใ ใ ์์ง ์์์ ๋ถ๊ณผํด์! ์ด์ ๋ถํฐ๊ฐ ์ง์ง์์. Logback์ ํต์ฌ ์ปดํฌ๋ํธ๋ค์ ํ๋์ฉ ๊น~์ ํํค์ณ๋ณผ ๊ฑฐ์์. ์ค๋น๋์ จ๋์? ๊ณ ๊ณ ์ฝ! ๐โโ๏ธ๐จ
๐งฉ Logback์ ํต์ฌ ์ปดํฌ๋ํธ ๐งฉ
Logback์ ํฌ๊ฒ ์ธ ๊ฐ์ง ํต์ฌ ์ปดํฌ๋ํธ๋ก ๊ตฌ์ฑ๋์ด ์์ด์. ์ด ์ธ ๊ฐ์ง๋ง ์ ๋๋ก ์๋ฉด Logback ๋ง์คํฐ๊ฐ ๋ ์ ์๋ต๋๋ค! ์, ํ๋์ฉ ์์๋ณผ๊น์?
1. Logger (๋ก๊ฑฐ) ๐
Logger๋ ๋ก๊น ์ ์ฃผ์ธ๊ณต์ด์์. ์ฌ๋ฌ๋ถ์ด ์ฝ๋์์ ์ง์ ์ฌ์ฉํ๋ ๋ ์์ด์ฃ . ๋ก๊ทธ๋ฅผ ๋จ๊ธฐ๊ณ ์ถ์ ๋๋ง๋ค Logger๋ฅผ ํตํด ๋ฉ์์ง๋ฅผ ์ ๋ฌํด์.
Logger logger = LoggerFactory.getLogger(MyClass.class);
logger.info("์ด๊ฒ์ ์ ๋ณด ๋ก๊ทธ์
๋๋ค.");
logger.error("์ด๋ฐ! ์๋ฌ๊ฐ ๋ฐ์ํ์ด์!");
์ด๋ ๊ฒ ์ฌ์ฉํ๋ฉด ๋๋๋ฐ, ์ง์ง ์ฝ์ฃ ? ใ ใ ใ
2. Appender (์ดํ๋) ๐ค
Appender๋ ๋ก๊ทธ๋ฅผ ์ด๋์ ์ถ๋ ฅํ ์ง ๊ฒฐ์ ํด์. ์ฝ์์ ๋์ธ ์๋ ์๊ณ , ํ์ผ์ ์ ์ฅํ ์๋ ์๊ณ , ์ฌ์ง์ด ์ด๋ฉ์ผ๋ก ๋ณด๋ผ ์๋ ์์ด์! ์์ฐ~
- ConsoleAppender: ์ฝ์์ ๋ก๊ทธ๋ฅผ ์ถ๋ ฅํด์.
- FileAppender: ํ์ผ์ ๋ก๊ทธ๋ฅผ ์ ์ฅํด์.
- RollingFileAppender: ํ์ผ์ ๋ก๊ทธ๋ฅผ ์ ์ฅํ๋๋ฐ, ํ์ผ ํฌ๊ธฐ๋ ์๊ฐ์ ๋ฐ๋ผ ์ ํ์ผ์ ๋ง๋ค์ด์.
- DBAppender: ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ก๊ทธ๋ฅผ ์ ์ฅํด์.
- SMTPAppender: ์ด๋ฉ์ผ๋ก ๋ก๊ทธ๋ฅผ ๋ณด๋ด์. (๊ธด๊ธ ์ํฉ์ ์ ์ฉํ๊ฒ ์ฃ ?)
3. Layout (๋ ์ด์์) ๐จ
Layout์ ๋ก๊ทธ ๋ฉ์์ง์ ํ์์ ๊ฒฐ์ ํด์. ๋ก๊ทธ๋ฅผ ์ด๋ค ๋ชจ์์ผ๋ก ์ถ๋ ฅํ ์ง ์ ํ๋ ๊ฑฐ์ฃ .
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
์ด๋ฐ ์์ผ๋ก ํจํด์ ์ ์ํ๋ฉด, ๋ก๊ทธ๊ฐ ์๋์ ๊ฐ์ด ์ถ๋ ฅ๋ผ์:
15:04:05.123 [main] INFO com.example.MyClass - ์๋
ํ์ธ์, Logback!
๐ก ๊ฟํ: PatternLayout์ ์ฌ์ฉํ๋ฉด ๋ก๊ทธ ๋ฉ์์ง๋ฅผ ์ํ๋ ๋๋ก ๊พธ๋ฐ ์ ์์ด์. ์๊ฐ, ์ค๋ ๋, ๋ก๊ทธ ๋ ๋ฒจ, ํด๋์ค ์ด๋ฆ ๋ฑ ๋ค์ํ ์ ๋ณด๋ฅผ ๋ฃ์ ์ ์๋ต๋๋ค!
์ด ์ธ ๊ฐ์ง ์ปดํฌ๋ํธ๊ฐ ์ด์ฐ๋ฌ์ ธ์ Logback์ ๋ง๋ฒ์ด ํ์ํ๋ ๊ฑฐ์์. Logger๊ฐ ๋ก๊ทธ๋ฅผ ๋ง๋ค๊ณ , Appender๊ฐ ์ด๋์ ์ถ๋ ฅํ ์ง ์ ํ๊ณ , Layout์ด ์ด๋ป๊ฒ ๋ณด์ฌ์ค์ง ๊ฒฐ์ ํ๋ ๊ฑฐ์ฃ . ์๋ฒฝํ ํ์ํฌ ์๋๊ฒ ์ด์? ๐
์, ์ด์ Logback์ ๊ธฐ๋ณธ ๊ตฌ์กฐ๋ฅผ ์์์ผ๋, ๋ค์์ ์ค์ ๋ก ์ด๋ป๊ฒ ์ค์ ํ๊ณ ์ฌ์ฉํ๋์ง ์์๋ณผ๊น์? ๊ณ ๊ณ ์ฝ! ๐
๐ ๏ธ Logback ์ค์ ํ๊ธฐ: ์ด๋ณด์๋ ํ ์ ์์ด์! ๐ ๏ธ
์, ์ด์ Logback์ ์ด๋ป๊ฒ ์ค์ ํ๋์ง ์์๋ณผ ์ฐจ๋ก์์. ๊ฑฑ์ ๋ง์ธ์, ์๊ฐ๋ณด๋ค ์ด๋ ต์ง ์์์! ใ ใ ใ
1. ์์กด์ฑ ์ถ๊ฐํ๊ธฐ ๐ฆ
๋จผ์ , ํ๋ก์ ํธ์ Logback ์์กด์ฑ์ ์ถ๊ฐํด์ผ ํด์. Maven์ ์ฌ์ฉํ๋ค๋ฉด pom.xml์ ๋ค์์ ์ถ๊ฐํ์ธ์:
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.6</version>
</dependency>
</dependencies>
Gradle์ ์ฌ์ฉํ๋ค๋ฉด build.gradle์ ์ด๋ ๊ฒ ์ถ๊ฐํ์ธ์:
dependencies {
implementation 'ch.qos.logback:logback-classic:1.2.6'
}
2. logback.xml ๋ง๋ค๊ธฐ ๐
์ด์ src/main/resources ๋๋ ํ ๋ฆฌ์ logback.xml ํ์ผ์ ๋ง๋ค์ด์. ์ด ํ์ผ์ด Logback์ ์ค์ ํ์ผ์ด ๋ ๊ฑฐ์์.
<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>
์ด ์ค์ ์ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ๊ฒ์ด์์. ์ฝ์์ ๋ก๊ทธ๋ฅผ ์ถ๋ ฅํ๋๋ก ์ค์ ํ์ฃ .
3. ์ฝ๋์์ ์ฌ์ฉํ๊ธฐ ๐ป
์ด์ Java ์ฝ๋์์ Logback์ ์ฌ์ฉํ ์ ์์ด์!
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyApp {
private static final Logger logger = LoggerFactory.getLogger(MyApp.class);
public static void main(String[] args) {
logger.info("์๋
ํ์ธ์, Logback!");
logger.warn("์ด๊ฑด ๊ฒฝ๊ณ ๋ฉ์์ง์์.");
logger.error("์๋ฌ๊ฐ ๋ฐ์ํ์ด์!");
}
}
์ด๋ ๊ฒ ํ๋ฉด ์ฝ์์ ์๋์ ๊ฐ์ด ์ถ๋ ฅ๋ ๊ฑฐ์์:
10:15:30.123 [main] INFO com.example.MyApp - ์๋
ํ์ธ์, Logback!
10:15:30.125 [main] WARN com.example.MyApp - ์ด๊ฑด ๊ฒฝ๊ณ ๋ฉ์์ง์์.
10:15:30.126 [main] ERROR com.example.MyApp - ์๋ฌ๊ฐ ๋ฐ์ํ์ด์!
๐ ์ถํํด์! ์ฌ๋ฌ๋ถ์ ๋ฐฉ๊ธ Logback์ ์ค์ ํ๊ณ ์ฌ์ฉํ๋ ๋ฐ ์ฑ๊ณตํ์ด์! ์ด์ ๋ก๊น ์ ์ธ๊ณ์ ์ฒซ ๋ฐ์ ๋ด๋์ ๊ฑฐ์์. ๐๐๐
์ด๋์? ์๊ฐ๋ณด๋ค ์ฝ์ฃ ? ใ ใ ใ ์ด์ Logback์ ๊ธฐ๋ณธ์ ๋ง์คํฐํ์ด์. ํ์ง๋ง ์ด๊ฒ ๋์ด ์๋์์. Logback์ ํจ์ฌ ๋ ๋ง์ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ต๋๋ค. ๋ค์ ์น์ ์์๋ ์ข ๋ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ ์ดํด๋ณผ ๊ฑฐ์์. ์ค๋น๋์ จ๋์? ๊ณ ๊ณ ์ฝ! ๐
๐ฅ Logback ๊ณ ๊ธ ๊ธฐ๋ฅ: ์ด์ ํ๋ก๊ฐ ๋์ด๋ณผ๊น์? ๐ฅ
์, ์ด์ Logback์ ๊ธฐ๋ณธ์ ๋ง์คํฐํ์ผ๋ ์ข ๋ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ ์์๋ณผ ์ฐจ๋ก์์. ์ด ๊ธฐ๋ฅ๋ค์ ์๋ฉด ์ฌ๋ฌ๋ถ์ ์ง์ ํ Logback ํ๋ก๊ฐ ๋ ์ ์์ด์! ๐
1. ๋ก๊ทธ ๋ ๋ฒจ ์ค์ ํ๊ธฐ ๐
Logback์ ๋ค์ํ ๋ก๊ทธ ๋ ๋ฒจ์ ์ ๊ณตํด์. ๊ฐ์ฅ ๋ฎ์ ๋ ๋ฒจ๋ถํฐ ๋์ ๋ ๋ฒจ ์์ผ๋ก ๋์ดํ๋ฉด ์ด๋ ๋ต๋๋ค:
- TRACE
- DEBUG
- INFO
- WARN
- ERROR
logback.xml์์ ์ด๋ ๊ฒ ์ค์ ํ ์ ์์ด์:
<root level="INFO">
<appender-ref ref="CONSOLE" />
</root>
<logger name="com.example.myapp" level="DEBUG" />
์ด๋ ๊ฒ ํ๋ฉด ์ ์ฒด์ ์ผ๋ก๋ INFO ๋ ๋ฒจ ์ด์์ ๋ก๊ทธ๋ง ์ถ๋ ฅํ์ง๋ง, com.example.myapp ํจํค์ง์์๋ DEBUG ๋ ๋ฒจ ์ด์์ ๋ก๊ทธ๋ฅผ ์ถ๋ ฅํ๊ฒ ๋ผ์.
2. ํ์ผ์ ๋ก๊ทธ ์ ์ฅํ๊ธฐ ๐พ
์ฝ์์ ๋ก๊ทธ๋ฅผ ์ถ๋ ฅํ๋ ๊ฒ๋ ์ข์ง๋ง, ํ์ผ์ ์ ์ฅํ๋ฉด ๋์ค์ ๋ถ์ํ๊ธฐ ์ข๊ฒ ์ฃ ? RollingFileAppender๋ฅผ ์ฌ์ฉํ๋ฉด ํ์ผ ํฌ๊ธฐ๋ ๋ ์ง์ ๋ฐ๋ผ ๋ก๊ทธ ํ์ผ์ ์๋์ผ๋ก ๊ด๋ฆฌํ ์ ์์ด์.
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/myapp.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/myapp.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="FILE" />
</root>
์ด๋ ๊ฒ ํ๋ฉด ๋งค์ผ ์๋ก์ด ๋ก๊ทธ ํ์ผ์ด ์์ฑ๋๊ณ , 30์ผ์น์ ๋ก๊ทธ๋ง ๋ณด๊ดํ๊ฒ ๋ผ์.
3. ์กฐ๊ฑด๋ถ ์ฒ๋ฆฌ ๐
Logback์ ์กฐ๊ฑด๋ถ ์ฒ๋ฆฌ๋ ์ง์ํด์. ํน์ ์กฐ๊ฑด์ ๋ฐ๋ผ ๋ค๋ฅธ ์ค์ ์ ์ ์ฉํ ์ ์์ฃ .
<if condition='property("ENV").equals("PRODUCTION")'>
<then>
<root level="WARN">
<appender-ref ref="FILE" />
</root>
</then>
<else>
<root level="DEBUG">
<appender-ref ref="CONSOLE" />
</root>
</else>
</if>
์ด๋ ๊ฒ ํ๋ฉด ์ด์ ํ๊ฒฝ์์๋ WARN ๋ ๋ฒจ ์ด์์ ๋ก๊ทธ๋ฅผ ํ์ผ์ ์ ์ฅํ๊ณ , ๊ทธ ์ธ์ ํ๊ฒฝ์์๋ DEBUG ๋ ๋ฒจ ์ด์์ ๋ก๊ทธ๋ฅผ ์ฝ์์ ์ถ๋ ฅํ๊ฒ ๋ผ์.
4. MDC (Mapped Diagnostic Context) ์ฌ์ฉํ๊ธฐ ๐บ๏ธ
MDC๋ฅผ ์ฌ์ฉํ๋ฉด ๋ก๊ทธ์ ์ถ๊ฐ์ ์ธ ์ปจํ ์คํธ ์ ๋ณด๋ฅผ ํฌํจ์ํฌ ์ ์์ด์. ์๋ฅผ ๋ค์ด, ์ฌ์ฉ์ ID๋ ์ธ์ ID ๊ฐ์ ์ ๋ณด๋ฅผ ๋ชจ๋ ๋ก๊ทธ์ ์๋์ผ๋ก ํฌํจ์ํฌ ์ ์์ฃ .
import org.slf4j.MDC;
// ์ฝ๋ ์ด๋๊ฐ์์
MDC.put("userId", "12345");
// ๋ก๊ทธ ํจํด์ MDC ์ ๋ณด ์ถ๊ฐ
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %X{userId} - %msg%n</pattern>
์ด๋ ๊ฒ ํ๋ฉด ๋ชจ๋ ๋ก๊ทธ ๋ฉ์์ง์ ์ฌ์ฉ์ ID๊ฐ ํฌํจ๋ผ์.
5. ๋น๋๊ธฐ ๋ก๊น โก
๋ก๊น ์ด ์ ํ๋ฆฌ์ผ์ด์ ์ฑ๋ฅ์ ์ํฅ์ ๋ฏธ์น๋ ๊ฑธ ๊ฑฑ์ ํ์๋์? ๋น๋๊ธฐ ๋ก๊น ์ ์ฌ์ฉํ๋ฉด ๊ทธ ์ํฅ์ ์ต์ํํ ์ ์์ด์!
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="FILE" />
</appender>
<root level="INFO">
<appender-ref ref="ASYNC" />
</root>
์ด๋ ๊ฒ ํ๋ฉด ๋ก๊ทธ ์์ฑ์ด ๋ณ๋์ ์ค๋ ๋์์ ๋น๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌ๋ผ์. ๋ฉ์ธ ์ค๋ ๋์ ์คํ ์๋์ ์ํฅ์ ๋ ๋ฏธ์น๊ฒ ์ฃ ?
๐ ํ๋ก ํ: ๋ก๊น ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅ์ ์ํฅ์ ์ค ์ ์์ด์. ์ด์ ํ๊ฒฝ์์๋ DEBUG ๋ ๋ฒจ์ ๋ก๊ทธ๋ฅผ ์ต์ํํ๊ณ , ๋น๋๊ธฐ ๋ก๊น ์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์์. ๊ทธ๋ฆฌ๊ณ ์ฃผ๊ธฐ์ ์ผ๋ก ๋ก๊ทธ๋ฅผ ๋ถ์ํด์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฑด๊ฐ ์ํ๋ฅผ ์ฒดํฌํ์ธ์!
์์ฐ! ์ด์ ์ฌ๋ฌ๋ถ์ Logback์ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค๋ ๋ง์คํฐํ์ด์. ์ด ์ ๋๋ฉด Logback ํ๋ก๋ผ๊ณ ํ ์ ์๊ฒ ์ฃ ? ใ ใ ใ ๐จโ๐๐ฉโ๐
ํ์ง๋ง ์์ง ๋์ด ์๋์์! Logback์๋ ๋ ๋ง์ ๊ธฐ๋ฅ๋ค์ด ์๋ต๋๋ค. ๋ค์ ์น์ ์์๋ Logback์ ์ค์ ํ๋ก์ ํธ์์ ์ด๋ป๊ฒ ํ์ฉํ ์ ์๋์ง, ๊ทธ๋ฆฌ๊ณ ๋ช ๊ฐ์ง ์ค์ฉ์ ์ธ ํ๋ค์ ์์๋ณผ ๊ฑฐ์์. ์ค๋น๋์ จ๋์? ๊ณ ๊ณ ์ฝ! ๐
๐ ๏ธ Logback ์ค์ ํ์ฉ: ์ด์ ์ง์ง ํ๋ก์ฒ๋ผ ์จ๋ณผ๊น์? ๐ ๏ธ
์, ์ด์ Logback์ ๊ธฐ๋ณธ๋ถํฐ ๊ณ ๊ธ ๊ธฐ๋ฅ๊น์ง ๋ค ๋ฐฐ์ ์ด์. ๊ทผ๋ฐ ์ด๊ฑธ ์ค์ ํ๋ก์ ํธ์์ ์ด๋ป๊ฒ ํ์ฉํ๋ฉด ์ข์๊น์? ๊ฑฑ์ ๋ง์ธ์! ์ง๊ธ๋ถํฐ Logback์ ์ค์ ์์ ํ์ฉํ๋ ๋ฐฉ๋ฒ์ ์๋ ค๋๋ฆด๊ฒ์. ๐
1. ๋ก๊ทธ ๋ ๋ฒจ ์ ๋ต ์ธ์ฐ๊ธฐ ๐
๋ก๊ทธ ๋ ๋ฒจ์ ์ ์ ํ ์ฌ์ฉํ๋ ๊ฒ์ ์ ๋ง ์ค์ํด์. ๊ฐ ๋ ๋ฒจ์ ์ธ์ ์ฌ์ฉํด์ผ ํ ์ง ๊ฐ์ด๋๋ผ์ธ์ ์ ํด๋ณด์ธ์.
- ERROR: ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ ์ด์ ๊ธฐ๋ฅ์ ์ํํ์ง ๋ชปํ ๋
- WARN: ์ ์ฌ์ ์ธ ๋ฌธ์ ์ํฉ. ๋น์ฅ์ ๊ธฐ๋ฅ ์ํ์ ๋ฌธ์ ๊ฐ ์์ง๋ง ์ฃผ์๊ฐ ํ์ํ ๋
- INFO: ์ผ๋ฐ์ ์ธ ์๋ ์ ๋ณด. ์์คํ ์ํ ๋ณ๊ฒฝ์ด๋ ์ฃผ์ ๋น์ฆ๋์ค ํ๋ก์ธ์ค ์๋ฃ ๋ฑ
- DEBUG: ๊ฐ๋ฐ ์ ๋ฌธ์ ํด๊ฒฐ์ ๋์์ด ๋๋ ์์ธํ ์ ๋ณด
- TRACE: ๊ฐ์ฅ ์์ธํ ์ ๋ณด. ๊ฑฐ์ ๋ชจ๋ ๊ฒ์ ๋ก๊น
if (userNotFound) {
logger.warn("์ฌ์ฉ์๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค. userId: {}", userId);
} else if (serverError) {
logger.error("์๋ฒ ์๋ฌ ๋ฐ์. ์์ธ ์ ๋ณด: {}", errorDetails);
} else {
logger.info("์ฌ์ฉ์ ๋ก๊ทธ์ธ ์ฑ๊ณต. userId: {}", userId);
}
2. ๋ก๊ทธ ํฌ๋งท ์ต์ ํํ๊ธฐ ๐จ
๋ก๊ทธ ํฌ๋งท์ ์ ์ค์ ํ๋ฉด ๋์ค์ ๋ก๊ทธ ๋ถ์ํ ๋ ์ ๋ง ํธํด์. ํ์ํ ์ ๋ณด๋ฅผ ๋ชจ๋ ํฌํจ์ํค๋, ๋๋ฌด ๋ณต์กํ์ง ์๊ฒ ๋ง๋์ธ์.
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %X{userId} - %msg%n</pattern>
์ด ํจํด์ ๋ค์ ์ ๋ณด๋ฅผ ํฌํจํด์:
- ๋ ์ง์ ์๊ฐ (๋ฐ๋ฆฌ์ด๊น์ง)
- ์ค๋ ๋ ์ด๋ฆ
- ๋ก๊ทธ ๋ ๋ฒจ
- ๋ก๊ฑฐ ์ด๋ฆ (์ต๋ 36์)
- MDC์์ userId
- ์ค์ ๋ก๊ทธ ๋ฉ์์ง
3. ์์ธ ์ฒ๋ฆฌ์ ๋ก๊น ๐จ
์์ธ๊ฐ ๋ฐ์ํ์ ๋ ๋ก๊ทธ๋ฅผ ๋จ๊ธฐ๋ ๊ฒ์ ์ ๋ง ์ค์ํด์. ๋จ, ์คํ ํธ๋ ์ด์ค๋ฅผ ๊ทธ๋๋ก ์ถ๋ ฅํ๋ ๊ฒ๋ณด๋ค๋ ํ์ํ ์ ๋ณด๋ง ์ถ์ถํด์ ๋ก๊น ํ๋ ๊ฒ ์ข์์.
try {
// ๋ญ๊ฐ ์ํํ ์์
} catch (Exception e) {
logger.error("์์
์ฒ๋ฆฌ ์ค ์๋ฌ ๋ฐ์. ๋ฉ์์ง: {}, ์์ธ: {}", e.getMessage(), e.getCause());
}
4. ์ฑ๋ฅ ๋ชจ๋ํฐ๋ง์ ํ์ฉํ๊ธฐ ๐
Logback์ ์ฌ์ฉํด ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅ์ ๋ชจ๋ํฐ๋งํ ์ ์์ด์. ์ฃผ์ ์์ ์ ์คํ ์๊ฐ์ ๋ก๊น ํด๋ณด์ธ์.
long start = System.currentTimeMillis();
// ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๋ ์์
long end = System.currentTimeMillis();
logger.info("์์
์๋ฃ. ์์ ์๊ฐ: {}ms", (end - start));
5. ๋ก๊ทธ ํ์ผ ๊ด๋ฆฌ ์ ๋ต ๐พ
๋ก๊ทธ ํ์ผ์ด ๋๋ฌด ์ปค์ง๋ฉด ๊ด๋ฆฌํ๊ธฐ ํ๋ค์ด์ ธ์. RollingFileAppender๋ฅผ ์ฌ์ฉํด ๋ก๊ทธ ํ์ผ์ ๊ด๋ฆฌํ์ธ์.
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/myapp.log</file>
< rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>logs/archived/myapp.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<maxFileSize>10MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
์ด ์ค์ ์ ๋ค์๊ณผ ๊ฐ์ ํจ๊ณผ๊ฐ ์์ด์:
- ๋ก๊ทธ ํ์ผ์ด 10MB๋ฅผ ๋์ด๊ฐ๋ฉด ์ ํ์ผ์ ์์ฑํด์.
- ๋งค์ผ ์๋ก์ด ๋ก๊ทธ ํ์ผ์ ๋ง๋ค์ด์.
- 30์ผ์น์ ๋ก๊ทธ๋ง ๋ณด๊ดํด์.
- ์ ์ฒด ๋ก๊ทธ ํ์ผ์ ํฌ๊ธฐ๊ฐ 1GB๋ฅผ ๋์ง ์๋๋ก ํด์.
- ์ค๋๋ ๋ก๊ทธ ํ์ผ์ gzip์ผ๋ก ์์ถํด์.
6. ๋ฏผ๊ฐํ ์ ๋ณด ๋ณดํธํ๊ธฐ ๐
๋ก๊ทธ์ ๋ฏผ๊ฐํ ์ ๋ณด๊ฐ ๋ ธ์ถ๋์ง ์๋๋ก ์ฃผ์ํด์ผ ํด์. ํจ์ค์๋๋ ๊ฐ์ธ์ ๋ณด๋ ๋ง์คํน ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ์ธ์.
public class MaskingPatternLayout extends PatternLayout {
private Pattern multilinePattern;
private List<String> maskPatterns = new ArrayList<>();
public void addMaskPattern(String maskPattern) {
maskPatterns.add(maskPattern);
multilinePattern = Pattern.compile(String.join("|", maskPatterns), Pattern.MULTILINE);
}
@Override
public String doLayout(ILoggingEvent event) {
String message = super.doLayout(event);
if (multilinePattern != null) {
Matcher matcher = multilinePattern.matcher(message);
if (matcher.find()) {
return matcher.replaceAll("****");
}
}
return message;
}
}
์ด๋ ๊ฒ ๋ง๋ MaskingPatternLayout์ logback.xml์์ ์ฌ์ฉํ๋ฉด ๋ผ์:
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<layout class="com.example.MaskingPatternLayout">
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</layout>
<maskPattern>(\w+@\w+\.\w+)</maskPattern> <!-- ์ด๋ฉ์ผ ์ฃผ์ ๋ง์คํน -->
<maskPattern>(\d{4}-\d{4}-\d{4}-\d{4})</maskPattern> <!-- ์นด๋๋ฒํธ ๋ง์คํน -->
</appender>
7. ๋ก๊ทธ ๋ถ์ ๋๊ตฌ ํ์ฉํ๊ธฐ ๐
๋ก๊ทธ๋ฅผ ์ ๋จ๊ธฐ๋ ๊ฒ๋ ์ค์ํ์ง๋ง, ๊ทธ ๋ก๊ทธ๋ฅผ ์ ๋ถ์ํ๋ ๊ฒ๋ ์ค์ํด์. ELK ์คํ(Elasticsearch, Logstash, Kibana)์ด๋ Splunk ๊ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํด๋ณด์ธ์.
๐ก ํ๋ก ํ: JSON ํ์์ผ๋ก ๋ก๊ทธ๋ฅผ ๋จ๊ธฐ๋ฉด ๋ก๊ทธ ๋ถ์ ๋๊ตฌ์์ ๋ ์ฝ๊ฒ ํ์ฑํ๊ณ ๋ถ์ํ ์ ์์ด์. Logback JSON encoder๋ฅผ ์ฌ์ฉํด๋ณด์ธ์!
8. ํ ์คํธ ์ฝ๋์์ ๋ก๊น ํ์ฉํ๊ธฐ ๐งช
ํ ์คํธ ์ฝ๋์์๋ ๋ก๊น ์ ํ์ฉํ๋ฉด ํ ์คํธ ์คํจ ์์ธ์ ๋ ์ฝ๊ฒ ํ์ ํ ์ ์์ด์.
@Test
public void testSomething() {
logger.info("ํ
์คํธ ์์: testSomething");
// ํ
์คํธ ์ฝ๋
logger.info("ํ
์คํธ ์ข
๋ฃ: testSomething");
}
9. ๋ก๊ทธ ๋ ๋ฒจ ๋์ ๋ณ๊ฒฝ ๐
JMX๋ฅผ ์ฌ์ฉํ๋ฉด ์ ํ๋ฆฌ์ผ์ด์ ์คํ ์ค์๋ ๋ก๊ทธ ๋ ๋ฒจ์ ๋์ ์ผ๋ก ๋ณ๊ฒฝํ ์ ์์ด์. ๋ฌธ์ ์ํฉ์์ ๋ก๊ทธ ๋ ๋ฒจ์ ์ผ์์ ์ผ๋ก ๋ ๋ฎ์ถ ์ ์์ฃ .
<configuration>
<jmxConfigurator />
// ๋ค๋ฅธ ์ค์ ๋ค...
</configuration>
10. ๋ก๊ทธ ๊ฐ์ด๋๋ผ์ธ ๋ง๋ค๊ธฐ ๐
ํ ์ ์ฒด๊ฐ ์ผ๊ด๋ ๋ฐฉ์์ผ๋ก ๋ก๊น ์ ํ๋๋ก ๊ฐ์ด๋๋ผ์ธ์ ๋ง๋ค์ด๋ณด์ธ์. ์ด๋ค ์ํฉ์์ ์ด๋ค ๋ ๋ฒจ์ ๋ก๊ทธ๋ฅผ ๋จ๊ธธ์ง, ๋ก๊ทธ ๋ฉ์์ง๋ ์ด๋ค ํ์์ผ๋ก ์์ฑํ ์ง ๋ฑ์ ์ ํด๋๋ฉด ์ข์์.
๐ ๋ง์ง๋ง ์กฐ์ธ: ๋ก๊น ์ ๊ฐ๋ฐ์ ํ์ ์์์์. ํ์ง๋ง ๊ณผ๋ํ ๋ก๊น ์ ์คํ๋ ค ์ฑ๋ฅ์ ์ ์ํฅ์ ์ค ์ ์์ด์. ํญ์ ๊ท ํ์ ์ก์ผ๋ ค๊ณ ๋ ธ๋ ฅํ์ธ์. ๊ทธ๋ฆฌ๊ณ ์ฃผ๊ธฐ์ ์ผ๋ก ๋ก๊ทธ๋ฅผ ๊ฒํ ํ๊ณ ๊ฐ์ ํ๋ ์ต๊ด์ ๋ค์ด์ธ์. ๋ก๊ทธ๋ ์ฌ๋ฌ๋ถ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ดํดํ๋ ๊ฐ์ฅ ์ข์ ๋๊ตฌ ์ค ํ๋๋๊น์!
์, ์ด์ ์ฌ๋ฌ๋ถ์ Logback์ ์ง์ ํ ๋ง์คํฐ๊ฐ ๋์์ด์! ๐๐๐ ์ด ์ง์์ ํ์ฉํด์ ๋ ๋์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง๋ค์ด๋ณด์ธ์. ๋ก๊น ์ ํ์ ๋ฏฟ์ผ์ธ์! ํ์ดํ ! ๐ช๐
๐ ๋ง๋ฌด๋ฆฌ: Logback, ์ด์ ์ฌ๋ฌ๋ถ์ ๋ ๋ ํ ํํธ๋! ๐
์์ฐ! ์ ๋ง ๊ธด ์ฌ์ ์ด์์ฃ ? Logback์ A๋ถํฐ Z๊น์ง, ์ฐ๋ฆฌ๋ ์ ๋ง ๋ง์ ๊ฒ์ ๋ฐฐ์ ์ด์. ์ด์ ์ฌ๋ฌ๋ถ์ Logback ์ ๋ฌธ๊ฐ๋ผ๊ณ ํด๋ ๊ณผ์ธ์ด ์๋ ๊ฑฐ์์. ๐จโ๐๐ฉโ๐
์ฐ๋ฆฌ๊ฐ ๋ฐฐ์ด ๋ด์ฉ์ ๊ฐ๋จํ ์ ๋ฆฌํด๋ณผ๊น์?
- Logback์ ๊ธฐ๋ณธ ๊ตฌ์กฐ์ ํต์ฌ ์ปดํฌ๋ํธ
- ๋ก๊ทธ ๋ ๋ฒจ๊ณผ ๊ทธ ํ์ฉ๋ฒ
- ๋ค์ํ Appender ์ค์ ๋ฐฉ๋ฒ
- ๋ก๊ทธ ํฌ๋งท ์ต์ ํ ์ ๋ต
- ํ์ผ ๋ก๊น ๊ณผ ๋ก๊ทธ ํ์ผ ๊ด๋ฆฌ
- ๋น๋๊ธฐ ๋ก๊น ์ผ๋ก ์ฑ๋ฅ ํฅ์์ํค๊ธฐ
- ๋ฏผ๊ฐํ ์ ๋ณด ๋ณดํธํ๊ธฐ
- ๋ก๊ทธ ๋ถ์ ๋๊ตฌ ํ์ฉํ๊ธฐ
- ํ ์คํธ ์ฝ๋์์์ ๋ก๊น
- ๋์ ๋ก๊ทธ ๋ ๋ฒจ ๋ณ๊ฒฝ
์ด ๋ชจ๋ ์ง์์ ๊ฐ์ง๊ณ ์ด์ ์ฌ๋ฌ๋ถ์ ์ด๋ค ์ํฉ์์๋ ์๋ฒฝํ ๋ก๊น ์ ๋ต์ ์ธ์ธ ์ ์์ ๊ฑฐ์์. ๋ก๊ทธ๋ ๋จ์ํ ์๋ฌ๋ฅผ ์ฐพ๋ ๋๊ตฌ๊ฐ ์๋๋ผ, ์ฌ๋ฌ๋ถ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ ๊น์ด ์ดํดํ๊ณ ๊ฐ์ ํ ์ ์๊ฒ ํด์ฃผ๋ ๊ฐ๋ ฅํ ๋๊ตฌ๋ผ๋ ๊ฑธ ์์ง ๋ง์ธ์.
๐ ๊ธฐ์ตํ์ธ์: ์ข์ ๋ก๊ทธ๋ ๊ฐ๋ฐ์์ ๊ฐ์ฅ ๋ ๋ ํ ํํธ๋์์. ๋ฌธ์ ๊ฐ ์๊ฒผ์ ๋ ์ฌ๋ฌ๋ถ์ ๊ตฌํด์ค ์์ ์ด ๋ ์๋ ์๊ณ , ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅ์ ๊ฐ์ ํ ์ ์๋ ์ธ์ฌ์ดํธ๋ฅผ ์ ๊ณตํ ์๋ ์์ด์. Logback์ ์ ํ์ฉํด์ ๋ ๋์ ๊ฐ๋ฐ์๊ฐ ๋์ด๋ณด์ธ์!
์, ์ด์ ์ฌ๋ฌ๋ถ์ Logback ๋ง์คํฐ์์. ์ด ์ง์์ ์ค์ ํ๋ก์ ํธ์ ์ ์ฉํด๋ณด์ธ์. ์ฒ์์๋ ์กฐ๊ธ ์ด์ํ ์ ์์ง๋ง, ์๊ฐ์ด ์ง๋ ์๋ก ๋ก๊น ์ ์ง์ ํ ๊ฐ์น๋ฅผ ๋๋ผ๊ฒ ๋ ๊ฑฐ์์.
๋ก๊น ์ ์ธ๊ณ์์ ์ฌ๋ฌ๋ถ์ ๋ชจํ์ ์ด์ ๋ง ์์๋์ด์. ๊ณ์ํด์ ํ์ตํ๊ณ , ๊ฒฝํ์ ์๊ณ , ๋ ๋์ ๋ก๊น ์ ๋ต์ ๋ง๋ค์ด๊ฐ์ธ์. ์ฌ๋ฌ๋ถ์ ์ฝ๋์ Logback์ ๋ง๋ฒ์ ๋ถ์ด๋ฃ์ด๋ณด์ธ์! ๐ฉโจ
๊ทธ๋ผ, ํดํผ ๋ก๊น ! ๋ค์์ ๋ ๋ง๋์~ ๐๐
- ์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์ฌ๋ฅ๋ท์ ์ต์ AI ๊ธฐ์ ๊ณผ ๋ฒ๋ฅ ์ ๊ธฐ๋ฐํ์ฌ ์์ฌ์ ์ง์ ์ฌ์ฐ๊ถ์ ์ ๊ทน์ ์ผ๋ก ๋ณดํธํ๋ฉฐ,
๋ฌด๋จ ์ฌ์ฉ ๋ฐ ์นจํด ํ์์ ๋ํด ๋ฒ์ ๋์์ ํ ๊ถ๋ฆฌ๋ฅผ ๋ณด์ ํฉ๋๋ค.
ยฉ 2025 ์ฌ๋ฅ๋ท | All rights reserved.
๋๊ธ 0๊ฐ