[v3] REST API 를 위한 Exception 설정 -4

V3 으로 들어오며 REST API 로 전환 되었기 때문에 더이상 HTML 을 리턴할 수 없다.
HootJem's avatar
Sep 06, 2024
[v3] REST API 를 위한 Exception 설정 -4
V3 으로 들어오며 REST API 로 전환 되었기 때문에 더이상 HTML 을 리턴할 수 없다.
따라서 기존에 예외를 처리하던 Exception 클래스 수정과, 응답 형식 통일을 위한 Resp 클래스를 만들 것이다.
 

제네릭 타입이란?

notion image
@AllArgsConstructor @Data public class Resp<T> { private Integer status; private String msg; private T body; public static <B> Resp<?> ok(B body){ return new Resp<>(200, "성공", body); } public static Resp<?> fail(Integer status, String msg){ return new Resp<>(status, msg, null); } }
제네릭 타입이란 결정되지 않은 타입을 파라미터로 처리하고, 실제 사용될 때 타입을 지정하는 것이다.
  • new 연산 시 타입의 제어권을 개발자가 갖게 된다. 개발자가 특정 타입을 지정하지 않으면 컴파일러가 오류를 발생시키기 때문에, 제네릭을 사용함으로써 타입 안정성을 보장할 수 있다.
  • 개발자가 new 할 수 없는 경우: 예를 들어, 어떤 상황에서는 실제 타입이 Object로 처리되어, 이를 다시 원하는 타입으로 변환하기 위해 다운 캐스팅을 해야 한다.
  • 개발자가 new 할 수 있는 경우: 반대로, 개발자가 new 연산을 사용할 수 있을 때는 제네릭 타입 <T>를 사용하여, 명시적으로 원하는 타입을 지정할 수 있다.
 

응답 상태 코드 처리

@GetMapping("/test/v5") public ResponseEntity<?> testV5(){ // 1. ResponseBody 생략, 상태코드를 넣을 수 있다. return new ResponseEntity<>(Resp.fail(404, "찾을 수 없습니다"), HttpStatus.NOT_FOUND); }
ResponseEntity를 사용하면 HTTP 상태 코드와 응답 데이터를 함께 관리할 수 있다.

@ResponseBody 사용

@GetMapping("/test/v4") public @ResponseBody Resp testV4(HttpServletResponse response){ response.setStatus(404); return Resp.fail(404, "유저를 찾을 수 없습니다"); }
notion image
@ResponseBody: 이 애노테이션은 리턴 값을 그대로 HTTP 응답의 본문으로 변환한다.
setStatus 를 사용해야 하여 상태 코드를 직접 숫자로 지정한다. 개발 시 실수할 가능성이 존재함.

ResponseEntity 사용

@GetMapping("/test/v5") public ResponseEntity<?> testV5(){ // 1. ResponseBody 생략, 상태코드를 넣을 수 있따. return new ResponseEntity<>(Resp.fail(404, "찾을 수 없습니다"), HttpStatus.NOT_FOUND); }
notion image
ResponseEntity<?>: 이 방식은 응답 본문뿐만 아니라 HTTP 상태 코드와 헤더를 명시적으로 설정할 수 있는 방식이다.
HttpStatus 가 상태 코드와 본문을 지원하기 때문에 실수를 방지할 수 있고 더 안전하다.
 
notion image
api 요청 해결 핸들러
notion image
400 → 프론트엔드 개발자가 확인할 수 있도록
HttpStatus.BAD_REQUEST 리스폰스 헤더에 들어가는거
 
@Deprecated DESTINATION_LOCKED(421, HttpStatus.Series.CLIENT_ERROR, "Destination Locked"), UNPROCESSABLE_ENTITY(422, HttpStatus.Series.CLIENT_ERROR, "Unprocessable Entity"), LOCKED(423, HttpStatus.Series.CLIENT_ERROR, "Locked"), FAILED_DEPENDENCY(424, HttpStatus.Series.CLIENT_ERROR, "Failed Dependency"), TOO_EARLY(425, HttpStatus.Series.CLIENT_ERROR, "Too Early"), UPGRADE_REQUIRED(426, HttpStatus.Series.CLIENT_ERROR, "Upgrade Required"), PRECONDITION_REQUIRED(428, HttpStatus.Series.CLIENT_ERROR, "Precondition Required"), TOO_MANY_REQUESTS(429, HttpStatus.Series.CLIENT_ERROR, "Too Many Requests"), REQUEST_HEADER_FIELDS_TOO_LARGE(431, HttpStatus.Series.CLIENT_ERROR, "Request Header Fields Too Large"), UNAVAILABLE_FOR_LEGAL_REASONS(451, HttpStatus.Series.CLIENT_ERROR, "Unavailable For Legal Reasons"), INTERNAL_SERVER_ERROR(500, HttpStatus.Series.SERVER_ERROR, "Internal Server Error"), NOT_IMPLEMENTED(501, HttpStatus.Series.SERVER_ERROR, "Not Implemented"), BAD_GATEWAY(502, HttpStatus.Series.SERVER_ERROR, "Bad Gateway"), SERVICE_UNAVAILABLE(503, HttpStatus.Series.SERVER_ERROR, "Service Unavailable"), GATEWAY_TIMEOUT(504, HttpStatus.Series.SERVER_ERROR, "Gateway Timeout"), HTTP_VERSION_NOT_SUPPORTED(505, HttpStatus.Series.SERVER_ERROR, "HTTP Version not supported"), VARIANT_ALSO_NEGOTIATES(506, HttpStatus.Series.SERVER_ERROR, "Variant Also Negotiates"), INSUFFICIENT_STORAGE(507, HttpStatus.Series.SERVER_ERROR, "Insufficient Storage"), LOOP_DETECTED(508, HttpStatus.Series.SERVER_ERROR, "Loop Detected"), BANDWIDTH_LIMIT_EXCEEDED(509, HttpStatus.Series.SERVER_ERROR, "Bandwidth Limit Exceeded"), NOT_EXTENDED(510, HttpStatus.Series.SERVER_ERROR, "Not Extended"), NETWORK_AUTHENTICATION_REQUIRED(511, HttpStatus.Series.SERVER_ERROR, "Network Authentication Required");
이거 참고해서 액셉션 숫자 처리(HttpStatus 클릭해 보면 들어가진다.)
 
@GetMapping("/test/v6") public ResponseEntity<?> testV6(){ // throw new ExceptionApi404("페이지를 찾을 수 없습니다."); }
notion image
설정한 json 형식 예외처리 작동 확인.
 

이제 다음 포스팅에서 댓글 삭제 기능 구현을 해 볼것이다.
 
SpringBoot 블로그 만들기 - v3 시리즈 1. https://inblog.ai/hj/v3-시작-27809 (개발환경 설정 및 post 맨 이용한 api 테스트) 2. https://inblog.ai/hj/v3-springboot-블로그-만들기-2-28708 (댓글 엔티티 생성 및 양방향 매핑) 3. https://inblog.ai/hj/v3-springboot-블로그-만들기-3-28793 (댓글 조회하기 완료) 4. https://inblog.ai/hj/v3-rest-api-를-위한-exception-설정-28848 (REST API 위한 익셉션 핸들러 구현) 5. https://inblog.ai/hj/v3-springboot-블로그-만들기5-28859 (댓글 삭제 기능 구현)
 
Share article

[HootJem] 개발 기록 블로그