DevBoi

[Spring] ControllerAdvice 본문

Develop/[Spring]

[Spring] ControllerAdvice

HiSmith 2022. 5. 2. 15:56
반응형

@Exceptionhandler같은 경우는 @Controller, RestController가 적용된 Bean 내에서 발생하는 예외를 잡아서 하나의 메서드에서 처리해주는 기능을 한다.

 

 

해당 컨트롤러에서 Exception이 발생하면 아래 핸들러에서 호출되어 처리가 된다.

 

@ExceptionHandler가 하나의 컨트롤러를 위한 것이면, ControllerAdvice는 전역 모든 클래스에 대한, 모든 컨트롤러를 위한 예외를 잡아주는 역할을 한다. (특정 경로를 설정할 수도 있긴하다.)

 

 

 

 

주로 예외 처리를 위해 이렇게 사용되기는 하지만, initBinder와 함께 바인딩/ 검증 설정, ModelAttribute와 함께 사용하여, 전반에 걸친 모델 정보 설정을 해주는 등의 목적으로 사용할 수도있다.

 

 

 

1. Target : 어노테이션을 붙일수 있는 대상을 지정해준다. Type인 경우는 클래스, 인터페이스 Constructor,Method,Field등 이있다.

2. Retention : 어노테이션 메모리 유지기간을 관리하는 어노테이션이다.

 

1) RetentionPolicy.source 

소스코드까지만 남아있는다, 즉 바이트코드로 바뀔때는 어노테이션 정보가 사라진다. ex. getter,setter

 

2)class(default)

바이트코드까지만 어노테이션이 유지된다.

JVM이 기동되며 런타임에 클래스로더로부터 로딩되는 시점에 사라지게된다.

롬복의 Nonnull

 

3) Runtime

런타임때도 jvm에서 별도 메모리에 어노테이션 정보를 자고 사용해야하는경우에사용한다.

@Autowired, 실행될때 빈을 주입해야하는 경우등 실행되는 중에도, JVM에서 어노테이션의 정보를 갖고 있어야 하는 경우 사용

대부분 어노테이션이 런타임 정책이다.

 

 

참고)

 

즉, ControllerAdvice는, 스프링 빈으로 등록되는 어노테이션이다.

ExceptionHandler도, 런타임, 하지만 스프링 빈은 아니다.

 

 

 

 

스프링은 에러 처리를 위한 basicErrorController가 있다.

 

스프링에서의 예외 처리 흐름

예외가 던져지면, 예외가 발생한 컨트롤러 안에 적합한 ExceptionHandler가 있는지 ㄱ머사

컨트롤러의 ExceptionHandler에서 처리가능하다면, 처리하고 아니면 넘어간다.

컨트롤러의 Exceptionhandler에서 처리가 불가능하다면, ControllerAdvice를 찾고 적합한 ExcetpionHandler가 있는 검사한다.

ControllerAdvice에서 처리가 가능하면 처리하고 아니면 패스

컨트롤러 어디브이스에서 처리가 불가능하면, ResponseStatus가 있는지 또는 해당 익셈셥인지 검사

맞다면, ResponseStatusExceptionResovler가 처리하고, 아니면 DefaultHandlerExcetpionResolver가 처리한다.

 

 

ControllerAdvice의 동작과정 코드로 살펴보기

-디스패처 서블릿이 에러를 catch한다.

-해당 에러를 처리할 수 있는 에러처리기가 에러처리를 담당한다.

-컨트롤러의 ExceptionHandler로 처리가능한지 검사한다.

-Controlleradvice의 exceptionhandler메소드를 invoke, 예외를 반환한다.

 

우선 Exception 처리를 하면 좋은점

내부구조를 알지 못하는 사용자도 구체적 문제를 유추할 수 있다.

exception이 발생했을때 모듈 내부의 정보를 숨길 수 있다.

exception을 모아서 관리할 수 있다. -> 동일한 메시지로 응답이 가능하다.

예외 생성 비용을 절감할 수 있다.

-> stack trace는 에외가 발생하면, 예외 발생 위치를 제공하기 위해 스택에 메소드 리스트를 저장해서, 출력한다. 

try/catch 나 advice를 통해 필요에 따라 예외를 처리하면, stack trace의 생성에 비용을 소모하지 않고 메시지만 넘겨주는 등의 동작을 할 수 있다.

 

 

최종 정리

 

 

스프링의 예외 처리 방법은 크게 2가지이다.


-ExceptionHandler를 사용해서 특정 컨트롤러의 예외를 처리하는 방법이 있고

-ControllerAdvice를 통해서 전체적인 Controller에 대한 예외를  핸들링하는 방법이 있다.

 

 

ControllerAdvice

compoenent를 포함하고있고, 스프링 빈으로 등록이 된다.

@ExceptionHandler, @InitBinder, and @ModelAttribute 주로 이 3개를 사용을 한다.

 

주로 예외가 발생되면 DispatcherServlet에서 handlerExceptionResolver에게 빈을 위임해 예외를 해결하고, 처리하게 된다.

이를 통해 우리는 컨트롤러 단에서 터진 Excepton을 그에 맞는 요청이 가도록 처리할 수있다.

 

사용가능한 handlerExceptionResolver는 여러개가 있는데

 

SimpleMappingExceptionResolver -> 예외 클래스 이름과 에러의 이름을 매핑 시켜준다. 브라우저 application 오류페이지를 렌더링 할때 사용한다.

 

DefaulthandlerExceptionResolver -> Spring Mvc에서 발생한 예외를 해결, http상태코드를 매핑해준다.

ResponseStatusExceptionResolver -> @ResponseStatus 어노테이션을 사용해 예외를 해결하고 http 상태 코드를 매핑해준다.

ExceptionHandlerExceptionResolver -> Controller, ControllerAdvice클래스에서 @ExceptionHandler메소드를 호출해서 예외처리한다.

 

 

ControllerAdvice는 결국 DispatcherServlet이 에러를 캐치해 , 이 빈에게 위임되고 처리된다.

이 Resolver는 Controller에서 구현한 ExceptionHandler가있는지 검사, 컨트롤러어드바이스에서 해당 타입을 구현한게 있는지를 탐색한다. 구체적으로 구현한게있다면 우선순위를 높여서 처리를 맡긴다.

 

ControllerAdvice는 Controller를 보조하는 기능이다.

즉 지정한 컨트롤러에서 (아니라면 전체를 보고 있게 된다.) 선언된 메소드를 모두 주시하고있고

해당 메소드 레벨에서 발생하는 익셉션에 대한 처리를 맡는다.

ControllerAdvice는 ExceptionHandler를 사용해 예외 처리에 대한 공통 로직으로 묶고 관리할 수 도있고

 

InitBinder같이 들어오는 요청에 대한 추가적인 기능, 예를 들면, 날짜에 대한 포맷을 일관되게 변경한다.

 

 

해당 InitBidner를 사용하게 되면, Date객체에 대한 요청이 들어오게 되면, CustomEdit을 하여 데이터를 고르게 가공할 수 있다.

 

 

또한 ModelAttribue에 대한 사용을 할수있다.

 

ModelAttribute는 두가지 기능을 제공한다.

1. Controller 에서 받아오는 외부 request 객체를 모델로 받을 수 있도록 매핑해준다.

2. Controller 내에서 공통으로 사용할 모델을 정의할 수 있으며, View에 전달할 모델을 자동설정 해준다.

 

이게 뭔소리냐?

 

1번, 파라미터로 ModelAttribute를 작성하면 해당 파라미터와 모델에 대한 바인딩 작업을 해준다는 뜻이다.

2번 항상 메서드중 첫번째로 돈다(Controller에 있으면) 해당 메서드에 선언하면 그렇게 사용이 가능하다.

 

 

2번에 대한 내용이고, Model에 대한 작업을 한 메서드에서 공통 처리를 하면서 register()에 대한 메서드의 모델에도 msg가 들어가게 된다. 이걸 한 컨트롤러에서 작성하면 해당 클래스 하나이지만

ControllerAdvice를 통해 설정을 하면, 해당 컨트롤러들의 공통적으로 사용이 가능하다

즉 여러개에 대한 모델 처리 작업을 해준다.

 

 

마지막 정리!

DispatcherServlet에서 수행하다가 컨트롤러에서 예외가 발생한다

그러면 서블릿이 HandlerExceptionResolver에게 업무를 위임한다.

 

해당 리졸버는 컨트롤러, 컨트롤러 어드바이스를 돌면서 EwxceptionHandler에 대한 정의가 되어있는지

가장 구체화 된것의 우선순위를 매겨 처리를 맡긴다!

 

참고, ResponseStatus 에 대한 처리를 하는 예외처리기도 따로있는데

이건 Controller,ControllerAdvice를 처리해주는 예외 처리기보다 우선순위가 낮다

 

ex.

반응형

'Develop > [Spring]' 카테고리의 다른 글

[Springboot] logging 전략 관련 주저리...  (0) 2022.05.09
[Spring] HandlerInterceptor  (0) 2022.05.03
@SessionAttribute에 대해서  (0) 2022.04.29
[Spring] static 과 스프링 빈의 차이  (2) 2022.04.29
[Spring] ModelAttribute  (0) 2022.04.28