@RestController
@RequestMapping("/v2/members")
@Validated
public class MemberController {

    private final MemberService memberService;

    @Autowired
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }

    @PostMapping
    public ResponseEntity postMember(@Valid @RequestBody MemberPostDto memberDto) {
        Member member = new Member();
        member.setEmail(memberDto.getEmail());
        member.setName(memberDto.getName());
        member.setPhone(memberDto.getPhone());

        Member response = memberService.saveMember(member);

        return new ResponseEntity<>(response, HttpStatus.CREATED);
    }

    @PatchMapping("/{member-id}")
    public ResponseEntity patchMember(@PathVariable("member-id") @Positive long memberId,
                                      @Valid @RequestBody MemberPatchDto memberPatchDto) {

        // No need Business logic

        Member member = new Member();
        member.setMemberId(memberPatchDto.getMemberId());
        member.setName(memberPatchDto.getName());
        member.setPhone(memberPatchDto.getPhone());

        Member response = memberService.updateMember(member);

        return new ResponseEntity<>(response, HttpStatus.OK);
    }

    @GetMapping("/{member-id}")
    public ResponseEntity getMember(@PathVariable("member-id") @Positive long memberId) {
        System.out.println("# memberId: " + memberId);

        Member response = memberService.findMember(memberId);
        // not implementation
        return new ResponseEntity<>(response, HttpStatus.OK);
    }

    @GetMapping
    public ResponseEntity getMembers() {
        System.out.println("# get Members");

        // not implementation
        List<Member> response = memberService.findMembers();
        return new ResponseEntity<>(response, HttpStatus.OK);
    }

    @DeleteMapping("/{member-id}")
    public ResponseEntity deleteMember(@PathVariable("member-id") @Positive long memberId) {
        System.out.println("# deleted memberId: " + memberId);
        // No need business logic
        memberService.deleteMember(memberId);

        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }

}
@Service
public class MemberService {

    public Member createMember(Member member) {

        return member;
    }

    public Member updateMember(Member member) {
        return member;
    }

    public Member getMember(long memberId) {

        return new Member(memberId, "thom", "[email protected]", "010-1234-1234");
    }

    public List<Member> getMembers() {
        return List.of(
                new Member(1, "thom", "[email protected]", "010-1234-1234"),
                new Member(2, "jonny", "[email protected]", "010-4555-1234"),
                new Member(3, "eddie", "[email protected]", "010-1233-1234")
        );
    }

    public void deleteMember(long memberId) {

    }

}

Mapper를 통해 DTO와 도메인 클래스 상호 변환 작업 분리

@Component
public class MemberMapper {

    public Member createMemberFrom(MemberPostDto memberPostDto) {
        return new Member(
                0L,
                memberPostDto.getName(),
                memberPostDto.getEmail(),
                memberPostDto.getPhone());
    }

    public Member createMemberFrom(MemberPatchDto patchDto) {
        return new Member(
                patchDto.getMemberId(),
                patchDto.getName(),
                null,
                patchDto.getPhone()
        );
    }

    public MemberResponseDto createMemberResponseDtoFrom(Member member) {
        return new MemberResponseDto(
                member.getMemberId(),
                member.getEmail(),
                member.getName(),
                member.getPhone());
    }
}