FireDrago
[Spring] 스프링 API 예외처리 본문

스프링에서 예외처리시 HTML 페이지를 반환하는 경우, BasicErrorController에 따라 html 페이지만 등록하면 된다.
그런데 Json을 사용하는 API는 예외 상황별 json 데이터를 다양하게 반환해야 하는 상황이 있다.
예를들어 서버간 통신을 할때, html 페이지를 전송할 수는 없다. html은 브라우저만 해석할 수 있기 때문이다.
그렇다면 API 에서는 어떻게 예외처리 할 수 있을까? 우선 BasicErrorController 를 살펴보자

BasicErrorController 에서도 @Request(produces) 속성을 사용하여 HTML 요청과 API 요청에 대응하도록 되어있다.
API 요청시, "/error" 경로를 지정하고, ResponseEntity 를 반환하여 HTTP 바디에 직접 메시지를 입력할 수 있도록 했다.
API 요청시에도 WAS 까지 에러는 전달 될 것이고, 복잡한 재요청 과정이 다시 실행된다
간단하고 유연하게 에러를 처리하기 위해서 HandlerExceptionResolver 가 필요하다.
BasicErrorController 를 사용한 에러처리는 HTML 을 반환하는 경우에만 사용하고,
API 요청 에러처리를 할 경우 HandlerExceptionResolver 를 사용하는것이 좋다.
<HandlerExceptionResolver>

HandlerExceptionResolver는 핸들러에서 발생한 에러를 WAS 까지 전달되기 전에 처리할 수 있는 인터페이스이다.
위의 그림에서 볼 수 있듯이, ModelAndView를 반환한다. 코드로 살펴보자

UserHandlerExceptionResolver 는 HandlerExceptionResolver 를 구현했다.
먼저 전달된 예외가 UserException 이 맞는지 확인한다. 맞다면 response 에 에러상태코드를 400으로 변경해준다.
그런다음 HTTP 헤더의 Accept 가 "application/json" 인 경우 ObjectMapper 를 사용하여 json 형태로 페이지를 반환한다.
(response 에 직접 contentType, characterEncoding 설정한다. ObjectMapper를 이용한 String 직접 입력해준다)
만약 Accept 가 JSON 이 아닌경우 ModelAndView 에 경로를 담아 View를 렌더링하도록 한다.
ModelAndView 반환 형태
- 빈 객체 : View를 렌더링 하지 않는다.
- View 또는 Model : View를 렌더링한다.
- null : 다음 HandlerExceptionResolver가 실행된다.
다음은 이렇게 정의한 UserHandlerExceptionResolver를 등록하는 방법을 알아보자

WebMvcConfigurer 를 구현한 @Configuration 클래스에서 extendHandlerExceptionResolver( ) 메서드를 작성한다.
파라미터로 전달된 List resolvers 에 내가 정의한 객체를 생성하여 담아주면 된다.
이렇게하여, 오류처리를 유연하게 할 수 있는 방법을 알아보았는데, 조금 복잡한 느낌이 든다.
<스프링이 제공하는 기본 HandlerExceptionResolver>

스프링은 HandlerExceptionResolver 의 기본 구현체를 제공한다. 하나씩 기능을 살펴보자
<ExceptionHandler>
API 에서 예외처리할때 사용되는 애너테이션이다. 코드로 살펴보자

@ControllerAdvice , @RestController 애너테이션을 사용하여 클래스와 에러처리 클래스를 분리할 수 있다.
또한 에러처리 범위를 지정할수 있다. (기본값은 글로벌 적용)

@ExceptionHandler 애너테이션을 사용하면, ExceptionHandlerExceptionResolver가 인식하고,
마치 정상 처리된 것처럼 처리해준다. 반환타입으로 ResponseEntity를 사용하여, 동적으로 상태코드등을 처리할수 있고, @ResponseStatus 애너테이션으로 상태코드를 처리할 수 도 있다.
@ExceptionHandler 에는 마치 스프링의 컨트롤러의 파라미터 응답처럼 다양한 파라미터와 응답을 지정할 수 있다.
자세한 파라미터와 응답은 다음 공식 메뉴얼을 참고하자.
https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-annexceptionhandler-args
Redirecting...
docs.spring.io
<ResponseStatus>


ResponseStatusExceptionResolver 는 예외에 따라서 상태코드를 지정해준다.
@ResponseStatus 적용된 예외와 ResponseException 예외를 처리한다.
애너테이션을 사용하면 편리하게 예외처리 할 수 있지만, 라이브러리등 개발자가 코드를 직접 조작하지 못하는 곳
에는 사용하지 못한다. 또한 동적인 처리도 어렵다. 이럴때는 ResponseException 객체를 사용하면 된다.
<DefaultException>
DefaultHandlerExceptionResolver 는 스프링 내부에서 발생하는 스프링 예외를 해결한다.
대표적으로 파라미터 바인딩 시점에 타입이 맞지 않으면 내부에서 TypeMismatchException 이 발생하는데, 이 경
우 예외가 발생했기 때문에 그냥 두면 서블릿 컨테이너까지 오류가 올라가고, 결과적으로 500 오류가 발생한다.
그런데 파라미터 바인딩은 대부분 클라이언트가 HTTP 요청 정보를 잘못 호출해서 발생하는 문제이다. HTTP 에서는
이런 경우 HTTP 상태 코드 400을 사용하도록 되어 있다.
DefaultHandlerExceptionResolver 는 이것을 500 오류가 아니라 HTTP 상태 코드 400 오류로 변경한다.
스프링 내부 오류를 어떻게 처리할지 수 많은 내용이 정의되어 있다
'프로그래밍 > Spring' 카테고리의 다른 글
| [Spring] 파일업로드 (0) | 2024.02.22 |
|---|---|
| [Spring] 스프링 타입 컨버터와 포매터 (0) | 2024.02.21 |
| [Spring] 스프링 예외처리와 오류페이지 (0) | 2024.02.17 |
| [Spring] 서블릿 필터와 스프링 인터셉터 (0) | 2024.02.15 |
| [Spring] 로그인 쿠키와 세션 (0) | 2024.02.14 |
