FireDrago

[JpaShop] 회원 가입 api 구현 본문

프로젝트

[JpaShop] 회원 가입 api 구현

화이용 2024. 4. 11. 13:06

" api를 만들때는 엔티티를 파라미터와 반환값에 절대 노출하면 안된다."

 

@Entity
@Getter @Setter
public class Member {

    @Id
    @GeneratedValue
    @Column(name = "member_id")
    private Long id;

    private String name;

    @Embedded
    private Address address;

    @OneToMany(mappedBy = "member")
    private List<Order> orders = new ArrayList<>();
}

회원 가입을 위한 엔티티이다. 주문 엔티티와 일대다 관계를 맺고있다.

Member 엔티티를 바탕으로 회원가입, 수정, 회원목록 조회 api를 만들어보자

 

@RestController
@RequiredArgsConstructor
public class MemberApiController {

    @PostMapping("/api/v2/members")
    // @RequestBody httpBody의 json 값을 객체로 변환
    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 {
         @NotEmpty
        private String name;
    }

    @Data
    static class CreateMemberResponse {
        private Long id;

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

회원 가입을 위한 컨트롤러 메서드이다.

api를 만들때는 엔티티를 파라미터와 반환값에 절대 노출하면 안된다.

1. 엔티티에 @NotNull등 여러 제약 조건이 덕지덕지 붙게되고,

2. 엔티티가 변경되면 API의 스펙이 변경된다.

따라서 별도의 DTO 를 통해 데이터를 입력받고, 반환해야 한다.

 

@RequestBody 어노테이션은 HttpBody 의 json, xml 정보를 객체로 변환한다.

@ModelAttribute는 여러 파라미터 정보에 사용된다. (Html Form )

 

@PostMapping("/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;
}

회원 정보 수정을 위한 메서드이다. 

@PostMapping 을 사용한다. 파라미터와 반환값을 위한 DTO를 따로 생성했다.

update 메서드는 반환값을 따로 주지 않았다. 명확한 책임분리를 위해서이다.

 

/**
 * 조회 V2: 응답 값으로 엔티티가 아닌 별도의 DTO를 반환한다.
 */
@GetMapping("/api/v2/members")
public Result membesV2() {
    List<Member> findMembers = memberService.findMembers();
    // 엔티티 -> DTO 변환
    List<MemberDto> collect = findMembers.stream()
            .map(m -> new MemberDto(m.getName()))
            .collect(Collectors.toList());
    return new Result(collect);
}

@Data
@AllArgsConstructor
static class Result<T> {
    private T data;
}

회원목록 조회 메서드이다.

Result<T> 객체를 반환하면, List를 그대로 반환하는 것보다 유연하게 API 스펙을 정의할 수 있다.

API 스펙에 여러 정보들 (ex 리스트의 사이즈 값 등) 을 추가하기 쉽다.

 

stream map( ) 메서드를 통해 컬렉션의 각 값들을 변환해준뒤

collect(Collectors.toList()) 메서드로 List 로 반환한다.