회원 등록 API
1. 엔티티를 Request Body에 직접 매핑(요청 값으로 엔티티를 직접 받는 경우)
@Entity
@Getter
@Setter
public class Member {
@Id
@GeneratedValue
@Column(name = "member_id")
private Long id;
@NotEmpty
private String name;
private String phone;
@Embedded
private Address address;
@OneToMany(mappedBy = "member")
private List<Reserve> reserves = new ArrayList<>();
}
@PostMapping("/api/v1/members")
public CreateMemberResponse saveMemberV1(@RequestBody @Valid Member member){
Long id = memberService.join(member);
return new CreateMemberResponse(id);
}
@Data
static class CreateMemberResponse{
private Long id;
public CreateMemberResponse(Long id) {
this.id = id;
}
}
- 엔티티에 프레젠테이션 계층을 위한 로직 추가 필요
- 엔티티에 API 검증을 위한 로직이 추가됨, 그러나 상황에 따라 API별 검증 로직이 다른 경우가 존재할 수도 있음
- 엔티티 변경 시(ex.Member 클래스의 필드 명 변경 시) API 스펙이 변경
2. 엔티티 대신 DTO를 RequestBody에 매핑(요청 값으로 별도의 DTO를 받는 경우)
@PostMapping("/api/v2/members")
public CreateMemberResponse saveMemberV2(@RequestBody @Valid CreateMemberRequest request){
Member member = new Member();
member.setName(request.getName());
Long id = memberService.join(member);
return new CreateMemberResponse(id);
}
...
@Data
static class CreateMemberRequest{
private String name;
}
@Data
static class CreateMemberResponse{
private Long id;
public CreateMemberResponse(Long id) {
this.id = id;
}
}
- 엔티티와 프레젠테이션 계층을 위한 로직 분리 가능
- DTO를 여러개 선언하여 API별 검증 로직을 다르게 적용 가능
- 엔티티와 API 스펙을 명확하게 분리 가능(DTO에 선언된 필드들만 파라미터로 넘어옴)
- 엔티티가 변해도 API 스펙이 변하지 않음
중요점
- 엔티티가 변해도 API 스펙이 변하면 안됨
회원 조회 API
1. 응답 값으로 엔티티를 외부에 직접 노출
@GetMapping("/api/v1/members")
public List<Member> membersV1(){
return memberService.findMembers();
}
- 엔티티의 모든 값이 노출
- 응답 스펙을 맞추기 위한 로직이 추가됨(@JsonIgnore 등)
- 엔티티가 변경되면 API 스펙이 변함
- 컬렉션을 직접 반환하는 경우 API 스펙 변경이 어려움(배열 내 스펙 추가 불가)
2. 응답 값으로 별도의 DTO 사용
@GetMapping("/api/v2/members")
public Result membersV2(){
List<Member> findMembers = memberService.findMembers();
List<MemberDto> collect = findMembers.stream()
.map(m -> new MemberDto(m.getName()))
.collect(collect.size(), Collectors.toList());
return new Result(collect);
}
...
@Data
@AllArgsConstructor
static class Result<T> {
int count; // 필요한 필드 추가
private T data;
}
@Data
@AllArgsConstructor
static class MemberDto{
private String name;
}
- 필요한 클래스를 생성한 뒤, 해당 클래스로 컬렉션을 감싸서 향후 필요한 필드 추가 가능(count)
중요점
- 엔티티를 외부에 노출하며 안됨
'개발진행목록 > 예약 서비스' 카테고리의 다른 글
예약 리스트 조회 API 순환참조 해결 (0) | 2024.10.29 |
---|---|
예약 조회 API 개발 (0) | 2024.10.24 |
설계 (0) | 2024.09.20 |