회원 조회는 값을 가져와 화면에 보여주기만 하면 된다. 즉, 생성 / 수정 없이 조회만 하면 된다 -> REST API : GET Method 사용
회원 조회 V1 : 응답 값으로 엔티티를 직접 외부에 노출
@RestController
@RequiredArgsConstructor
public class MemberApiController {
private final MemberService memberService;
@GetMapping("/api/v1/members")
public List<Member> membersV1() {
return memberService.findMembers();
}
}
V1 코드는 매우 간단하다. memberService를 통해 가지고 있는 모든 엔티티를 리스트 형태로 반환해주는 코드이다. 하지만 이제는 딱 보면 알 수 있듯이 엔티티로 API를 조회하는 좋지 않은 코드이다. 당연히 DTO로 변환해서 받아주어야 한다.
- 문제점
- 엔티티에 프레젠테이션 계층을 위한 로직이 추가된다.
- 기본적으로 엔티티의 모든 값이 노출된다.
- 응답 스펙을 맞추기 위해 로직이 추가된다. (@JsonIgnore, 별도의 뷰 로직 등등)
- 실무에서는 같은 엔티티에 대해 API가 용도에 따라 다양하게 만들어지는데, 한 엔티티에 각각의 API를 위한 프레젠테이션 응답 로직을 담기는 어렵다.
- 엔티티가 변경되면 API 스펙이 변한다.
- 추가로 컬렉션을 직접 반환하면 향후 API 스펙을 변경하기 어렵다. (별도의 Result 클래스 생성으로 해결)
- 결론
- API 응답 스펙에 맞추어 별도의 DTO를 반환한다.
※ 참고 : 엔티티를 외부에 노출하지 않는다.
실무에서는 member 엔티티의 데이터가 필요한 API가 계속 증가하게 된다. 어떤 API는 name 필드가 필요하지만, 어떤 API는 name필드가 필요없을 수 있다. 결론적으로 엔티티 대신에 API 스펙에 맞는 별도의 DTO를 생성하여 노출해야한다.
회원 조회 V2 : 응답 값으로 엔티티가 아닌 별도의 DTO 사용
@RestController
@RequiredArgsConstructor
public class MemberApiController {
private final MemberService memberService;
@GetMapping("/api/v2/members")
public Result memberV2(){
List<Member> members = memberService.findMembers();
List<MemberDto> collect = members.stream()
.map(m -> new MemberDto(m.getUsername()))
.collect(Collectors.toList());
return new Result(collect);
}
@Data
@AllArgsConstructor
static class Result<T>{
private T data;
}
// 고객들의 이름의 반환해야한다고 가정
@Data
@AllArgsConstructor
static class MemberDto{
private String name;
}
- 엔티티를 DTO로 변환해서 반환한다.
- 엔티티가 변해도 API 스펙이 변경되지 않는다.
- 추가로 Result 클래스로 컬렉션을 감싸서 향후 필요한 필드를 추가할 수 있다.
※ Result 클래스로 컬렉션을 감싸는 이유는 Json 스펙에 맞춰 좀 더 유연하게 API를 반환하기 위함이다.
만약 감싸지 않을 경우에는 리스트 자체로 [ {Data1}, {Data2}, {Data3}, ,,,] 이런 식으로 반환된다. 만약 API가 요구하는 것이 Data 뿐만 아니라 Data의 수도 반환을 요청했을 경우 [ {Count}, {Data1}, {Data2}, {Data3} ,,] 이런 식으로 반환이 불가능하다. 리스트이기 때문에 Data와 Count객체가 동일해야한다.
따라서, 좀 더 유연한 Json 객체 반환을 위해 { "count" : 3, "Data" : [ {Data1}, {Data2}, {Data3} ] } 이런 식으로 반환해주어야한다. 그렇기 때문에 Result 클래스로 원하는 Json형태로 만들어 준 뒤 반환해주는 것이다.
위 처럼 반환해주기 위한 코드
@GetMapping("/api/v2/members")
public Result memberV2(){
List<Member> members = memberService.findMembers();
List<MemberDto> collect = members.stream()
.map(m -> new MemberDto(m.getUsername()))
.collect(Collectors.toList());
return new Result(collect.size(), collect);
}
@Data
@AllArgsConstructor
static class Result<T>{
private int count;
private T data;
}
이런 식으로 원하는 Json 형태로 만들어준 뒤 반환해주면 좀 더 유연하게 API 개발이 가능하다.
'Spring > API' 카테고리의 다른 글
API 개발 : 간단한 주문조회 (지연로딩 최적화 - 패치 조인) (0) | 2022.06.26 |
---|---|
API 개발 : 간단한 주문 조회 (지연 로딩) (0) | 2022.06.26 |
회원 수정 API 개발 (0) | 2022.06.25 |
회원 등록 API 개발 (0) | 2022.06.25 |
API란? REST API란? (0) | 2022.06.25 |