스프링

API 예외처리-1

winwin-k9 2023. 1. 26. 14:17

HTML페이지는 4xx, 5xx와같은 오류 페이지만 준비해놓으면 대부분 문제 해결이 가능하다.
그러나 API는 각 오류 상황에 맞는 오류 응답스펙을 정하고 JSON으로 데이터를 내려주어야 하기때문에 고민해야 될것이 많다.

API를 요청했는데, 정상의 경우 API로 JSON 형식으로 데이터가 정상 반환된다.
그런데 오류가 발생하면 우리가 미리 만들어둔 오류 페이지 HTML이 반환된다.

JSON으로 원하는 형식에 맞추어 해당 정보를 주어야 한다.

 

@Component
public class WebServerCustomizer implements WebServerFactoryCustomizer<ConfigurableWebServerFactory> {
    @Override
    public void customize(ConfigurableWebServerFactory factory) {

        ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/error-page/404");
        ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error-page/500");

        ErrorPage errorPageEx = new ErrorPage(RuntimeException.class, "/error-page/500");

        factory.addErrorPages(errorPage404, errorPage500, errorPageEx);
    }
}

에러 처리의 설정이다.

오류의 종류에 따라서 해당 url로 이동하도록 한다.

 

@RequestMapping("/error-page/500")

@RequestMapping(value = "/error-page/500", produces = MediaType.APPLICATION_JSON_VALUE)

같은 URL이지만, 해당 요청이 JSON이면 아래의 쪽이 더 우선 순위를 가진다.

 

@RequestMapping(value = "/error-page/500", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Map<String, Object>> errorPage500Api(
            HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<>();
        Exception ex = (Exception) request.getAttribute(ERROR_EXCEPTION);
        result.put("status", request.getAttribute(ERROR_STATUS_CODE));
        result.put("message", ex.getMessage());

        Integer statusCode = (Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
        return new ResponseEntity<>(result, HttpStatus.valueOf(statusCode));
    }

RequestDispatcher는 오류와 상태코드를 둘다 가져올 수 있다.

 

이제 여기서 오류가 발생하면

{
    "code": "EX",
    "message": "내부 오류"
}

다음과 같은 원하는 JSON형태를 가져올 수 있다.

 

해당 URL이 실행되면 throw로 실행된 에러가 터지고, 커스터마이징에 따라서 

/error-page/500으로 이동한다.

이때 HttpAccept가 Json이므로 우리가 작성한 에러 로직이 수행된다.

그래서 status코드와 message를 가진 Json이 반환된다. 

 

그런데 아무것도 설정하지 않아도 스프링이 기본으로 제공하는 매커니즘만으로 에러 처리가 가능하다.

@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class BasicErrorController extends AbstractErrorController {

에러처리를 설정한 WebServerCustormizer를 지우고 실행해보자.

 

에러가 발생하면 sevlet컨테이너까지 올라가면 스프링부트가 기본에러페이지로 정한 /error가 호출된다.

즉 BasicErrorController로 들어오게 된다.

 

BasicErrorController가 Json형태의 에러를 내려주게 된다.

 

 

 

728x90