본문 바로가기

Dev Log

로그 관리와 디버깅을 빠르게 만드는 방법

728x90

프로젝트를 운영하다 보면, 결국 문제를 해결하는 출발점은 로그다.

이번 글에서는 현재 프로젝트에서 로그가 어떻게 생성·관리되고 있는지 정리하고,

오류 발생 시 디버깅 속도를 높이기 위해 어떤 방식과 도구를 쓰면 좋은지를 정리해봤다.


1. 현재 프로젝트의 로그 구조 정리

로그는 어디에 저장되고 있을까?

현재 프로젝트는 Logback을 사용하고 있고, 환경별로 설정 파일을 분리해서 관리하고 있다.

  • 로컬: logback-local.xml
  • 개발: logback-dev.xml
  • 스테이징: logback-stg.xml
  • 프로덕션: logback-prod.xml

모든 환경에서 로그 파일은 공통적으로 아래 위치에 생성된다.

${user.home}/logs/main-api.log

환경별 실제 경로는 다음과 같다.

  • Mac / Linux
  • ~/logs/main-api.log
  • Windows
  • C:\\Users\\사용자명\\logs\\main-api.log
  • 서버
  • 서버 계정의 홈 디렉토리 하위 logs/main-api.log

로그 파일은 언제 생성될까?

  • 애플리케이션이 시작되고 첫 로그가 기록되는 시점에 자동 생성
  • 별도의 에러 조건 없이, INFO 레벨 이상의 로그가 찍히면 파일 생성

로그 파일 구성

현재 로그는 목적에 따라 두 가지로 나뉜다.

  • 메인 로그 (main-api.log)
    • 애플리케이션 전반 로그 (INFO / WARN / ERROR)
    • Root 레벨: INFO
    • 일부 핵심 패키지는 DEBUG 레벨로 설정
  • 요청 로그 (main-api.request.log)
    • dev / stg / prod 환경에서만 사용
    • HTTP 요청 관련 로그만 별도로 기록
    • ApplicationLogRequest 키워드 기준으로 필터링

로그 롤링 정책

  • 날짜 기준 롤링
  • main-api.2024-01-01.log
  • 보관 기간: 30일
  • 파일 크기 기준 분할: 100MB
  • 전체 로그 용량 제한: 10GB

성능을 위한 비동기 로깅

  • AsyncAppender 사용
  • 큐 사이즈: 8192
  • 요청 처리 성능에 로그가 영향을 주지 않도록 설계

로그 패턴

yyyy-MM-ddHH:mm:ss.SSS [thread]LEVEL logger - message

이 패턴 덕분에 언제 / 어떤 스레드에서 / 어떤 클래스가 / 무슨 로그를 남겼는지를 한 줄에서 바로 파악할 수 있다.


2. 환경별 로그 관리 전략

로그는 “많이 남기는 것”보다 환경에 맞게 남기는 것이 더 중요하다.

로컬 환경

  • 목적: 개발 중 빠른 디버깅
  • 특징
    • 콘솔 출력 + 파일 저장
    • DEBUG 레벨까지 상세 로그
  • 권장
    • 로그 양은 신경 쓰지 말고 최대한 자세히
    • 파일 보관 기간은 짧게 가져가도 무방

개발 환경

  • 목적: 개발 서버 이슈 추적
  • 특징
    • 요청 로그 파일 분리
    • 외부 라이브러리는 ERROR 위주
  • 권장
    • 애플리케이션 로그는 DEBUG 유지
    • 장애 재현 가능한 수준까지 정보 남기기

스테이징 환경

  • 목적: 운영 전 최종 검증
  • 특징
    • 프로덕션과 거의 동일한 설정
  • 권장
    • 로그 레벨을 INFO로 맞춰 실제 운영 상황 테스트
    • 모니터링 도구 연동 확인

프로덕션 환경

  • 목적: 안정성과 성능
  • 특징
    • Root 레벨 INFO
    • 비동기 로깅
    • 요청 로그 분리
  • 권장
    • DEBUG는 정말 필요한 로직에만 제한적으로 사용
    • 로그 모니터링 시스템과 반드시 연동

환경별 로그 레벨 요약

Local →DEBUG
Dev   →DEBUG
Stg   →INFO
Prod  →INFO

3. 오류를 빠르게 찾는 로그 작성 방식

로그를 “찍는다”와 “쓸 수 있게 찍는다”는 완전히 다르다.

로그 메시지는 반드시 맥락을 포함해야 한다

❌ 의미 없는 로그

log.error("Error occurred");

✅ 맥락이 있는 로그

log.error("User not found - memberSeq: {}, checkupDt: {}", memberSeq, checkupDt);

Exception 로깅은 반드시 스택 트레이스 포함

현재 프로젝트에서도 잘 쓰고 있는 패턴이다.

log.error("baseHandler.exception", exception);

메시지만 남기지 말고, 예외 객체 자체를 전달해야 나중에 원인 추적이 가능하다.

로그 레벨 사용 기준

  • DEBUG
  • → 흐름 추적, 내부 상태 확인
  • INFO
  • → 주요 비즈니스 이벤트
  • WARN
  • → 이상하지만 처리는 가능한 상황
  • ERROR
  • → 실패, 중단, 재시도 필요

요청 단위 추적을 위한 식별자

MDC를 활용하면 요청 단위로 로그를 묶어볼 수 있다.

MDC.put("requestId", UUID.randomUUID().toString());
MDC.put("memberSeq", String.valueOf(memberSeq));

로그 패턴에 추가해두면,

**“이 에러가 어떤 요청에서 발생했는지”**를 한 번에 추적할 수 있다.

로그 메시지 포맷 통일

[액션] [대상] [결과] - 상세정보

예:

[RETRIEVE] [CHECKUP_RESULT] [FAILED] - memberSeq: {}, error: {}

팀 단위로 합의만 되어 있으면, 나중에 검색·분석 속도가 확연히 빨라진다.


4. 로그를 분석하는 도구들

아래는 로그를 분석할 때 많이 사용되는 커맨드 및 도구들이라고 하는데, 다음주에는 실제 사용해서 후기를 적어보려고 한다.

기본적으로 많이 쓰는 커맨드

  • 실시간 확인
  • tail -f main-api.log
  • ERROR 필터링
  • grep ERROR main-api.log
  • 특정 사용자 추적
  • grep "memberSeq: 12345" main-api.log

IDE 활용

  • VS Code / IntelliJ
    • 정규식 검색
    • 로그 레벨별 하이라이팅
    • 대용량 로그도 비교적 편하게 확인 가능

로그 중앙화 도구

  • ELK Stack
  • 대규모 서비스, 검색·시각화 강점
  • Grafana Loki
  • 가볍고 쿠버네티스 친화적
  • CloudWatch / Datadog
  • 클라우드 환경에서 빠른 도입 가능
728x90