- Spring MVC 마스터하기 예외처리 102022년 06월 19일
- starryeye
- 작성자
- 2022.06.19.:37
스프링 부트가 기본으로 제공하는(등록하는) ExceptionResolver에 대해 계속 알아보자..
1. ExceptionHandlerExceptionResolver : @ExceptionHandler 처리
2. ResponseStatusExceptionResolver : Http 상태코드 지정할 수 있는 @ResponseStatus 처리
3. DefaultHandlerExceptionResolver : 스프링 내부 기본 예외 처리
위 순서대로 우선순위가 있다.
(1번 return null이면 다음 ExceptionResolver인 2번이 호출되는 식)
이번엔..
첫번째 우선순위를 가진.. ExceptionHandlerExceptionResolver에 대해 알아보자.
BasicErrorController를 회피하는 방법이다.
(응답데이터를 바로 내려주는 방법)
+ 상태코드까지 컨트롤 가능
장점을 먼저 알아보자..
1. 예외처리에서 바로 응답데이터를 만들어 내려주기 위해
HandlerExceptionResolver를 직접 구현하지 않아도 된다.
-> HttpServletRequest, HttpServletResponse를 사용하며 과거 스타일 코드를 다룰 필요가 없어짐.
-> 사용도 안하는 ModelAndView를 생성하여 반환 할 필요가 없다.2. 같은 예외라도 컨트롤러에 따라 다르게 응답(상태코드, 바디 데이터)을 내려줄 수 있다.
(물론 예외에 따른 상태코드 정의는 2번, 3번 방법으로 충분..)
@ExceptionHandler, @RestControllerAdvice
@ExceptionHandler를 처리해주는 ExceptionResolver가 ExceptionHandlerExceptionResolver이다.
위와 같이 사용할 수 있다.
@RestControllerAdvice 어노테이션으로 따로 빼서 예외 처리용 컨트롤러로 구현하지 않고
일반 @RestController 에 위 3개의 메서드 컨트롤러를 추가하여 구현해놓으면..
그 클래스 컨트롤러에만 적용된다.
@RestControllerAdvice를 사용하면 어느 클래스 컨트롤러에 적용할지 조절이 가능하다.
대상을 지정하지않고(어노테이션 요소 사용X) 사용하면 기본 값은 글로벌 적용이다.
-> 모든 컨트롤러에 적용
annotations 요소 : 특정 어노테이션이 있는 컨트롤러에만 적용 할 수 있는 요소이다.
(개발자가 어노테이션을 만들거나 원래 있는 어노테이션을 적용 가능)
basePackages 요소 : 패키지 단위의 컨트롤러에 적용가능
assignableTypes 요소 : 특정 클래스 컨트롤러에 적용가능
(예외처리용 컨트롤러(@ExceptionHandler) 말고도.. @InitBinder를 빼서 사용하는데도 사용됨)
예외 처리용 컨트롤러 메서드를 보자..
@ExceptionHandler 어노테이션을 사용하고 있다.
요소의 의미는 적용될 컨트롤러에서 요소에 적어놓은 예외가 발생했을 때 해당 예외 처리용 컨트롤러가 불리도록 한다.
(요소가 생략된 경우는 해당 파라미터의 타입을 따른다.)
결국 예외처리용 컨트롤러는 컨트롤러이기 때문에 개발자가 보내고 싶은 모양으로
객체를 리턴할 수 있다. (예시에서는 ErrorResult 객체를 따로 정의 하여 사용)
(ResponseEntity를 생성하여 리턴하거나 @ResponseStatus로 응답 상태코드를 지정할 수 있다.)
(ResponseEntity를 사용하면 동적으로 변경 가능)
(@ResponseStatus가 없거나 요소를 지정하지 않으면 default 200이다.)
예외 상속 구조에 따른 적용될 예외 처리용 컨트롤러는 구체적인게 우선이다.
자식 예외 타입 처리용 컨트롤러와 부모 예외 타입 처리용 컨트롤러가 동시에 있다면..
자식 예외 타입이 터짐 -> 자식 예외 타입 처리용 컨트롤러 호출
부모 예외 타입이 터짐 -> 부모 예외 타입 처리용 컨트롤러 호출 (자식은 부모를 담을 수 없으니..)
<참고>
@RestControllerAdvice로 따로 빼놓던 @RestController에 함께 구현하든..
결국 @ResponseBody이므로 Http 응답 데이터에 직접 데이터가 담긴다.(HttpMessageConverter 적용 됨)
(사실 @Controller로 해놓고 반환값 String하면 view 호출 까지 지원됨.. 하지만 실무에선.. API용으로만 사용됨..)
<동작 순서>
위 예시 코드를 바탕하여 설명
hello.exception.api 패키지 내부의 어느 컨트롤러에서 IllegalArgumentException이 터짐
-> ExceptionResolver들이 호출됨
-> 1순위인 ExceptionHandlerExceptionResolver가 호출됨
-> IllegalArgumentException을 처리 할 수 있는 @ExceptionHandler 컨트롤러(예외처리용 컨트롤러)가 있는지 확인
-> 해당 컨트롤러를 호출
-> @RestController 적용되어있으니.. @ResponseBody적용됨
-> HttpMessageConverter가 동작하여 return된 객체가 Json으로 변경됨
-> @ResponseStatus를 보고 400으로 설정됨
-> 그대로 응답으로 나감
ExceptionResolver에 의해 결국 정상 흐름으로 바꾸게 되었다.
->sendError를 사용하지 않고 응답데이터를 만들어줘서 BasicErrorController가 호출되지 않았고 바로 응답으로 나갔다.
<궁금한 점..>
1. 예외처리용 컨트롤러에 accept application/json 조건을 걸고..
accept가 text/html 이라면.. BasicErrorController가 호출될까..?
-> ExceptionHanderExceptionResolver 코드를 보자...(??)-> 호출됨. accept 조건때문에 ExceptionHandlerExceptionResolver 에서 처리를 못할 것이고..
-> 예외에 따라서 2, 3순위 ExceptionResolver가 호출되어 결국 sendError처리 되어 BasicErrorController가 호출된다.
2. @ExceptionHandler 요소에 TypeMismatchException.class(스프링 내부 예외) 를 적용하면 호출 될까..?
-> 호출됨.. 컨트롤러 호출전에 예외가 발생하더라도.. ExceptionResolver는 반드시 거치기 때문에 호출된다.
<참고>
아래 페이지에서 @ExceptionHandler가 지원하는 파라미터, return 타입을 볼 수 있다.
'Spring > MVC' 카테고리의 다른 글
Spring MVC 마스터하기 예외처리 9 (0) 2022.06.19 Spring MVC 마스터하기 예외처리 8 (0) 2022.06.19 Spring MVC 마스터하기 예외처리 7 (0) 2022.06.18 Spring MVC 마스터하기 예외처리 6 (0) 2022.06.18 Spring MVC 마스터하기 예외처리 5 (0) 2022.06.11 다음글이전글이전 글이 없습니다.댓글