API Basics(Part 2: Request Response를 DTO로 받음)

4113 단어 SpringbootJPAJPA

V2: Request & Response로 DTO를 사용:
Member 엔티티 대신에 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;
    }

각 요청의 Request에 따라서 DTO를 개발하며(MemberDTO, CreateMemberRequest, UpdateMemberRequest ...), Response에 따라서 DTO를 개발(Result, CreateMemberResponse, UpdateMemberResponse ..)합니다.
각각 필요에 따라 DTO를 개발함으로써, 필요한 값들만 request로 받고 response를 내보내며, 스펙에 맞게 그 외 추가로 필요한 값들도 response로 보냅니다.(public Result getMembersV2()참고)

좋은 웹페이지 즐겨찾기