*공식문서를 바탕으로 공부하고 작성한 글입니다!
💋 스프링의 예외 처리
Spring에서 에외를 처리하는 방법은 많다. (출처: 지피티쌤)
이번 포스팅에서는 @ExceptionHandler 어노테이션을 사용하는 방법에 대해서 공부해보자!
💋 @ExceptionHandler
컨트롤러에서 예외가 발생했을 때, 예외를 처리하는 메서드를 지정하는 어노테이션이다.
일반적으로 예외 처리는 try-catch 블록 안에서 하게 되지만, 컨트롤러에서 예외가 발생한 경우에 별도로 @ExceptionHandler를 사용해 예외 처리 메서드를 정의해야 한다.
예를 들어서, 사용자가 로그인을 시도할 때 인증 오류가 발생했다고 생각해보자. 서버는 인증 오류에 대한 예외를 반환할 거고, @ExceptionHandler를 사용해서 예외 처리 메서드를 지정해주면, 서버 인증 오류에 대한 예외가 발생한 경우에 서버는 정의된 메서드를 호출해서 예외를 처리할 수 있다. 결과적으로 불필요한 중복 코드를 피하고, 간결하고 유지보수가 가능한 코드를 만들 수 있다.
스프링에서 @Controller와 @ControllerAdvice 어노테이션을 달고 있는 클래스들은 @ExceptionHandler 메서드를 사용해서, 컨트롤러에서 발생하는 예외들을 처리할 수 있다.
@Controller
public class SimpleController {
// ...
@ExceptionHandler
public ResponseEntity<String> handle(IOException ex) {
// ...
}
}
아래의 코드에서와 같이 어노테이션 내에서 value 값으로 구체적으로 어떤 예외 타입을 처리할 것인지 선언할 수 있다.
value를 설정하지 않으면, 모든 예외를 다 잡기 때문에 구체적으로 적어주는 것이 좋다.
@ExceptionHandler({FileSystemException.class, RemoteException.class})
public ResponseEntity<String> handle(IOException ex) {
// ...
}
여러 개의 예외를 잡기 위해서 value 안에 예외 유형의 목록을 작성했다면, 파라미터 자리에는 아주 일반적인 예외인 Exception과 같이 상위의 예외가 들어가도 상관없다!
@ExceptionHandler({FileSystemException.class, RemoteException.class})
public ResponseEntity<String> handle(Exception ex) {
// ...
}
그럼에도 파라미터 자리에는 최대한 구체적인 예외를 작성하도록 노력하는 것이 좋다.
@ExceptionHandler({IOException.class})처럼 포괄적인 예외를 잡는 것이 아니라, @ExceptionHandler({FileSystemException.class, RemoteException.class})처럼 구체적인 클래스를 나열하는 것이 더 좋다는 말이다!
참고로, @ExceptionHandler 어노테이션은 예외의 타입 뿐만 아니라, 예외의 원인(cause)도 처리할 수 있다. 예외의 원인은 예외를 발생시키는 원인이 되는 예외 객체를 말한다. 예를 들어, IOException이 발생할 때, 그 원인이 되는 객체가 NullPointer 예외일 수도 있다.
이전 버전의 스프링에서는 예외 처리 시, 예외의 원인이 바로 위의 예외에 대해서만 처리할 수 있었지만, 5.3 버전부터는 모든 원인까지 확인하여 예외를 처리할 수 있게 되었다. 즉, 예외를 발생시키는 최상위 예외부터, 예외를 발생시키는 가장 깊은 원인까지 모두 처리할 수 있게 되었다.
예외 처리의 정확성과 유연성이 개선되었으며, 보다 정확하고 효과적인 예외 처리가 가능해졌다.