api로써 반환할 값은 공통의 스펙으로 반환하도록 정의하는 것이 좋다. 그래서 우선 정상 처리의 대한 반환 객체를 정의해주려고 한다.
@Getter
public class CommonApi<T> {
private String code;
private String msg;
private T data;
public CommonApi(@NonNull String code,@NonNull String msg,@NonNull T data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public CommonApi(@NonNull CommonEnum e,@NonNull T data) {
this.code = e.getCode();
this.msg = e.getMsg();
this.data = data;
}
}
CommonApi
공통의 객체를 정의해주었다.
@Getter
public enum CommonEnum {
OK("200", "정상실행"),
FAIL("500", "알수 없는 에러");
;
CommonEnum(String code, String msg) {
this.code = code;
this.msg = msg;
}
private String code;
private String msg;
}
CommonEnum
자주 사용될 코드나 메세지를 Enum으로 정의해두면 유지보수에 편하기 때문에 미리 정의해두었다.
@RestController
public class TestController {
@GetMapping("/test")
public ResponseEntity<CommonApi> test(){
CommonApi api = new CommonApi(CommonEnum.OK, new TestObject());
return ResponseEntity.ok(api);
}
@Data
public class TestObject{
private Integer idx = 1;
private String name = "test1";
}
}
다음과 같이 TestController를 정의하고 요청해보자.
다음과 같이 내가 예상했던 모양으로 반환해준다. 초반엔 귀찮을 수도 있지만 이렇게 설정해두면 어떤 api도 동일한 스펙으로 반환할 수 있기 때문에 미리 정의해주는게 좋다.
정상 실행만 되면 좋겠지만 우리는 항상 에러를 대비해야하고 가장 좋은 에러는 개발자가 예상한 에러이다. 예상된 에러는 개발자가 핸들링을 할 수 있기 때문인데. api에서 Exception Handling을 구현해보자.
@AllArgsConstructor
@NoArgsConstructor
@Getter
public class CommonException extends RuntimeException{
private String code;
private String msg;
private HttpStatus status;
public CommonException(CommonExceptionEnum e) {
this.code = e.getCode();
this.msg = e.getMsg();
this.status = e.getStatus();
}
}
먼저 우리가 예상된 Exception을 던지기 위해 CommonException을 구현했다.
@RestController
public class TestController {
...
@GetMapping("/exception")
public ResponseEntity<CommonApi> exce() throws Exception {
CommonApi api = new CommonApi(CommonEnum.OK, new TestObject());
//예상된 Exception 발생! 400으로 반환해보자
if(true) throw new CommonException(CommonExceptionEnum.BAD_REQUEST);
return ResponseEntity.ok(api);
}
}
/exception
으로 요청 시 CommonException으로 던지고
@Getter
public enum CommonExceptionEnum {
BAD_REQUEST("400","잘못된 요청", HttpStatus.BAD_REQUEST),
;
CommonExceptionEnum(String code, String msg, HttpStatus status) {
this.code = code;
this.msg = msg;
this.status = status;
}
private String code;
private String msg;
private HttpStatus status;
}
enum으로 미리 정의해놨다.
@RestControllerAdvice
public class CommonAdvice {
@ExceptionHandler(CommonException.class)
public ResponseEntity commonExceptionAdvice(CommonException ce){
ErrorApi error = new ErrorApi(ce.getCode(), ce.getMsg());
return ResponseEntity.status(ce.getStatus()).body(error);
}
}
그 후 advice를 지정해주는데 우선 테스트 용도로 다음과 같이 작성했다.
@Getter
@AllArgsConstructor
public class ErrorApi {
private String code;
private String msg;
}
ErrorApi
는 다음과 같이 정의해주었다.
api는 error의 스펙도 동일하게 반환해줘야하므로 다음과 같이 정의했다. 이런 형식을 선택한 이유는
네이버와 카카오의 api 에러 메세지 반환 형식을 참고했다.
실제 테스트를 해보면 정상적으로 예상된 에러를 반환하며 Http 상태 코드 또한 우리가 지정한 400으로 반환하는 것을 확인할 수 있다.