[Exception] 전역으로 예외처리 해보기

Ader(아더)·2022년 4월 28일
0

토비의 스프링 스터디를 진행하며 4장에서 더 알아보고 싶은 내용으로 위와 같은 주제를 정했다.
이제부터 자세히 알아보자!

1. DispatcherServlet에서의 예외처리

  • SpringBoot에서 예외처리를 하는 방식

  • doDispatch 메소드 내부에서 try/catch를 통해 예외처리를 하고 있음

  • 이후 processDispatchResult에서 Dispatch 결과 처리

    public class DispatcherServlet {
    	protected void doDispatch(...) throws Exception {
      	// ...
      	try {
        	ModelAndView mv = null;
        	Exception dispatchException = null;
    
        	try {
            	// Controller 로직 실행 (핸들러를 찾고, 해당 로직을 실행)
        	} catch (Exception ex) {
          	dispatchException = ex;
        	}
        	// Dispatch 결과 처리 (예외 처리도 여기서 진행)
        	processDispatchResult(...,dispatchException);
      	} catch {...}
      	// ...
    	}
    }

2. 스프링부트에서의 예외처리 방법들

  • @controller@ExceptionHandler 정의

    @ExceptionHandler(value = IllegalArgumentException.class)
     public ResponseEntity<ErrorResponse> handleIllegalArgumentException(IllegalArgumentException e) {
        ErrorResponse errorResponse = new ErrorResponse(e.getMessage());
    
        return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
    }
  • @ControllerAdvice / @RestControllerAdvice@ExceptionHandler 정의


3. HandlerExceptionResolver

  • HandlerExceptionResolver 내부의 resolveExceptionHandler() 메소드에서 어떤 ExceptionResolver를 선택하는지 결정하게 된다.
  • AnnotationMethodHandlerExceptionResolver
    • @ExceptionHandler 어노테이션을 찾아 예외처리
    • 특정 컨트롤러의 예외만 처리하고 싶을 때 유용하다
  • ResponseStatusExceptionResolver
@GetMapping(value = "/{id}")
public Foo findById(@PathVariable("id") Long id, HttpServletResponse response) {
    try {
        Foo resourceById = RestPreconditions.checkFound(service.findOne(id));

        eventPublisher.publishEvent(new SingleResourceRetrievedEvent(this, response));
        return resourceById;
     }
    catch (MyResourceNotFoundException exc) {
         throw new ResponseStatusException(
           HttpStatus.NOT_FOUND, "Foo Not Found", exc);
    }
}
  • 스프링 5부터 도입됨
    • 예외를 특정 응답코드로 변환해준다
    • 500에러 대신 의미있는 응답 상태를 사용하고자 할 때 유용
    • Exception 클래스에 @ResponseStatus를 붙이는 방식으로 구현
      • 당연히 @ExceptionHandler 위에도 붙일 수 있다
  • DefaultHandlerExceptionResolver
    • 위의 두 가지 ExceptionResolver에서 처리하지 못한 예외를 다룬다.
    • 스프링에서 발생하는 주요 예외를 처리하는 표준 예외처리 로직을 담고 있다.

4. HandlerInteceptor

  • 주의할 점
    • 실제 Handler단에 들어오기전에 HandlerInterceptor에서 발생할 수 있느 예외들은 위에서 구현한 전역 예외처리에 걸리지 않는다. 따라서 preHandle()로 따로 처리해주어야 한다.
    • @ControllerAdvice는 Handler(Controller) 단에서 발생하는 Exception을 @ExceptionHandler 어노테이션으로 처리하는 로직이라 ExceptionHandling 불가

5. 전역 예외 처리

  • @ExceptionHandler
  • @RestControllerAdvice
    • AOP 방식의 일종인 @RestControllerAdvice
    • @RestControllerAdvice = @ControllerAdivce + @ResponseBody
  • 제이와 저의 프로젝트를 소개하겠습니다!

6. 전역 예외 처리했을 때의 이점

  • 컨트롤러가 많아지면 예외처리에 대한 중복코드도 많아지고 유지보수가 어려워진다
  • 이를 해결하기 위해 전역에서 예외를 핸들링 할 수 있는 기술이 등장
  • 일종의 AOP 방식인 @RestControllerAdvice이 사용됨
profile
하루하루 성장하는 개발자

0개의 댓글