// Member 엔티티를 파라미터에
@PostMapping("/api/v1/members")
public CreateMemberResponse saveMemberV1(@RequestBody @Valid Member member) {
Long id = memberService.join(member);
return new CreateMemberResponse(id);
}
@Data
static class CreateMemberRequest {
@NotEmpty
private String name;
}
@Data
@AllArgsConstructor
static class CreateMemberResponse {
private Long id;
}
- 요청 값으로 Member 엔티티를 직접 받는다.
- 엔티티에 프레젠테이션 계층을 위한 로직이 추가된다. → 분리가 되지 않고 결국 API 스펙이 변할 우려가 있다.
- 결론 : 엔티티 파라미터 (X) & 요청 스펙에 맞추어 커스텀으로 구성한 DTO 파라미터 (O)
@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);
}
- 엔티티 - 도메인(Domain)
- 컨트롤러 - 프레젠테이션(Presentation)
- 이 두 가지의 명확한 분리가 가능하며 엔티티가 변하더라도 API 스펙은 변하지 않는다.
@PutMapping("/api/v2/members/{id}")
public UpdateMemberResponse updateMemberV2(@PathVariable(name = "id") Long id,
@RequestBody @Valid UpdateMemberRequest request) {
memberService.update(id, request.getName());
Member findMember = memberService.findOne(id);
return new UpdateMemberResponse(findMember.getId(), findMember.getName());
}
@Data
static class UpdateMemberRequest {
private String name;
}
@Data
@AllArgsConstructor
static class UpdateMemberResponse {
private Long id;
private String name;
}
@Transactional
public void update(Long id, String name) {
Member member = memberRepository.findOne(id);
member.setName(name);
}
- 회원 수정 역시 엔티티 대신 DTO를 파라미터에 넣는다.
-
@PutMapping
: 전체 업데이트, @PatchMapping
: 일부 업데이트
- 식별자를 통해 DB로부터 조회하여 JPA의 1차 캐시로 가져온 후(영속 상태) Dirty Checking(더티 체킹)을 통해 변경한다.
@GetMapping("/api/v1/members")
public List<Member> membersV1() {
return memberService.findMembers();
}
- 응답 값으로 엔티티를 직접 외부에 노출한다.
- 예를 들어, 회원 목록만을 조회하고 싶다면 불필요하게 주문 내역 등도 같이 조회가 된다.
- API 응답 스펙에 맞추어 별도의 DTO를 반환하는 것이 좋다.
@GetMapping("/api/v2/members")
public Result membersV2() {
List<Member> members = memberService.findMembers();
List<MemberDto> list = members.stream().map(member -> new MemberDto(member.getName())).toList();
return new Result(list);
}
@Data
@AllArgsConstructor
static class MemberDto {
private String name;
}
@Data
@AllArgsConstructor
static class Result<T> {
private T data;
}
- 응답 값으로 엔티티가 아닌 별도의 DTO를 만들어 반환한다.