[Spring] Exception Handler 과 Controller Advice 간단 정리

케이·2022년 8월 6일
1

학습기록

목록 보기
3/5
post-thumbnail

해당글은 공식문서를 직역한 부분이 많아 문장이 어색할 수 있습니다. 오역이 있을 시 언제든 지적해주시면 감사하겠습니다 🙇🏻‍♀️

Exception

들어가기전에 Exception에 대해 짤막하게 정리하고자 한다.
(분량이 많아 정말 최소한으로 가볍게하고 다음에 Exception 정리 포스팅..예정..)

  • Exception은 프로그램시 실행될 때 발생되는 예상치 못한, 원하지 않은 event.
  • Exception은 프로그램에 의해 잡히거나 핸들링 될 수 있다.
    메소드 안에서 Exception이 발생할 시 object를 생성하게 되는데 이 object를 Exception Object라고 부른다. Exception Object는 Exception에 관한 정보(예외 이름, 예외에 대한 설명 등)를 담고 있다.

Exception이 발생하는 주요 원인들

  • 코드 에러
  • 기계 결함
  • 네트워크 연결 장애
  • 물리적인 한계 (디스크 메모리 등)
  • 실행시킬 수 없는 파일을 여는 것 등이 있다.

우리가 개발하면서 마주치게 되는 Exception들을 처리하기 위해 Exception Handler와 Controller Advice를 사용할 수 있는데 이 둘의 개념을 학습하면서 간단히 아래처럼 정리해보았다.

Exception Handler

@Controller@ControllerAdvice 클래스들은 Controller 메소드들로부터 발생한 exception들을 처리하기 위해 @ExceptionHandler 메소드를 갖는다.

예시)

@Controller
public class SimpleController {

    // ...

    @ExceptionHandler
    public ResponseEntity<String> handle(IOException ex) {
        // ...
    }
}

특정 타입의 exception을 잡고 싶은 경우에는 아래의 예시처럼 (@ExceptionHandler({FileSystemException.class, RemoteException.class})) 작성하면 특정 Exception 하나 또는 Exception 여러개를 잡을 수 있다. 이 때 value를 넣어주지 않으면 모든 Exception을 잡는다.

스프링 공식문서에서는 Exception들을 구체적으로 명시하기를 권하고 있다.

@ExceptionHandler({FileSystemException.class, RemoteException.class})
public ResponseEntity<String> handle(IOException ex) {
    // ...
}

Controller Advice

@ExceptionHandler, @InitBuilder 그리고 @ModelAttribute 메소드들은 @Controller 클래스 이거나 해당 클래스 계층에서만 적용이 가능하다.
하지만@ControllerAdvice 또는 @RestControllerAdvice를 사용하면 어떤 컨트롤러에나 적용이 가능하다.
(= ExceptionHandler 사용해서 Exception을 핸들링 할 수 있다는 이야기)

또한 5.3 버전에서는 @Controller가 있으면 Exception을 핸들링하기 위해 @ControllerAdvice가 가지고 있는@ExceptionHandler 메소드들이 사용될 수 있다.

요약: 어플리케이션에 같은 에러를 핸들링 하는 것을 가능하게 하는 인터셉터

Controller Advice와 Rest Controller Advice

  • @ControllerAdvice는 컴포넌트 스캐닝을 통해 스프링 빈으로 등록될 수 있는 @Component의 메타 어노테이션이다.

  • @RestControllerAdvice@ControllerAdvice@ResponseBody의 메타 어노테이션이다. 그렇기 때문에 @ExceptionHandler가 response body로 렌더링 된 리턴 값을 갖는다.

Controller Advice로 잡을 수 없는 예외?

Spring Security Exception
(예시, runtime exception에 속하는 AuthenticationException과 AccessDeniedException)들은 핸들링 할 수 없다.
DispatcherServlet과 컨트롤러 메소드들이 불러지기 전에 authentication filter에 의해 exception이 던져지기 때문이다. 이 같은 exception들을 @ExceptionHandler@ControllerAdvice로 핸들링하기 위해서는 AuthenticationEntryPoint를 커스텀해야한다.
자세한 내용은 baeldung의 spring security exceptionhandler 참고.


적용해보기

프로젝트 진행 중 아래와 같이 작성해보았다.

아직 커스텀 예외들을 작성하지 않아 일단은 RuntimeException을 잡는 것으로 작성해두었는데 작동은 잘 하는 것으로 보인다.
하지만 이렇게 쓰면 예외가 발생 했을 때 정확히 어떤 예외가 발생했는지 확인이 어려워 해당 부분은 주석 처리해두고 프로젝트를 진행하면서 이후에 예외상황들을 좀 더 세세하게 나누어(스프링 공식문서에서 권장하듯이) 해당 클래스를 구현할 계획이다.


참고

https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-exceptionhandler
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/ExceptionHandler.html
https://www.baeldung.com/spring-security-exceptionhandler

profile
삽질하며 깨닫고 배웁니다. (a.k.a 프로삽질러) + 이 구역의 회고왕

2개의 댓글

comment-user-thumbnail
2022년 8월 7일

오.. 마침 스프링 예외처리에 대해서 공부를 하려고 했는데 어떻게 아시고 정리를 해주셧나요!! 👍
ExceptionHandler만으로는 컨트롤러 계층에서 발생한 예외만 처리되는 걸 처음 알았네요.
공식문서로 공부하는 거 정말 멋집니다. 저도 앞으로는.. 공식문서 공부 해야겠네요. 홧팅!!

1개의 답글