IT/SpringBoot

[SpringBoot] 예외처리

j8970 2025. 5. 7. 17:11

Spring Boot Global Exception Handler 정리

스프링 부트(Spring Boot)에서 예외 처리의 **단일 책임 원칙(SRP)**을 지키고, 재사용성과 가독성을 높이기 위해 사용하는 @RestControllerAdvice 기반의 전역 예외 처리 클래스를 정리합니다.


📌 전역 예외 처리(GlobalExceptionHandler)란?

🔷 정의

  • @RestControllerAdvice 어노테이션을 사용하여, 모든 @RestController에서 발생하는 예외를 하나의 클래스에서 통합적으로 처리할 수 있는 방식입니다.

🔷 장점

  • 단일 책임 원칙(SRP) 준수: 예외 처리를 각 Controller가 아닌 별도의 클래스에서 관리
  • 재사용성 증가: 하나의 클래스에서 모든 예외를 처리
  • 가독성 향상: 중복되는 예외 처리 코드 제거 및 명확한 책임 분리

📌 주요 예외 핸들링 목록

🔷 400 Bad Request (잘못된 요청)

  • IllegalArgumentException
  • MethodArgumentNotValidException (DTO 검증 실패 시, @Valid 사용 시 발생)
@ExceptionHandler({IllegalArgumentException.class, MethodArgumentNotValidException.class})
public ResponseEntity<ResponseDto<?>> handleBadRequest(Exception e) {
    e.printStackTrace();
    ResponseDto<?> response = ResponseDto.setFailed("Bad Request: " + e.getMessage());
    return ResponseEntity.badRequest().body(response);
}

🔷 403 Forbidden (권한 없음)

  • AccessDeniedException: 인증되지 않은 사용자의 접근
@ExceptionHandler(AccessDeniedException.class)
public ResponseEntity<ResponseDto<?>> handleAccessDenied(AccessDeniedException e) {
    e.printStackTrace();
    ResponseDto<?> response = ResponseDto.setFailed("Access Denied: " + e.getMessage());
    return ResponseEntity.status(HttpStatus.FORBIDDEN).body(response);
}

🔷 404 Not Found (엔티티 없음)

  • EntityNotFoundException: 데이터베이스에서 엔티티를 찾을 수 없음
@ExceptionHandler(EntityNotFoundException.class)
public ResponseEntity<ResponseDto<?>> handleNotFoundException(EntityNotFoundException e) {
    e.printStackTrace();
    ResponseDto<?> response = ResponseDto.setFailed("Not Found: " + e.getMessage());
    return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
}

🔷 409 Conflict (데이터 충돌 / 무결성 위반)

  • DataIntegrityViolationException: DB 제약 조건 위반 시 발생
@ExceptionHandler(DataIntegrityViolationException.class)
public ResponseEntity<ResponseDto<?>> handleDataIntegrityViolationException(DataIntegrityViolationException e) {
    e.printStackTrace();
    ResponseDto<?> response = ResponseDto.setFailed("Conflict : " + e.getMessage());
    return ResponseEntity.status(HttpStatus.CONFLICT).body(response);
}

🔷 500 Internal Server Error (서버 내부 오류)

  • Exception: 기타 모든 예외를 처리 (가장 마지막 수단)
@ExceptionHandler(Exception.class)
public ResponseEntity<ResponseDto<?>> handleException(Exception e) {
    e.printStackTrace();
    ResponseDto<?> response = ResponseDto.setFailed("Internal Server Error : " + e.getMessage());
    return ResponseEntity.internalServerError().body(response);
}