- 회원 조회 API 설계시 응답 DTO를 쓰지 않는 버전1 대비 응답 DTO를 쓰는 버전2의 이점
- Entity와 DTO는 서로 독립적인 관계가 되어, Entity가 변해도 DTO는 변하지 x == API 스펙은 변하지 x
- 또한 JPA를 쓴다면 Entity가 함부로 변하면 안되는데, 이럴 때 API스펙이 변해도 == DTO가 변해도 , Entity는 변하지 x (장점)
3_2. 나아가 Response 값으로 단순히 응답 DTO를 넘기는게 아니라,
별도의 껍데기 객체 Result 에 담아서 보낼 수 O
- 이 경우 DTO 값 이외에 다른 값을 추가로 보내야 할 경우, 이 껍데기 객체에만 추가하여 보낼 수 O
- 이 경우 Result에 다른 값을 추가해도, 어차피 API 스펙상 Result.aaa 로 꺼내서 쓰는 부분은 동일하니 -> API 스펙은 변하지 않으면서 && 확장 가능성만 열린것 이 된다.
- 실제로 나는 Retrofit 응답 결과에 맞추기 위해, ResponseDto를 만들더라도, Retrofit 응답 결과 껍데기 클래스를 만들어, 그 안에 ResponseDto 객체를 담아서 보내는 경우를 경험해 보았음.
/** <회원 조회 API V1>
* : 응답 값으로 Member Entity 자체를 직접 넘긴다
*
* [문제점]
* : Member라는 Entity가 변할 경우 , API 스펙도 함께 변한다 -> "API는 일종의 약속 이기 때문에 이렇게 깨지면 NO!" (이게 다른 모든 이유들 가운데, 가장 근본적인 문제점!)
*
* [해결책]
* : 역시나 Request 뿐만 아니라, Response도 API 응답 스펙에 맞는 별도의 DTO를 사용하자. -> 그러면 DTO를 사용하지 않았을 때의 문제점이 모두 해결됨
* */
@GetMapping("/api/v1/members")
public List<Member> membersV1() {
List<Member> findMembers = memberService.findMembers();
return findMembers;
}
/**
* <회원 조회 API V2>
* : API 응답 스펙에 맞는 별도의 DTO를 생성하여, 그 DTO를 넘겨라!
*
* [V1과의 차이점]
* : 결국 Entity와 , 프레젠테이션 계층인 DTO가 별도로 분리되므로, 1) Entity가 변하여도 API 스펙은 유지가 되고 , 2) API 스펙이 변해서 DTO가 변해도 , Entity는 함부로 변하지 x
*
* => 결론적으로 섹션1의 1,2,3강에서 하고싶은 말은 , 한마디로 Request와 Response의 값으로 넘어가는 프레젠테이션 계층 값은 Entity를 직접 쓰지 말고, 반드시 별도의 DTO를 생성해서 그 DTO를 넘겨라!!!
* */
@GetMapping("/api/v2/members")
public Result<List<MemberDto>> membersV2(){
List<Member> findMembers = memberService.findMembers();
List<MemberDto> memberDtoList = findMembers.stream()
.map(m -> new MemberDto(m.getName()))
.collect(Collectors.toList());
return new Result<>(memberDtoList, findMembers.size());
}
@Data
@AllArgsConstructor
static class Result<T>{
private T data;
private Integer numOfMembers;
}
@Data
@AllArgsConstructor
static class MemberDto{
private String name;
}