스프링/스프링 MVC 패턴

API 예외처리 - HandlerExceptionResolver

chanhee01 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 에러 상태로 나오게 된다.