일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 프록시
- 백준
- 티스토리챌린지
- 다형성
- objecterror
- ocp
- JSON
- 의존관계
- html form
- 코드트리
- fielderror
- 참조변수
- 코드트리조별과제
- 서블릿
- java
- 테스트코드
- 스프링컨테이너
- equals()
- @configuration
- 오블완
- 추상클래스
- 인터페이스
- HttpServletResponse
- http 메시지 컨버터
- 김영한
- DI
- 오버라이딩
- 스프링
- 코딩테스트
- 싱글톤
- Today
- Total
minOS
API 예외 처리 - 시작 본문
API 예외 처리 - 시작
목표
API의 경우에는 생각할 내용이 더 많다. 오류 페이지는 단순히 고객에게 오류 화면을 보여주고 끝이지만, API는
각 오류 상황에 맞는 오류 응답 스펙을 정하고, JSON으로 데이터를 내려주어야 한다.
앱에서 앱 , 기업 간 시스템 통신하기때문에지금부터 API의 경우 어떻게 예외 처리를 하면 좋은지 알아보자.
API도 오류 페이지에서 설명했던 것 처럼 처음으로 돌아가서 서블릿 오류 페이지 방식을 사용해보자.
WebServerCustomizer 주석 풀고 다시 동작@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); } }
`WebServerCustomizer` 가 다시 사용되도록 하기 위해 `@Component` 애노테이션에 있는 주석을 풀자
이제 WAS에 예외가 전달되거나, `response.sendError()` 가 호출되면 위에 등록한 예외 페이지 경로가 호출된다.
ApiExceptionController - API 예외 컨트롤러
import lombok.AllArgsConstructor; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @Slf4j @RestController public class ApiExceptionController { @GetMapping("/api/members/{id}") public MemberDto getMember(@PathVariable("id") String id){ if (id.equals("ex")){ throw new RuntimeException("잘못된 사용자"); //500 html 반환 문제를 해결하려면 오류 페이지 컨트롤러도 JSON응답 할 수 있도록 수정해야한다. } return new MemberDto(id,"hello "+id); } @Data @AllArgsConstructor static class MemberDto{ private String memberId; private String name; } }
postman으로 api 실행오류가 발생하면
html이 반환된다. 이것은 기대한 바가 아니다. 클라이언트는 정상 요청이든, 오류 요청이든 JSON이 반환되기를 기대한다. 웹 브라우저가 아닌 이상 HTML을 직접 받아서 할 수 있는 것은 별로 없다.문제를 해결하려면 오류 페이지 컨트롤러도 JSON 응답을 할 수 있도록 수정해야 한다.
ErrorPageController - API 응답 추가
@RequestMapping(value = "/error-page/500", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<Map<String,Object>> errorPage500Api( HttpServletRequest request,HttpServletResponse response){ log.info("API errorPage 500"); 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)); }
`produces = MediaType.APPLICATION_JSON_VALUE` 의 뜻은 클라이언트가 요청하는 HTTP Header의
`Accept` 의 값이 `application/json` 일 때 해당 메서드가 호출된다는 것이다. 결국 클라어인트가 받고 싶은 미디어
타입이 json이면 이 컨트롤러의 메서드가 호출된다.
응답 데이터를 위해서 `Map` 을 만들고 `status` , `message` 키에 값을 할당했다. Jackson 라이브러리는 `Map` 을
JSON 구조로 변환할 수 있다.
`ResponseEntity` 를 사용해서 응답하기 때문에 메시지 컨버터가 동작하면서 클라이언트에 JSON이 반환된다.
포스트맨을 통해서 다시 테스트 해보자.
HTTP Header에 `Accept` 가 `application/json` 인 것을 꼭 확인하자.
HTTP Header에 `Accept` 가 `application/json` 이 아니면, 기존 오류 응답인 HTML 응답이 출력되는 것을 확인
할 수 있다.
'TIL > 김영한의 스프링 MVC 2편 - 백엔드 웹 개발 핵심 기술' 카테고리의 다른 글
API 예외 처리 - HandlerExceptionResolver 시작 (7) | 2024.10.07 |
---|---|
API 예외처리 - 스프링 부트 기본 오류 처리 (1) | 2024.10.03 |
스프링 부트 - 오류 페이지 (0) | 2024.10.01 |
서블릿 예외 처리 - 필터 ,인터셉터 (1) | 2024.10.01 |
서블릿 예외 처리 - 시작 ,오류 화면 제공 , 오류 페이지 작동 원리 (1) | 2024.10.01 |