Spring BootとJPA 2(API開発と性能最適化)を利用した1-API開発基本


(1)会員登録API

  • MemberApiコントローラ-登録会員
  • package jpabook.jpashop.api;
    import jpabook.jpashop.domain.Member;
    import jpabook.jpashop.service.MemberService;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.RequiredArgsConstructor;
    import org.springframework.web.bind.annotation.*;
    import javax.validation.Valid;
    import java.util.List;
    import java.util.stream.Collectors;
    
    @RestController
    @RequiredArgsConstructor
    public class MemberApiController {
    
        private final MemberService memberService;
    
        /**
         * 회원 가입(생성) API
         */
        @PostMapping("/api/v1/members")
        public CreateMemberResponse saveMemberV1(@RequestBody @Valid Member member) {
            Long id = memberService.join(member);
            return new CreateMemberResponse(id);
        }
    
        @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;
            }
        }
    }
    V 1エンティティをRequest Bodyに直接マッピング
  • 問題
    :エンティティにプレゼンテーションレイヤ用の論理が追加されました.
    :エンティティにAPIを検証するロジックが含まれます.(@NotEmptyなど)
    :実際の作業では、会員エンティティのために作成されるAPIは多種多様であり、1つのエンティティに各APIのすべての要求要求要求を含めることは難しい.
    :エンティティが変更されると、API仕様が変更されます.
  • 結論
    ->API要求の仕様に従って、パラメータ
  • として個別のDTOを受け入れる
    DTOをV 2エンティティではなくRequest Bodyにマッピング

    :CreateMemberRequestをメンバーエンティティではなくRequestBodyにマッピングします.
    :エンティティとプレゼンテーションレイヤの論理を分離できます.
    :エンティティとAPI仕様を明確に分けることができます.
    :エンティティが変更された場合、API仕様は変更されません.

    (2)会員修正API

  • MemberApiController.JAva-メンバー
  • の変更
        /**
         * 회원 수정 API
         */
        @PutMapping("/api/v2/members/{id}")
        public UpdateMemberResponse updateMemberV2(
                @PathVariable("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;
        }
    
    会員API updateMemberV 2を変更すると、会員情報が一部更新されます.ここではPUTを使います
  • PUT:完全更新用
  • PATCH,POIST:部分更新時に
  • を使用

    (3)会員照会API

  • MemberApiController.JAva-会員照会
  • package jpabook.jpashop.api;
    @RestController
    @RequiredArgsConstructor
    public class MemberApiController {
     
     private final MemberService memberService;
    
     //조회 V1: 안 좋은 버전, 모든 엔티티가 노출, 
     @JsonIgnore -> 이건 정말 최악, api가 이거
    하나인가! 화면에 종속적이지 마라!
    
        @GetMapping("/api/v1/members")
        public List<Member> membersV1() {
            return memberService.findMembers();
        }
    
        @GetMapping("/api/v2/members")
        public Result membersV2() {
            List<Member> findMembers = memberService.findMembers();
            List<MemberDto> collect = findMembers.stream()
                    .map(m -> new MemberDto(m.getName()))
                    .collect(Collectors.toList());
    
            return new Result(collect.size(),collect);
        }
    }
    会員照会V 1:エンティティを直接応答値として露出する
  • 問題
    :エンティティにプレゼンテーションレイヤ用の論理が追加されました.
    :デフォルトでは、エンティティのすべての値が露出されます.
    :specに応答するためにロジックを追加します.(@JsonIgnore、個別ビューロジックなど)
    :実際の作業では、同じエンティティのAPIは用途によって異なり、1つのエンティティに各APIに対するプレゼンテーション応答ロジックを含めるのは難しい.
    :エンティティが変更されると、API仕様が変更されます.
    :追加のローカルコレクションを直接返すと、永続API仕様を変更することは困難です.(個別のResultクラスを作成して解決)
  • 結論
    ->API応答specに従って個別のDTOを返す.
  • 会員照会V 2:エンティティではなく独立したDTOを応答値として使用
  • エンティティをDTOに戻します.
  • エンティティが変更されても、API仕様は変更されません.
  • 追加のResultクラスローカルセットで、将来必要なフィールド
  • を追加できます.