APIベース(第2部:DTO受信要求応答)


V 2:DTOはリクエストと応答に使用されます.
メンバーエンティティではなくCreateMemberRequestなどのDTOをRequestBody、ResponseBodyにマッピングします.
メリット:
1.エンティティとプレゼンテーションレイヤの論理を分離できます.
2.エンティティとAPIの仕様は明確に分けることができる.
3.エンティティが変更された場合、API仕様は変更されません.
4.パラメータが受け入れる値をより明確に知ることができる.
	/**
     * 회원 조회
     * 조회 값을 DTO를 사용하지 않고, List<Member>로 엔티티의 리스트를 그대로 반환 할 시, 엔티티의 모든 속성 값들을 반환(id, username, address, orders)
     * 필요하지 않는 정보들도 모두 반환하는 문제가 있으므로, DTO로 반환
     */
    @GetMapping("/api/v2/members")
    public Result getMembersV2(){
        List<Member> findMembers = memberService.findMembers();
        List<MemberDTO> members = findMembers.stream()
                .map((m) -> {
                    return new MemberDTO(m.getId(), m.getUsername());
                }).collect(Collectors.toList());
        System.out.println("membersList = " + members);

        return new Result(members.size(), members);
        /**
         * 결과:
         * {
         *     "count": 2,
         *     "data": [
         *         {
         *             "id": 1,
         *             "username": "usernameB"
         *         },
         *         {
         *             "id": 2,
         *             "username": "updateUsernameB"
         *         }
         *     ]
         * }
         */

        /**
         *  Response에 단순히 members만 배열로 반환하는 경우는 적음; 배열 + 추가적인 값들을 반환할때가 많음
         *  그러므로, Result라는 DTO를 생성 후, 스펙에 맞게 값들을 반환해줌
         */
       
    }

	/*
    * 회원 저장
    */
    @PostMapping("/api/v2/members")
    public CreateMemberResponse saveMemberV2(@RequestBody @Valid CreateMemberRequest request) {
        Member member = new Member();
        member.setUsername(request.getUsername());

        Long id = memberService.join(member);

        return new CreateMemberResponse(id);
    }

    /**
     * 회원 수정
     */
    @PutMapping("/api/v2/members/{id}")
    public UpdateMemberResponse updateMember(@RequestBody @Valid UpdateMemberRequest request,
                                             @PathVariable("id") Long id) {

        memberService.update(id, request.getUsername());
        Member findMember = memberService.findOne(id);

        return new UpdateMemberResponse(id, findMember.getUsername());
    }

    @Data //Getter, Setter, RequiredArgsConstructor ...
    static class CreateMemberRequest {
        private String username;
    }

    @Data
    static class CreateMemberResponse {
        private Long id;

        public CreateMemberResponse(Long id) {
            this.id = id;
        }
    }

    @Data
    static class UpdateMemberRequest {
        private String username;
    }

    @Data
    @AllArgsConstructor
    static class UpdateMemberResponse {
        private Long id;
        private String username;

    }

    @Data
    @AllArgsConstructor
    static class MemberDTO {
        private Long id;
        private String username;
    }

    @Data
    @AllArgsConstructor
    static class Result<T> {
        private int count;
        private T data;
    }
各リクエストのリクエストに応じてDTO(MemberDTO、CreateMemberRequest、UpdateMemberRequest...)を開発します.応答開発DTO(Result、CreateMemberResponse、UpdateMemberResponse...).
必要に応じてDTOを開発し、必要な値だけを受信して応答をエクスポートし、仕様に応じて他の必要な値を応答に戻すことができます.(public Result getMembersV 2を参照)