본문 바로가기
language/java

Java 예외 로그 전략 완벽 이해하기

by 죄니안죄니 2026. 5. 29.
반응형

Java 예외 로그 전략 완벽 이해하기

실무에서 장애가 발생했을 때 가장 먼저 보는 것은 무엇일까요?

정답은:

로그(Log)
 

입니다.

아무리 예외 처리를 잘 해도 로그가 잘못 남아 있으면:

  • 원인 분석 불가
  • 장애 복구 지연
  • 운영 비용 증가

문제가 발생합니다.

실제로 실무에서는:

예외 처리보다
예외 로그를 어떻게 남길 것인가가
더 중요할 때가 많다.
 

1. 가장 흔한 실수

초보자가 가장 많이 하는 코드

 
try {

    ...

} catch(Exception e) {

    e.printStackTrace();
}
 

2. 왜 문제일까?

운영 서버에서는 안 보임

대부분 서버는

stdout
stderr
 

를 직접 보지 않습니다.


로그 검색 불가

 
e.printStackTrace();
 

는 로그 시스템과 연동 안 됨.


로그 포맷 통일 안 됨

운영 환경에서는:

  • Elasticsearch
  • Kibana
  • Datadog
  • Grafana

등에서 검색해야 함.


3. 실무 표준

보통:

SLF4J

Logback

조합 사용.


4. 기본 형태

 
private static final Logger log =
    LoggerFactory.getLogger(
        UserService.class
    );
 

5. 예외 발생 시

 
catch(Exception e) {

    log.error("회원 조회 실패", e);
}
 

6. 왜 e를 따로 넘길까?

좋은 코드

 
log.error("회원 조회 실패", e);
 

나쁜 코드

 
log.error(
    "회원 조회 실패 : " +
    e.getMessage()
);
 

7. 차이점

좋은 코드:

메시지
+
전체 StackTrace
 

출력.


나쁜 코드:

메시지만 출력
 

됨.


8. StackTrace가 중요한 이유

예:

NullPointerException
 

만 봐서는 부족.


실제로 필요한 정보

어디서 발생했는가?
어떤 경로로 호출됐는가?
 

UserService.java:52
 

이 정보가 핵심.


9. 로그 레벨 이해

매우 중요.


TRACE

매우 상세
 

DEBUG

개발용
 

INFO

정상 흐름
 

WARN

문제 가능성 있음
 

ERROR

실패 발생
 

10. 예외는 무조건 ERROR?

의외로 아님.


 
if(user == null) {

    throw new UserNotFoundException();
}
 

이건 비즈니스적으로 정상 가능 상황.


실무에서는

 
log.warn(...)
 

정도 사용하는 경우도 많음.


11. 로그 중복 문제

실무에서 매우 중요.


안 좋은 코드

 
try {

} catch(Exception e) {

    log.error("Service 실패", e);

    throw e;
}
 

Controller

 
catch(Exception e) {

    log.error("Controller 실패", e);

    throw e;
}
 

GlobalExceptionHandler

 
log.error("최종 실패", e);
 

12. 결과

같은 예외가

3번 출력
 

됨.


13. 이것이 로그 폭탄

실제 장애 시

로그 수백만 건
 

발생 가능.


14. 실무 권장

로그는 보통

최종 처리 지점
 

에서만 남김.


ControllerAdvice
 

15. 좋은 구조

Repository
 ↓
Service
 ↓
Controller
 ↓
ControllerAdvice
 

예외는 계속 던지고

 
throw e;
 

로그는

 
@ControllerAdvice
 

에서 한 번만.


16. 예외를 잡고 무시하면 안 됨

매우 중요.


안 좋은 코드

 
catch(Exception e) {

}
 

또는

 
catch(Exception e) {

    log.error("에러");
}
 

17. 문제

예외 사라짐.


결과

시스템은 실패했는데
성공한 것처럼 보임
 

18. 예외를 다시 던져야 함

 
catch(Exception e) {

    log.error("실패", e);

    throw e;
}
 

또는

 
throw new BusinessException(e);
 

19. 개인정보 로그 주의

매우 중요.


안 좋은 예

 
log.info(
    "password={}",
    password
);
 

또는

 
log.info(
    "주민번호={}",
    rrn
);
 

20. 절대 금지 대상

대표적으로:

비밀번호
주민번호
카드번호
토큰
Access Token
Refresh Token
 

21. 로그 마스킹

 
010-1234-5678
 

010-****-5678
 

22. 예외 로그 포맷 추천

실무 예시

 
log.error(
    "[USER] 회원 조회 실패. id={}",
    userId,
    e
);
 

23. 왜 좋을까?

검색 가능.

[USER]
 

검색.


24. MDC란?

실무 고급 주제.


MDC

(Mapped Diagnostic Context)


목적

요청별 식별자 저장
 

 
MDC.put(
    "traceId",
    UUID.randomUUID()
);
 

25. 로그 결과

[traceId=ABC123]
회원 조회 실패
 

26. 왜 중요할까?

MSA 환경에서는

서버 A
↓
서버 B
↓
서버 C
 

흐름 추적 필요.


27. Trace ID

대표적으로:

OpenTelemetry

또는

Spring Cloud Sleuth

(현재는 Micrometer Tracing 기반으로 발전)

사용.


28. 예외 체이닝 로그

좋은 코드

 
catch(SQLException e) {

    throw new UserException(e);
}
 

로그

 
log.error(
    "회원 조회 실패",
    e
);
 

결과

UserException
 ↓
SQLException
 

전부 출력.


29. 실무 로그 레벨 전략


상황 레벨
정상 요청 INFO
디버깅 DEBUG
복구 가능 문제 WARN
시스템 실패 ERROR

30. 자주 하는 실수

printStackTrace()

실무 금지 수준.


로그 중복

한 예외 여러 번 출력.


예외 삼키기

 
catch(Exception e){}
 

민감 정보 출력

보안 사고 가능.


모든 예외 ERROR

로그 오염 발생.


31. Spring 실무 패턴

Repository
 ↓
Service
 ↓
Controller
 ↓
@ControllerAdvice
 ↓
로그 기록
 ↓
응답 반환
 

32. 핵심 흐름 요약

예외 발생
↓
전파
↓
최상위 처리
↓
로그 1회 기록
↓
응답 반환
 

33. 가장 중요한 핵심 한 줄

좋은 예외 로그는
예외를 많이 남기는 것이 아니라
원인을 한 번에 찾을 수 있게 남기는 것이다.
 

34. 면접 단골 질문

Q. printStackTrace()를 사용하면 안 되는 이유는?

로그 시스템 연동 불가
운영 환경 검색 불가
포맷 관리 불가
 

Q. 로그는 어디서 남겨야 하나요?

최상위 예외 처리 지점
(ControllerAdvice)
 

Q. 예외를 잡고 로그만 남기면 되나요?

안 됨

재전파하거나
비즈니스 예외로 변환 필요
 

다음 글은 "실무 예외 처리 패턴" 으로 진행하면 됩니다.

여기서부터는 지금까지 배운:

  • Exception
  • RuntimeException
  • Custom Exception
  • Logging
  • ControllerAdvice

를 전부 연결해서 실제 Spring 프로젝트 구조로 들어가게 됩니다.

반응형

댓글