Spring 7기 프로젝트/일정관리 프로젝트
[트러블슈팅] Spring의 글로벌 예외 처리와 커스텀 예외 클래스
JuNo_12
2025. 5. 13. 19:34
@RestControllerAdvice 란?
- 전역 예외 처리
컨트롤러에서 발생하는 예외를 전역적으로(즉, 모든 컨트롤러에 대해 공통적으로) 처리할 수 있다.
각 예외 유형마다 별도의 메서드를 만들어, 상황에 맞는 HTTP 상태 코드와 메시지를 반환할 수 있다. - RestController와의 통합
내부적으로 @ControllerAdvice와 @ResponseBody를 결합한 것과 같다.
즉, 반환값이 자동으로 JSON, XML 등 REST 응답 형태로 변환 - 코드 중복 감소
개별 컨트롤러마다 try-catch를 두지 않아도 되며, 예외 처리 로직을 한 곳에서 일관되게 관리할 수 있다.
정리 : REST API에서 발생할 수 있는 다양한 상황을 전역적으로, 효율적이고 일관되게 처리하기 위한 도구
@ExceptionHandler 란?
- 대상 예외 지정
파라미터 또는 애너테이션의 값으로 처리하고 싶은 예외 클래스(예: IllegalArgumentException.class)를 지정합니다. - 예외 발생 시 동작
컨트롤러 내, 또는 @RestControllerAdvice(혹은 @ControllerAdvice) 클래스 내에 정의할 수 있으며, 지정한 예외가 발생하면 해당 메서드가 자동으로 실행됩니다. - 맞춤형 응답 반환
예외 상황에 따라 직접 메시지, 상태 코드, 또는 원하는 형식의 응답(JSON, 객체 등)을 반환할 수 있습니다.
정리 : @ExceptionHandler는 예외 상황별로 맞춤 응답을 만드는 데 사용하는 애너테이션 / 코드 가독성과 예외 처리의 일관성을 높일 수 있다.
1. GlobalExceptionHandler의 역할
- @RestControllerAdvice를 사용하여 프로젝트 전역에서 발생할 수 있는 예외를 한 곳에서 처리할 수 있다.
- @ExceptionHandler를 통해 각 예외 유형 별로 적절한 HTTP 상태 코드와 메시지를 반환할 수 있다.
- 대표적인 처리 예시:
- → 400 Bad Request InvalidPasswordException
- → 404 Not Found ScheduleNotFoundException
- 그 외 모든 Exception → 500 Internal Server Error
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(InvalidPasswordException.class)
public ResponseEntity<String> handleInvalidPasswordException(InvalidPasswordException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
}
@ExceptionHandler(ScheduleNotFoundException.class)
public ResponseEntity<String> handleNotFound(ScheduleNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage());
}
// 최종 방어막 (예기치 못한 오류 발생 시)
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleOtherException(Exception ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("서버 오류가 발생했습니다: " + ex.getMessage());
}
}
- 모든 컨트롤러에서 중복되는 try-catch문이 필요 없어 유지보수성이 크게 향상된다.
- 예외 별로 응답 형태와 메시지를 일관되게 구성할 수 있다.
@ExceptionHandler(Exception.class)
- 이 애너테이션은 Exception 타입의 예외가 발생하면 해당 메서드가 실행되도록 설정
- Exception.class는 모든 예외의 최상위 클래스이므로, 이 핸들러는 컨트롤러 내부에서 발생하는 예외 대부분을 처리할 수 있다.
2. 커스텀 예외 클래스
InvalidPasswordException
- 비밀번호 불일치 등의 비즈니스 로직 예외 상황에 사용되는 커스텀 예외
- RuntimeException 을 상속받아 필요할 때 자유롭게 throw할 수 있다.
public class InvalidPasswordException extends RuntimeException {
public InvalidPasswordException(String message) {
super(message);
}
}
ScheduleNotFoundException
- 일정이 존재하지 않을 때(예: 특정 ID로 조회 시 결과가 없을 때) 사용되는 예외입니다.
- 마찬가지로 RuntimeException 상속 후, 메시지를 입력받아 생성됩니다.
public class ScheduleNotFoundException extends RuntimeException {
public ScheduleNotFoundException(String message) {
super(message);
}
}
커스텀 예외 사용 이유
- 예외 상황을 더 명확하게 구분하고, 상황별로 적절한 처리를 할 수 있습니다.
- API 응답의 신뢰성이 높아지고, 디버깅 및 로그 분석이 쉬워집니다.
3. 활용 예시 흐름
- 사용자가 잘못된 비밀번호로 일정을 수정/삭제 시도
→ InvalidPasswordException 발생
→ GlobalExceptionHandler가 이 예외를 받아서 400 반환 - 존재하지 않는 일정(ID) 조회 시
→ ScheduleNotFoundException 발생
→ GlobalExceptionHandler가 404 반환
4. 오늘의 깨달음
- @RestControllerAdvice 하나만으로 전체 시스템의 예외 관리를 효율화할 수 있음을 경험
- 커스텀 Exception 설계를 통해 비즈니스 로직의 명확한 예외 처리가 가능함을 확인