본문 바로가기

BackEnd/Spring

Controller 작성시 예외 상황

반응형

Controller를 작성할 때 예외 상황을 고려하면 처리해야 하는 작업이 엄청나게 늘어날 수 밖에 없다. 154p


스프링 MVC에서는 이러한 작업을 다음과 같은 방식으로 처리할 수 있다.


1) @ControllerAdvice와 @ExceptionHandler를 이용한 처리


@ControllerAdvice를 선언하면 웹어플리케이션의 특정 익셉션들을 공통적으로 핸들링 할 수 있다.


@ControllerAdvice는 뒤에서 배우게 되는 AOP(Aspect-Oriented-Prograinming)를 이


용하는 방식이다. AOP에 대해서는 별도의 파트에서 설명하겠지만, 간단히 언급하자면


핵심적인 로직은 아니지만 프로그램에서 필요한 '공통적인 관심사(cross-concern)는 분


리’하자는 개념이다. Controller를 작성할 때는 메서드의 모든 예외사항을 전부 핸들


링해야 한다면 중복적이고 많은 양의 코드를 작성해야 하지만, AOP 방식을 이용하면 공


통적인 예외사항에 대해서는 별도로 @ControllerAdvice를 이용해서 분리하는 방식이다.


@ControllerAdvice는 해당 객체가 스프링의 컨트롤러에서 발생하는 예외를 처리하는 존재임을 


명시하는 용도로 사용하고,


@ExceptionHandler는 해당 메서드의 예외 타입을 처리한다는 것을 의미.


예 : 


@ExceptionHandler(Exception.class)

public String except(Exception ex, Model model) {

}


Exception.class를 지정하였으므로 모든예외에 대한 처리가 except() 메서드만을 이용해서 처리할 수 있다


만일 특정한 타입의 예외를 다루고 싶다면 Exception.class 대신에 구체적인 예외의 클

래스를 지정해야 한다


2) 404에러페이지 


WAS의 구동 중 가장 흔한 에러와 관련된 HTTP 상태 코드는 ’404’와 ’500’ 에러 코드다. 


500 메시지는 'Internal Server Error’이므로 @ExceptionHandler를 이용해서


처리되지만, 잘못된 URL을 호출할 때 보이는 404 에러 메시지의 경우는 조금 다르게 처


리하는 것이 좋다. 서블릿이나 JSP를 이용했던 개발 시에는 web.xml을 이용해서 별도의 에러 페


이지를 지정할 수 있다. 하지만 에러 발생 시 추가적인 작업을 하기는 어렵기 때문에 스프링을 이


용해서 404와 같이 WAS 내부에서 발생하는 에러를 처리하는 방식을 알아두는 것이 좋다.


스프링 MVC의 모든 요청은 DispatcherServlet을 이용해서 처리되므로 404 에러도 같


이 처리할 수 있도록 web.xml을 수정해야한다.


왜냐하면 잘못된 URL을 호출할 때 DispatcherServlet을 이용해처 바로 처리를 하면


예외 처리기를 호출하지 않고 오류 응답을 보내는것 같다.


즉, 서블릿의 404 에러처럼 DispatcherServlet에서 바로 처리해버리는 익셉션들의 경우는 


@ControllerAdvice 까지 전달되지 않고 그 전에 DispatcherServlet에 의해 처리된다.


그래서 보통은 404 에러 페이지가 뜨게 된다.


그래서 web.xml을 수정해야한다.


<init-param>

      <param-name>throwExceptionIfNoHandlerFound</param-name>

      <param-value>true</param-value>

</init-param>


        404 에러 처리를 위해 404에러 페이지로 넘기지 않고,익셉션을 발생 시키는 설정


이렇게 설정을 추가해주면 이제 @ControllerAdvice에서 에러 핸들링을 해줄수 있다.

  @ExceptionHandler(NoHandlerFoundException.class)

@ResponseStatus(HttpStatus.NOT_FOUND)

public String handle404(NoHandlerFoundException ex) {


return "error/404errorPage";

}



웹개발자를 위한 스프링 4.0 349페이지 


1) @ExceptionHandler을 이용한 익셉션 처리


컨트롤러 클래스에 @ExceptionHandler을 적용하면 해당 컨트롤러에서 발


생한 익셉션만을 처리한다.


스프링 MVC는 컨트롤러에서 익셉션이 발생하면 HandlerExceptionResolver에 처


리를 위임한다. HandlerExceptionResolver에는 여러 종류가 존재하는데


MVC 설정 mvc:annotation-driven 태그나 @EnableWebMvc 애노테이션을 사용할 경


우 내부적으로 ExceptionHandlerExceptionResolver를 등록한다. 이 클래스는


@ExceptionHandler 애노테이션이 적용된 메서드를 이용해서 익셉션을 처리하는 기능을 제공


하고 있다.


MVC 설정을 사용할 경우 다음의 순서대로 HandlerExceptionResolver를 사용하게 된다.


1. ExceptionHandlerExceptionResolver : 발생한 익셉션과 매칭되는 @Exception

Handler 메서드를 이용해서 익셉션을 처리한다.


2. DefaultHandlerExceptionResover : 스프링이 발생시키는 익셉션에 대한 처리. 

예를들어,요청 URL에 매핑되는 컨트롤러가 없을 경우 NoHandlerFoundException이 발

생하는데,이 경우 DefaultHandlerExceptionResolver는 404 에러 코드를 응답으로

전송한다.


3. ResponseStatusExceptionResolver : 익셉션 타입에 @ResponseStatus 애노테이

션이 적용되어 있을 경우,@ResponseStatus 애노테이션의 값을 이용해서 응답 코드를

전송한다.


DispatcherServlet은 익셉션이 발생하면,가장 먼저 ExceptionHandlerExceptionResolver 


에 익셉션 처리를 요청한다. 만약 익셉션에 매핑되는 @ExceptionHandler 메서드가 존재


하지 않으면, ExceptionHandlerExceptionResolver는 익셉션을 처리하지 않는다. 익셉션


이 처리되지 않으면 그 다음 차례인 DefaultHandlerExceptionResolver를 사용하고,여기서


도 익셉션을 처리하지않으면 마지막으로 ResponseStatusExceptionResolver사용한다.


마지막 차례인 ResponseStatusExceptionResolver에서도 익셉션을 처리하지 않으면,컨테


이너가 익셉션을 처리하도록 만든다.


2) @ControllerAdvice 애노테이션을 이용한 공통 익셉션 처리


컨트롤러 클래스에 @ExceptionHandler을 적용하면 해당 컨트롤러에서 발생한 익셉션만을 처리한


다. 그런데,다수의 컨트롤러에서 동일 타입의 익셉션을 발생시킬 수 있고, 이때 익셉션 처리 코드


가 동일하다면 어떻게 해야 할까? 각 컨트롤러 클래스마다 익셉션 처리 메서드를 구현하는 것은 불


필요한 코드 중복을 발생시킨다.


이렇게 여러 컨트롤러에서 동일한 익셉션을 발생시킬 경우,@ControllerAdvice 애노테


이션을 이용해서 익셉션 처리 메서드 중복을 없앨 수 있다. 


@ControllerAdvice 애노테이션이 적용된 클래스는 지정한 범위의 컨트롤러에서 공통


으로 사용될 설정을 지정할 수 있다. 그러면 @ ControllerAdvice 클래스에 있는 @ 


ExceptionHandler 메서드를 통해서 익셉션을 처리하게 된다. 그리고


@ Controller Advice 적용 클래스가 동작하려면 해당 클래스를 스프링에 빈으로 등록해


주어야 한다.


@ Controller Advice 클래스에 있는  ExceptionHandler 메서드와 컨트롤러 클래스에


있는 ©ExceptionHandler 메서드 중 우선순위를 갖는 것은 컨트롤러 클래스에 적용된


©ExceptionHandler 클래스이다. 즉, 컨트롤러의 메서드를 실행하는 과정에서 익셉션


이 발생하면 다음의 순서로 익셉션을 처리할 ©ExceptionHandler 메서드를 찾는다.


© 같은 컨트롤러에 위치한 ©ExceptionHandler 메서드 중 해당 익셉션을 처리할 수 있는 메


서드를 검색


© 같은 클래스에 위치한 메서드가 익셉션을 처리할 수 없을 경우, @ControllerAdvice 클래


스에 위치한 @ExceptionHandler 메서드를 검색


3) @ResponseStatus을 이용한 익셉션 처리


@ResponseStatus 애노테이션은 익셉션 자체에 에러 응답 코드를 설정하고 싶을 때 사


용한다. 




반응형

'BackEnd > Spring' 카테고리의 다른 글

스프링 mvc 프로젝트의 기본구성  (0) 2020.02.10
http 에러코드  (0) 2020.02.10
컨트롤러의 리턴타입  (0) 2020.02.09
Autowired 와 Resource 와 lnject 어노테이션정리  (0) 2020.02.09
스프링 컨테이너 계층 구조  (0) 2020.02.08