Spring boot
ResponseEntity Code Convention
Subi
2023. 7. 26. 10:53
ResponseEntity를 Custom 하여 ResopnseResult 사용하여 이에 맞는 Convention 을 작성합니다.
Template
ResponseResult 의 Template은 다음을 유지한다.
- List Template
- contents : Parameter Contents (List)
- pageable : Paging 정보
- pageSize : 페이지 사이즈 (int)
- pageNumber : 현재 페이지 번호 (int) / 1 부터 시작
- totalElement : Total Contents Size (Long)
{
"code": int,
"message": "string",
"content": [
{list1 : data1},
{list2 : data2}
],
"pageable": {
"pageSize": int,
"pageNumber": int,
"totalElement": Long
}
}
- Single Templte
- contents : Parameter Contents (Object)
{
"code": int,
"message": "string",
"content": {
parameter1 : data1 ,
parameter2 : data2
}
- Create Templte , Update Templte, Delete Templte
- contents : Parameter Id (Long) / 실행을 처리한 ID
{
"code": int,
"message": "string",
"content": id(Long)
}
ResponseStatus
- ResponseResult 에서 사용하기 위한 Response의 상태값을 관리하는 Enum Class
public enum ResponseStatus {
SUCCESS(200, "SUCCESS"),
CREATE(201, "SUCCESS CREATED"),
NO_CONTENTS(204, "SUCCESS NO_CONTENTS");
private final int code;
private final String message;
ResponseStatus(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}
Enum의 변수로 code, message 값을 가지고 Service에서 값을 넣어 사용한다.
- 기본 code 의 값은 Http.Status의 값을 사용한다.
- 추가가 필요할 시 다음의 형태를 유지한다.
- Enum 의 Name 은 대문자와 언더바( _ ) 를 사용한다.
- code 의 값 중 200번 대의 값은 Http 통신이 성공했을 시에 대한 값으로 유지한다.
- 특이한 별도의 Case를 추가 할 시 기존 Http.stauts 에서 사용하지 않는 값으로 추가한다.
Service
- Service 에서는 Repository에서 return 받은 값을 ResponseResult 로 retrun 시켜준다.
- List Data
public ResponseResult<Page<EntityDTO>> listEntity (EntitySearchCondition entitySearchCondition, Pageable pageable){
return ResponseResult.response(ResponseStatus.SUCCESS , repository.listEntity(entitySearchCondition,pageable));
}
- List Data 에 대한 Retrun 은 ResponseStatus.SUCCESS 로 설정한다. (”200”,”SUCCESS”)
- Single Data
public ResponseResult<EntityDTO> getEntity (Long id){
return ResponseResult.response(ResponseStatus.SUCCESS , repository.findById(id).get());
}
- Single Data 에 대한 Retrun 은 ResponseStatus.SUCCESS 로 설정한다. (”200”,”SUCCESS”)
- Create
public ResponseResult<Long> createEntity (EntityRequest entityRequest){
Entity saveEntity = repository.save(entityRequest.toEntity());
return ResponseResult.response(ResponseStatus.CREATE , saveEntity .getId());
}
- Create 에 대한 Return 은 ResponseStatus.CREATE 로 설정한다. (”201” , “SUCCESS CREATED”)
- 저장된 Entity에 대한 id 값 (Long) 을 같이 ResponseResult 에 보낸다.
- Update
public ResponseResult<Long> updateEntity (Long id , EntityDTO entityDTO) {
Entity result = repository.findById(id).orElseThrow(()-> new IllegalArgumentException("해당 게시글이 없습니다.") );
result.updateEntity(entityDTO);
return ResponseResult.response(ResponseStatus.SUCCESS, result.getId());
}
- Update 에 대한 Retrun 은 ResponseStatus.SUCCESS 로 설정한다. (”200”,”SUCCESS”)
- Delete
public ResponseResult<Long> deleteEntity (Long id) {
Entity entity = repository.findById(id).orElseThrow( () -> new IllegalArgumentException("해당 게시글이 없습니다."));
entity.delete();
return ResponseResult.response(ResponseStatus.SUCCESS, id);
}
- Delete 에 대한 Retrun 은 ResponseStatus.SUCCESS 로 설정한다. (”200”,”SUCCESS”)
- 형식적으로 Delete 에 대한 Http.Status 에 대한 값은 204 (NO_CONTENT) 이지만, 현재 Soft-Delete (논리 삭제) 방식을 사용하고 있으므로, ResponseStatus.SUCCESS 으로 사용한다.
Controller
- Controller 에서는 전달받은 ResponseResult 의 객체와 Header Http.Status 를 설정해서 Retrun 한다.
- List Data
@GetMapping("/domain/list")
public ResponseEntity<ResponseResult<Page<EntityResponse>>> listEntity(EntitySearchCondition condition, @ParameterObject @PageableDefault(page = 1) Pageable pageable) {
return new ResponseEntity<>(entityService.listEntity(condition, pageable),HttpStatus.OK);
}
- List Data 에 대한 Header의 상태 값은 HttpStatus.OK로 설정한다.
- Single Data
@GetMapping("/domain/{id}")
public ResponseEntity<ResponseResult<EntityResponse>> getEntity(@PathVariable @NotBlank Long id) {
return new ResponseEntity<>(entityService.getEntity(id),HttpStatus.OK);
}
- Single Data 에 대한 Header의 상태 값은 HttpStatus.OK로 설정한다.
- Create
@PostMapping("/domain/create")
public ResponseEntity<ResponseResult<Long>> createEntity(@RequestBody @Valid EntityRequest entityRequest) {
return new ResponseEntity<>(entityService.createEntity(entityRequest) , HttpStatus.CREATED);
}
- Create 에 대한 Header의 상태 값은 HttpStatus.CREATED로 설정한다.
- 저장된 Entity에 대한 id 값 (Long) 을 같이 ResponseResult 에 보낸다.
- Update
@PutMapping("/domain/update/{id}")
public ResponseEntity<ResponseResult<Long>> updateEntity(@RequestBody @Valid EntityRequest entityRequest) {
return new ResponseEntity<>(entityService.updateEntity(entityRequest) , HttpStatus.OK);
}
- Update 에 대한 Header의 상태 값은 HttpStatus.OK로 설정한다.
- Delete
@DeleteMapping("/domain/delete/{id}")
public ResponseEntity<ResponseResult<Long>> deleteEntity(@PathVariable @NotBlank Long id)
return new ResponseEntity<>(entityService.deleteEntity(entityRequest) , HttpStatus.OK);
}
- Delete 에 대한 Header의 상태 값은 HttpStatus.OK로 설정한다.
- 형식적으로 Delete 에 대한 Http.Status 에 대한 값은 204 (NO_CONTENT) 이지만, 현재 Soft-Delete (논리 삭제) 방식을 사용하고 있으므로, HttpStatus.OK 로 사용한다.
Test Code
- Cotroller Test는 아직 R&D 가 필요합니다
- Service 에서 ResponseResult 로 return 하면서 Service Test 대한 부분이 수정이 되었습니다.
Service Test 의 대한 데이터는 크게 3가지로 분류한다.
- List Data (Page 로 감싸진 형태)
ResponseResult<Page<TestResponse>> pageResponseResult = testService.listTest(getTestSearchCondition(), getPageable(0, 10));
List<TestResponse> list = pageResponseResult.getResultToList();
//getResultToList
public <T>List<T> getResultToList() {
return (List<T>) this.content;
}
- Service 단에서 Method를 호출하게 되면 ResponseResult<Page<TestResponse>> 이 자료형으로 나오게 된다.
- 이 데이터에서 Content 를 추출할려고 getContent 를 쓰게 되면 Page라는 자료형으로 캐스팅 오류가 발생하게 된다.
- 그러므로 따로 생성해 놓은 getResultTOList() 를 사용해 Content를 추출해야 List 에 대한 형태로 나오게 된다.
- Single Data
ResponseResult<TestResponse> responseResult = testService.getTest(id);
TestResponse response= pageResponseResult.getResultToData();
//getResultToData
public T getResultToData() {
return this.content;
}
- Single Data는 getContent() 를 호출해도 문제가 없지만 , Code Convention과 추후의 리팩토링을 위해 다른 Method 와의 Convention을 유지한다.
- Long Data
ResponseResult testResult = testService.createTest(testRequest);
Long resultToLong = testResult.getResultToLong();
//getResultToLong
public Long getResultToLong() {
return (Long) this.content;
}
- Create, Update, Delete 같은 Long 으로 retrun 해주는 method 같은 경우에도 getContetns를 하게 될 경우에 Object로 반환 하기 때문에 Test Code 에서 캐스팅이 필요하다.
- 그렇게 때문에 getResultToLong 이라는 Method를 통해 Long 형으로 content를 추출해야 된다.