1. 스프링 MVC 예외 처리 개요
- 스프링 MVC는 애플리케이션에서 발생하는 예외를 우아하게 처리할 수 있는 다양한 메커니즘을 제공합니다.
- 예외 처리는 애플리케이션의 안정성과 사용자 경험 향상에 중요한 역할을 합니다.
- 스프링의 예외 처리 방식은 크게 다음과 같이 나뉩니다:
- 컨트롤러 레벨의
@ExceptionHandler - 글로벌 레벨의
@ControllerAdvice또는@RestControllerAdvice - HTTP 상태 코드 기반의 오류 페이지
- 컨트롤러 레벨의
2. @ExceptionHandler 애노테이션
@ExceptionHandler애노테이션은 컨트롤러 또는@ControllerAdvice클래스 내에서 예외를 처리하는 메서드를 지정하는 데 사용됩니다.- 이 애노테이션이 적용된 메서드는 지정된 예외 타입이 발생했을 때 자동으로 호출됩니다.
2.1 기본 사용법
@Controller나@RestController클래스 내에서 사용할 수 있습니다.- 처리하고자 하는 예외 타입을 지정하여 해당 예외가 발생했을 때 특정 응답을 반환할 수 있습니다.
기본 예제 코드
@Controller
public class SimpleController {
@ExceptionHandler(IOException.class)
public ResponseEntity<String> handle() {
return ResponseEntity.internalServerError().body("Could not read file storage");
}
}
- 이 예제는
IOException이 발생했을 때 500 상태 코드와 함께 에러 메시지를 반환합니다.
2.2 예외 매핑 방식
- 예외 매핑은 발생한 최상위 예외 또는 중첩된 원인 예외와 일치시킬 수 있습니다.
- 스프링 5.3부터는 임의의 깊이에 있는 원인 예외까지 매칭할 수 있습니다(이전 버전에서는 직접적인 원인만 고려했습니다).
- 여러 예외 메서드가 매칭될 때는 일반적으로 최상위 예외 매치가 원인 예외 매치보다 우선시됩니다.
예외 매핑 예시
ServiceException → DataAccessException → SQLException → IOException
- 위와 같은 예외 계층 구조에서 5.3 이전에는 IOException을 처리하는 핸들러가 있어도 ServiceException이나 그 직접적인 원인인 DataAccessException만 확인했기 때문에 매칭되지 않았습니다
- 하지만 5.3부터는 예외 체인을 깊게 탐색해서 IOException까지 확인하므로 해당 핸들러가 작동할 수 있게 되었습니다.
2.3 예외 매개변수 선언
@ExceptionHandler({FileSystemException.class, RemoteException.class})
public ResponseEntity<String> handleIoException(IOException ex) {
return ResponseEntity.internalServerError().body(ex.getMessage());
}
- 이 예제에서는
FileSystemException과RemoteException을 처리하며, 이 두 예외는 모두IOException을 확장합니다.
2.4 일반 예외 타입 사용 예제
@ExceptionHandler({FileSystemException.class, RemoteException.class})
public ResponseEntity<String> handleExceptions(Exception ex) {
return ResponseEntity.internalServerError().body(ex.getMessage());
}