ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • API 예외처리 - HandlerExceptionResolver
    스프링/스프링 MVC 패턴 2023. 3. 5. 14:30

    HTML이 아니라 API에서 예외를 처리해야할 상황이 있다. 그 때는 HTML처럼 뷰 템플릿을 보여주는 것이 아니라 Json 방식으로 사용자에게 전달해야한다.

     

    @Slf4j
    @RestController
    public class ApiExceptionController {
        @GetMapping("/api/members/{id}")
        public MemberDto getMember(@PathVariable("id") String id) {
    
            if (id.equals("ex")) {
                throw new RuntimeException("잘못된 사용자");
            }
            if (id.equals("bad")) {
                throw new IllegalArgumentException("잘못된 입력 값");
            }
    
            return new MemberDto(id, "hello " + id);
        }
    
        @Data
        @AllArgsConstructor
        static class MemberDto {
            private String memberId;
            private String name;
        }
    }

    http://localhost:8080/api/members/bad 로 연결하면 illegalArgumentException의 예외가 발생할 것이다.

     

    예외를 Json 방식으로 사용자에게 보여준다.

    예상했던 대로 500 서버 에러가 발생했다.

     

     

    에러는 예전 게시글에서 썼던 것처럼 400에러, 500에러 등 상황에 맞는 에러를 반환해준다. 하지만 우리가 사용자에게 다른 에러페이지를 보여주고 싶거나 특별한 예외처리를 하고 싶을 때에는 HandlerExceptionResolver를 사용하면 된다. 

     

     

    @Slf4j
    public class MyHandlerExceptionResolver implements HandlerExceptionResolver {
        @Override
        public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
    
            try {
                if (ex instanceof IllegalArgumentException) {
                    log.info("IllegalArgumentException resolver to 400");
                    response.sendError(HttpServletResponse.SC_BAD_REQUEST, ex.getMessage());
                    // 여기서 에러를 받아들이고 400에러를 내보낸다.
    
                    return new ModelAndView();
                }
    
            } catch (IOException e) {
                log.error("resolver ex", e);
            }
    
            return null;
        }
    }

    주석이 있는 윗 줄에서 response.sendError로 400에러를 내보낸다. illegalArgumentException 에러가 나오게 된다면 그 에러를 삼키고 400에러를 sendError로 내보낸다는 것이다. 만약 특정 에러가 발생하지 않는다면 그냥 null 값이 리턴되고, 위에처럼 에러가 발생하면 ModelAndView를 리턴한다.

    new ModelAndView를 리턴했다. 즉, 빈 ModelAndView를 반환했는데 이처럼 빈 객체를 반환하면 뷰를 렌더링하지 않고 정상 흐름으로 서블릿이 리턴된다.

    물론 ModelAndView에 값을 채워서 예외에 따른 새로운 오류 화면 뷰를 렌더링해서 고객에게 제공할 수도 있다.

     

     

     

    extendHandlerExceptionResolvers 메서드

    WebConfig에 추가

    @Override
    public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
        resolvers.add(new MyHandlerExceptionResolver());
    }

    위의 코드들을 사용하려면 WebConfig에 등록해줘야 한다. 스프링에서 제공하는 메서드를 오버라이드 한 다음 우리가 만든 ExceptionResolver를 add로 추가해주면 된다.

     

     

    분명 bad라는 url로 들어갔기 때문에 illegalArgumentException이 발생하지만 400 에러 상태로 나오게 된다.

     

Designed by Tistory.