API 예외처리 - HandlerExceptionResolver
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 에러 상태로 나오게 된다.