Spring Boot를 이용한 RESTful Web Services 개발 #16 WebRequest와 Spring AOP를 이용한 Exception Handling

Jake Seo·2021년 9월 16일
1

Spring-boot-restful

목록 보기
16/17

WebRequest 이용해보기

@Slf4j
@RestControllerAdvice
@RequiredArgsConstructor
public class CommonControllerAdvice extends ResponseEntityExceptionHandler {

    private final MessageSource messageSource;

    @ResponseStatus(value = HttpStatus.NOT_FOUND)
    @ExceptionHandler(UserNotFoundException.class)
    public ExceptionResponse notFoundExceptionHandler(UserNotFoundException e, WebRequest request) {
        log.error("[Not Found Exception] :", e);
        return new ExceptionResponse(
                HttpStatus.NOT_FOUND.value(),
                messageSource.getMessage("error.user_not_found", new Object[]{e.getUserId()}, null),
                request.getDescription(false)
        );
    }
}

위와 같이 예외를 처리할 때, WebRequest 또한 받을 수 있는데, 사용자가 요청한 정보에 대한 내용을 다시 한번 응답으로 돌려줄 때 유용하다.

ResponseEntityExceptionHandler

CommonControllerAdviceResponseEntityExceptionHandler를 추가하면 해당 인터페이스에 있는 메소드를 구현하여 많은 예외를 처리해볼 수 있다.

공식문서에 가보면 어떤 arguments들을 활용할 수 있는지에 대해 상세히 나와있다. HttpServletRequest와 같은 타입도 활용 가능하다.

CommonControllerAdvice 수정해보기

@Slf4j
@RestControllerAdvice
@RequiredArgsConstructor
public class CommonControllerAdvice extends ResponseEntityExceptionHandler {

    private final MessageSource messageSource;

    @ResponseStatus(value = HttpStatus.NOT_FOUND)
    @ExceptionHandler(UserNotFoundException.class)
    public ExceptionResponse notFoundExceptionHandler(UserNotFoundException e, HttpServletRequest request) {
        log.error("[Not Found Exception] :", e);
        return new ExceptionResponse(
                HttpStatus.NOT_FOUND.value(),
                messageSource.getMessage("error.user_not_found", new Object[]{e.getUserId()}, null),
                request.getRequestURI()
        );
    }
}
  • UserString으로 description이라는 것을 추가하고, 거기에 URI 경로까지 출력해보도록 했다.

결과

Spring AOP를 이용하여 모든 에러에 대한 기본 예외 처리해보기

@Slf4j
@RestControllerAdvice
@RequiredArgsConstructor
public class CommonControllerAdvice extends ResponseEntityExceptionHandler {

    private final MessageSource messageSource;

    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(Exception.class)
    public ExceptionResponse allExceptionsHandler(Exception e, HttpServletRequest request) {
        log.error("[Exception] :", e);
        return new ExceptionResponse(
                HttpStatus.INTERNAL_SERVER_ERROR.value(),
                messageSource.getMessage("error.server", null, null),
                request.getRequestURI()
        );
    }

위와 같이 모든 예외의 상위 예외인 Exception.class의 예외가 터졌을 때, 사용할 공통 예외처리 부분을 만들어보았다.

UserController에 예외용 메소드 하나 만들어보기

    @GetMapping("/exception")
    public void exception(){
        throw new RuntimeException();
    }

무조건 RuntimeException을 던지는 예외용 메소드를 하나 만들었다.

실행 결과

의도한대로 잘 작동한다.

의문점

그런데 혹시 Exception.class를 예외처리하도록 설정했으니, 이전에 작성한 UserNotFoundException.class에 대해서도 기본 예외처리가 적용되는 게 아닐까?

UserNotFoundException 예외 실행 결과

이전에 작성한 UserNotFoundException.class에서는 의도한대로 잘 처리 된다. 그 이유는 스프링이 최대한 구체적인 것을 우선순위로 두기 때문이다.

UserNotFoundException.classException.class의 하위 클래스는 맞지만, 훨씬 더 구체적이기 때문에 우선순위가 높다.

profile
풀스택 웹개발자로 일하고 있는 Jake Seo입니다. 주로 Jake Seo라는 닉네임을 많이 씁니다. 프론트엔드: Javascript, React 백엔드: Spring Framework에 관심이 있습니다.

0개의 댓글