고품질 로그 출력을 위한 10가지 원칙

로그 출력의 중요성

시스템 장애 발생 시 로그는 문제 진단의 핵심 수단입니다. 효과적인 로깅은 장애 분석 시간을 크게 단축시킵니다.

1. 통일된 형식 사용

잘못된 예시:

logger.info("process start");
logger.error("error occurred");

타임스탬프와 컨텍스트 정보가 누락되었습니다.

올바른 설정:

<!-- logback.xml 구성 -->
<pattern>
    %d{yyyy-MM-dd HH:mm:ss.SSS}
    |%X{requestId:-NO_ID}
    |%thread
    |%-5level
    |%logger{40}
    |%msg%n
</pattern>

표준화된 로그 형식은 문제 추적을 용이하게 합니다.

2. 예외 스택 트레이스 포함

피해야 할 방식:

try {
    executeOrder();
} catch (Exception ex) {
    logger.error("처리 실패");
}

예외 정보가 누락되어 디버깅이 어렵습니다.

권장 방식:

logger.error("주문 처리 오류 orderCode={}", orderCode, ex);

3. 적절한 로그 레벨 설정

레벨사용 시나리오
FATAL시스템 중단 임박 (메모리 부족, 디스크 풀)
ERROR핵심 비즈니스 실패 (결제 실패, 주문 생성 오류)
WARN복구 가능 예외 (재시도 성공, fallback 실행)
INFO주요 프로세스 지점 (주문 상태 변경)
DEBUG디버깅 정보 (파라미터 흐름, 중간 결과)

4. 완전한 파라미터 기록

불완전한 로깅:

logger.info("사용자 로그인 실패");

상세 정보 포함:

logger.warn("사용자 로그인 실패 userId={}, clientIP={}, reason={}", 
    userId, clientIP, "비밀번호 오류 횟수 초과");

5. 데이터 마스킹 적용

// 마스킹 유틸리티
public class DataMasker {
    public static String maskPhoneNumber(String phone) {
        return phone.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
    }
}

// 사용 예시
logger.info("사용자 등록 phone={}", DataMasker.maskPhoneNumber("01012345678"));

6. 비동기 로깅으로 성능 보장

동기 로깅 문제:

logger.info("요청 수신 userId={}, productId={}", userId, productId);

고부하 시 I/O 블로킹 발생

비동기 설정:

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

7. 분산 추적 구현

// 추적 ID 주입
MDC.put("traceId", UUID.randomUUID().toString().substring(0, 12));

// 로그 패턴에 traceId 포함
<pattern>%d{HH:mm:ss} |%X{traceId}| %msg%n</pattern>

8. 동적 로그 레벨 조정

@RestController
public class LogController {
    
    @PostMapping("/log/level")
    public String adjustLogLevel(
        @RequestParam String targetLogger,
        @RequestParam String newLevel) {
        
        Logger logger = (Logger) LoggerFactory.getLogger(targetLogger);
        logger.setLevel(Level.toLevel(newLevel));
        return "로그 레벨 변경 완료";
    }
}

9. 구조화된 저장 형식

비구조화된 로그:

사용자가 갤럭시 폰 구매 주문번호2001 금액1200000

JSON 형식 로그:

{
  "eventType": "PURCHASE_COMPLETE",
  "orderNumber": "2001",
  "paymentAmount": 1200000,
  "items": [{"name":"Galaxy Phone", "productCode": "G123"}]
}

10. 지능형 모니터링 구축

ELK 스택을 활용한 로그 모니터링 시스템 구성

알림 규칙 예시:

  • 5분간 ERROR 로그 100건 이상 → 즉시 알림
  • 1시간 동안 WARN 로그 지속 → 이메일 통보

태그: 로깅 java Logback ELK 모니터링

10월 8일 18:05에 게시됨