본문 바로가기
개발&프로그래밍

[Spring Boot] 로깅 설정 가이드

by 재아군 2024. 12. 4.

[Spring Boot] 로깅 설정 가이드

기본 로깅 설정

로그 레벨 설정

# application.yml
logging:
  level:
    root: INFO
    com.example.myapp: DEBUG
    org.springframework.web: WARN
    org.hibernate: ERROR

로그 출력 형식 설정

logging:
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
    file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"

파일 로깅 설정

기본 파일 로깅

logging:
  file:
    name: logs/application.log
    max-size: 10MB
    max-history: 30

Rolling File 설정

<!-- logback-spring.xml -->
<configuration>
    <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/application.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logs/application-%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>30</maxHistory>
            <totalSizeCap>3GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%-5level] %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

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

Slf4j와 Lombok 활용

Lombok @Slf4j 사용

@Slf4j
@RestController
public class UserController {

    @GetMapping("/users")
    public List<User> getUsers() {
        log.debug("사용자 목록 조회 시작");
        // 비즈니스 로직
        log.info("사용자 목록 조회 완료");
        return users;
    }

    @PostMapping("/users")
    public User createUser(@RequestBody User user) {
        log.info("사용자 생성 요청: {}", user);
        try {
            // 사용자 생성 로직
            log.debug("사용자 생성 완료: {}", user);
            return user;
        } catch (Exception e) {
            log.error("사용자 생성 실패: {}", e.getMessage(), e);
            throw e;
        }
    }
}

Profile별 로깅 설정

개발 환경 (application-dev.yml)

logging:
  level:
    root: DEBUG
    org.springframework: DEBUG
  pattern:
    console: "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"

운영 환경 (application-prod.yml)

logging:
  level:
    root: WARN
    com.example.myapp: INFO
  file:
    name: /var/log/myapp/application.log
  pattern:
    file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"

MDC (Mapped Diagnostic Context) 활용

MDC 설정

@Component
public class MDCFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, 
                                  HttpServletResponse response,
                                  FilterChain chain) throws IOException, ServletException {
        try {
            MDC.put("requestId", UUID.randomUUID().toString());
            MDC.put("userIp", request.getRemoteAddr());
            chain.doFilter(request, response);
        } finally {
            MDC.clear();
        }
    }
}

MDC 로그 패턴 설정

logging:
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] [%X{requestId}] %-5level %logger{36} - %msg%n"

로그 분석을 위한 추가 설정

JSON 형식 로깅

<dependency>
    <groupId>net.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
    <version>7.2</version>
</dependency>
<!-- logback-spring.xml -->
<appender name="JSON_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>logs/application.json</file>
    <encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
</appender>

실전 로깅 예제

@Service
public class OrderService {

    @Transactional
    public Order createOrder(OrderRequest request) {
        MDC.put("orderId", request.getOrderId());
        log.info("주문 생성 시작: {}", request);

        try {
            validateOrder(request);
            log.debug("주문 유효성 검사 완료");

            Order order = orderRepository.save(new Order(request));
            log.info("주문 저장 완료: {}", order.getId());

            return order;
        } catch (Exception e) {
            log.error("주문 생성 실패: {}", e.getMessage(), e);
            throw new OrderException("주문 처리 중 오류 발생", e);
        } finally {
            MDC.remove("orderId");
        }
    }
}

로깅 모범 사례

  1. 적절한 로그 레벨 사용
    • ERROR: 시스템 동작이 불가능한 경우
    • WARN: 시스템은 동작하지만 주의가 필요한 경우
    • INFO: 일반적인 정보
    • DEBUG: 개발 시 상세 정보
    • TRACE: 가장 상세한 정보
  2. 예외 처리 시 로깅
try {
    // 비즈니스 로직
} catch (Exception e) {
    log.error("에러 발생: {}", e.getMessage(), e);
    throw new CustomException("처리 중 오류 발생", e);
}
  1. 성능 고려사항
// 좋은 예
if (log.isDebugEnabled()) {
    log.debug("복잡한 계산 결과: {}", calculateExpensiveValue());
}

댓글