티스토리 뷰

개발 노트/개발 가이드라인

Java 예외 처리 가이드라인

시뮬레이션 프로그래머 2025. 8. 21. 22:52

Java에서 자주 쓰는 예외/에러 클래스

구분 (체크/언체크/에러) 대표 클래스 하위/관련 예외 설명
Checked Exception
(Exception 상속,
RuntimeException 미상속)
IOException FileNotFoundException,
EOFException,
ObjectStreamException
파일/네트워크 I/O 문제
  SQLException SQLTimeoutException,
SQLTransientException
DB 액세스·쿼리 오류
ClassNotFoundException NoSuchMethodException,
NoSuchFieldException
클래스/메서드/필드 로딩 실패
ParseException   문자열·데이터 파싱 실패
InterruptedException 스레드 인터럽트 발생
CloneNotSupportedException 객체 복제 불가
GeneralSecurityException 암호화·보안 관련 오류
MalformedURLException UnknownHostException 잘못된 URL, 네트워크 해석 실패
- 구분 -
Unchecked Exception
(RuntimeException 계열)
NullPointerException   null 참조 접근
  IllegalArgumentException NumberFormatException 잘못된 인자 전달
IllegalStateException   잘못된 객체 상태에서 호출
IndexOutOfBoundsException ArrayIndexOutOfBoundsException,
StringIndexOutOfBoundsException
인덱스 범위 초과
ConcurrentModificationException   컬렉션 수정 중 순회 오류
UnsupportedOperationException 지원되지 않는 연산
ArithmeticException 0으로 나누기 등 수학 오류
NegativeArraySizeException 음수 크기 배열 생성 시
ClassCastException 잘못된 타입 캐스팅
IllegalMonitorStateException 동기화 모니터 사용 오류
RejectedExecutionException 스레드 풀에 작업 제출 실패
UncheckedIOException I/O 오류를 Runtime 예외로 래핑
- 구분 -
Error(Error 계열, 복구 불가) OutOfMemoryError   힙 메모리 부족
  StackOverflowError   재귀 과다 호출
  VirtualMachineError   JVM 자체 문제
  NoClassDefFoundError   클래스 로딩 실패

Java 예외 처리 가이드라인 (상황 → 전략 매핑)

상황 대표 예외 (예시) 심각도 /
복구 가능성
기본 처리 전략 외부 응답
(HTTP)
로그레벨 메트릭
/알림
비고
입력 유효성 실패 IllegalArgumentException,
서버 측 검증 오류
낮음 /
복구 가능(사용자 수정)
요청 스키마/범위 검증 → 오류 메시지 반환 400
WARN 요청 실패 카운트 클라이언트 가이드 포함(필드·포맷)
파싱/포맷
오류
ParseException,
NumberFormatException
낮음 /
복구 가능
포맷 에러 상세 반환 400 WARN 실패 카운트 예: 날짜/숫자 포맷
인증 실패 (프레임워크 예외),
토큰 검증 실패
낮음 /
복구 가능
재인증 유도 401
INFO~WARN 인증 실패율 민감 정보 로그 금지
인가(권한) 실패 (프레임워크 예외) 낮음 /
복구 가능
권한 오류 반환 403
INFO~WARN 권한 실패율  
비즈니스
규칙 위반
커스텀 BusinessException 보통 /
재시도 무의미
도메인 코드·메시지로 응답 409
또는
422
INFO~WARN 도메인 실패율 예: 잔액 부족, 재고 없음
네트워크
일시 장애
(타임아웃, 일시적)
SocketTimeoutException,
IOException
보통 /
재시도 가능
지수 백오프 재시도, 회로차단기, 폴백 502/
504
또는
503
WARN 외부 의존성 에러율·지연 idempotency 고려
네트워크
영구 실패
(DNS/호스트)
UnknownHostException,
지속 4xx
보통 /
재시도 무의미
즉시 실패, 재시도 금지, 설정 재검토 502/
503
ERROR 알람(연속 실패) 구성/비밀키 오류 가능
외부
Rate Limit 초과
(HTTP 429) 낮~보통 / 재시도 가능 Retry-After 준수, 백오프, 큐잉 429
WARN 429 비율 서드파티 정책 반영
DB
제약 위반
SQLException (unique/foreign key) 보통 /
재시도 무의미
도메인 오류 변환 후 응답 409/
422
INFO~WARN 제약 위반 카운트 중복 요청/순서 문제 점검
DB 데드락/락 타임아웃 SQLException (deadlock) 보통 /
재시도 가능
짧은 백오프 재시도, 트랜잭션 단축 503(서버 내부)/
200(내부 재시도 성공 시)
WARN 데드락 건수, 재시도 성공률 쿼리·인덱스·격리수준 점검
DB
연결 부족/
풀 고갈
SQLException (pool exhausted) 높음 /
조건부 복구
서킷 오픈, 큐 길이 제한, 백프레셔 503 ERROR 즉시 알람, 연결 사용률 리소스 상한/리크 점검
파일
I/O 오류/
디스크 꽉 참
IOException 높음 /
조건부 복구
쓰기 중단, 읽기 전용 전환/폴백 507/
500
ERROR 디스크 사용률 알람 로테이션·정리 작업 필요
동시성 오류 RejectedExecutionException,
IllegalMonitorStateException
보통 /
설계 이슈
큐/스레드 제한, 배압, 재시도 여부 판단 503 WARN~ERROR 큐 길이·거절률 용량 계획/스로틀링
타임아웃
(SLA 초과)
(도메인 타임아웃) 보통 /
설계 이슈
타임아웃 단축, 캐시/폴백 504/
503
WARN P95/P99 지연 핫패스 최적화
버그/NPE/
경계 케이스
NullPointerException,
IndexOutOfBoundsException 등
높음 /
비복구
Fail-fast, 에러 페이지, 알람 500 ERROR 즉시 알람, Sentry 등 재현 케이스와 함께 수정
메모리 부족/스택 오버플로 OutOfMemoryError,
StackOverflowError
치명적 /
비복구
프로세스 재시작, 메모리 덤프 500 FATAL 즉시 알람 릴리즈 전 부하 테스트 필
정책에 따라 달라질 수 있음.

처리 규칙 요약

  1. 입력·파싱: 즉시 400, 무엇이 잘못됐는지 구체 메시지.
  2. 비즈니스 위반: 409/422와 도메인 에러코드(사용자 재시도 무의미).
  3. 네트워크·외부 일시 장애: 지수 백오프 재시도 + 회로차단기 + 폴백.
  4. DB 데드락: 짧게 재시도(횟수 제한), 트랜잭션 범위·인덱스 개선.
  5. DB 제약 위반: 도메인 오류로 변환, 클라이언트 로직 수정 유도.
  6. 리소스 고갈(풀/디스크): 배압·상한, 즉시 알람, 자동 복구 전략.
  7. 버그/NPE: Fail-fast + 스택트레이스 수집 + 빠른 핫픽스.
  8. 로그 규칙: 클라이언트 탓(4xx)은 WARN, 서버 탓(5xx)은 ERROR, 치명적은 FATAL.
  9. 관찰 가능성: 모든 로그에 traceId 포함, 에러 코드·원인 체인 기록.
  10. 멱등성: 재시도되는 경로(네트워크/데드락)엔 idempotency key 필수. (= 멱등성 키)

Java 코드 스니펫(컨트롤러 예외 매핑 예시 – Spring)

@RestControllerAdvice
public class ApiExceptionHandler {

  @ExceptionHandler({ IllegalArgumentException.class, MethodArgumentNotValidException.class })
  public ResponseEntity<ApiError> handleBadRequest(Exception ex) {
    return ResponseEntity.badRequest().body(ApiError.of("VALIDATION_FAILED", ex.getMessage()));
  }

  @ExceptionHandler(BusinessException.class)
  public ResponseEntity<ApiError> handleBiz(BusinessException ex) {
    return ResponseEntity.status(409).body(ApiError.of(ex.code(), ex.getMessage()));
  }

  @ExceptionHandler(SQLTransientException.class) // deadlock/timeout 등
  public ResponseEntity<ApiError> handleSqlTransient(SQLTransientException ex) {
    return ResponseEntity.status(503).body(ApiError.of("DB_TRANSIENT", "Please retry"));
  }

  @ExceptionHandler(SQLException.class) // 제약 위반 등
  public ResponseEntity<ApiError> handleSql(SQLException ex) {
    return ResponseEntity.unprocessableEntity().body(ApiError.of("DB_CONSTRAINT", ex.getMessage()));
  }

  @ExceptionHandler({ SocketTimeoutException.class, IOException.class })
  public ResponseEntity<ApiError> handleNetwork(Exception ex) {
    return ResponseEntity.status(504).body(ApiError.of("UPSTREAM_TIMEOUT", "Upstream timeout"));
  }

  @ExceptionHandler(Throwable.class) // 마지막 안전망
  public ResponseEntity<ApiError> handleFatal(Throwable t) {
    return ResponseEntity.status(500).body(ApiError.of("INTERNAL_ERROR", "Unexpected error"));
  }
}

ApiError.of(code, message)는 { code, message, traceId } 같은 표준 에러 응답 포맷을 가정.

'개발 노트 > 개발 가이드라인' 카테고리의 다른 글

C# 예외 처리 가이드라인  (1) 2025.08.21