Common Response 왜 궁금했을까❓
- SSAFY 1학기 프로젝트에서 시간에 쫒겨 개발을 하다보니 기능 완성에만 집중하여 코드를 작성했다.
- 그 결과, 일관되지 못한 REST API Response를 받아오게 되고 Client 입장에서 혼란을 야기할 것이라 생각되었다.
- 이러한 문제점을 Common Response를 만들어 구조화 한다면 Client는 일관된 응답을 통해 일의 생산성과 안정성 측면이 향상될 것이라 생각되어 학습하고 Refactoring을 진행해보려 한다.
Common Response
- 이번 포스팅에서는 Success Response만 다루고 Error Response는 추후 포스팅에서 다루도록 하겠다.
- 우선, Common Response를 만들기 위해서 응답 구조를 어떻게 구성할지 고민해보았다.
- Client의 요청에 대한 데이터를 담기 위한 필드, 서버에서 어떠한 작업이 이뤄졌는지에 대한 설명이 담긴 필드, 응답에 대한 고유 코드가 담길 필드 이렇게 3가지를 구상했다.
@PutMapping
public ResponseEntity<Map<String, Object>> ModifyUser(@RequestBody UserDto dto) {
Map<String, Object> map = new HashMap<>();
try {
boolean res = service.modifyUser(dto);
map.put("resdata", res);
map.put("resmsg", "수정성공");
} catch (Exception e) {
map.put("resmsg", "수정실패");
map.put("resdata", e.getMessage());
}
ResponseEntity<Map<String, Object>> res = new ResponseEntity<>(map, HttpStatus.OK);
return res;
}
- 위 코드는 Refactoring을 하기 전에 코드로 map Collection을 이용하여 응답 구조를 구성했다.
- 이러한 코드의 문제점은 일관되지 못한 응답을 야기할 수 있다.
public class SuccessResponse<T> {
private final String code;
private final String message;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private final T data;
...
}
- 위의 문제점을 해결하기 위해 SuccessResponse 클래스를 만들어 CommonResponse 구조를 구성했다.
public enum SuccessCode implements ResponseCode {
LOGIN_SUCCESS(HttpStatus.OK, "로그인에 성공했습니다."),
CREATED_USER(HttpStatus.CREATED, "유저 정보를 생성했습니다."),
MODIFY_USER_SUCCESS(HttpStatus.OK, "유저 정보를 수정했습니다."),
;
private final HttpStatus httpStatus;
private final String message;
}
- 유지 보수를 쉽게 하기 위해 enum으로 SuccessCode를 구성하였다.
public static <T> ResponseEntity<Object> createSuccess(final SuccessCode successCode, final T data) {
return ResponseEntity.status(successCode.getHttpStatus())
.body(SuccessResponse.builder()
.code(successCode.name())
.message(successCode.getMessage())
.data(data)
.build()
);
}
public static <T> ResponseEntity<Object> createSuccess(final SuccessCode successCode) {
return ResponseEntity.status(successCode.getHttpStatus())
.body(SuccessResponse.builder()
.code(successCode.name())
.message(successCode.getMessage())
.build()
);
}
- SuccessCode를 받아 ResponseEntity를 생성하기 위해 createSuccess Method 2개를 만들었다.
- 데이터가 존재하는 응답도 있고 없는 응답도 있기 때문에 오버로딩을 하였다.
@PutMapping
public ResponseEntity<Object> ModifyUser(@RequestBody UserDto dto) {
service.modifyUser(dto);
return SuccessResponse.createSuccess(SuccessCode.MODIFY_USER_SUCCESS);
}
- Controller에서 다음과 같이 수정하여 코드의 가독성과 일관된 응답을 만들 수 있었다.