2025-12-23
오늘 배운 것
IllegalArgumentException은 항상 400일까?
오늘의 질문
- IllegalArgumentException을 400 Bad Request로 매핑하는 것이 정말 안전한가?
핵심 개념 정리
1. 4xx vs 5xx의 본질적 차이
- 4xx (Client Error)
- 클라이언트 요청 자체가 잘못됨
- 요청을 수정하지 않으면 재시도 의미 없음
- 예: 400, 401, 404
- 5xx (Server Error)
- 서버 내부 문제로 처리 실패
- 일시적 장애 가능 → 재시도(backoff) 의미 있음
- 예: 500, 502, 503
-
기준은 단순함
→ 책임이 클라이언트인가, 서버인가
2. 운영·모니터링 관점에서의 중요성
- 5xx는 즉시 알람·대응 대상
- 서버 버그를 4xx로 내려버리면
- 클라이언트 문제로 오인
- 장애 인지 및 대응 지연
- 반대로 클라이언트 오류를 5xx로 주면
- 불필요한 장애 알람 증가
- 진짜 장애를 놓칠 위험
IllegalArgumentException이 위험한 이유
- IllegalArgumentException은 의미가 너무 넓은 예외
- 클라이언트 입력 오류
- 서버 내부 로직 오류
- 라이브러리/프레임워크 내부 오류
- 발생 원인이 외부 요청인지 내부 버그인지 구분 불가
예시
- Thread.setPriority(1~10 범위 초과 시 IllegalArgumentException 발생)
- 서버 내부 계산 로직 오류로도 충분히 발생 가능
- 이걸 400으로 내려버리면
- 서버 버그가 클라이언트 잘못으로 숨겨짐
권장되는 예외 매핑 전략
1. 기본 원칙
- 예상 못 한 예외 → 5xx
- 명백한 클라이언트 잘못 → 4xx
- 원인을 파악한 뒤 4xx로 좁혀가는 방식이 안전
2. 비즈니스 예외 vs 시스템 예외
- 비즈니스 예외
- 입력 조건 불만족, 정책 위반 등
- 예: 최소 주문 금액 미달
- → 400 Bad Request
- 시스템 예외
- DB 장애, 외부 API 실패, NPE, 내부 로직 버그
- → 5xx
- 예측 가능한 시스템 예외
- fallback, 별도 모니터링 포인트로 관리
3. 커스텀 예외 사용
- IllegalArgumentException 대신
- BusinessException
- InvalidExpressionException 등
- 의도적으로 400을 내려야 하는 경우에만 사용
- Global Exception Handler에서는
- BusinessException만 400으로 매핑
@ExceptionHandler(BusinessException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
출처
https://techblog.woowahan.com/21686/