GitHub

https://github.com/Choidongjun0830

Spring

[JPA 활용 2편] API 개발 기본

gogi masidda 2024. 7. 2. 14:48

회원 등록 API

@RestController
@RequiredArgsConstructor
public class MemberApiController {

    private final MemberService memberService;

    @PostMapping("api/v1/members")
    public CreateMemberResponse saveMemberV1(@RequestBody @Valid Member member) {
        Long id = memberService.join(member);
        return new CreateMemberResponse(id);
    }

    @Data
    static class CreateMemberResponse {
        private Long id;

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

실무에서는 회원 엔티티를 위한 API가 다양하게 만들어지는데, 한 엔티티에 각각의 API를 위한 모든 요청의 요구사항을 담을 수 없고, 엔티티가 수정되면 API 스펙도 바뀐다. 그래서 API의 요청을 받기 위한 DTO를 만들어야 한다.

 

@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;
        }
    }

엔티티가 변해도 API 스펙이 변하지 않아 요청 시에 쓰이는 DTO를 따로 만드는 것이 API를 만들 때의 정석이다.

 

회원 수정 API

등록과 수정은 API 스펙이 달라서 다른 DTO를 만들어주어야 한다.

 

@PutMapping("api/v2/members/{id}")
    public UpdateMemberResponse updateMemberV2(@PathVariable 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;
    }

update()는 memberService에서 변경 감지를 이용함. 

 

회원 조회 API

조회에서도 역시 응답 값으로 엔티티를 직접 외부에 노출하면 안된다.

실무에서 하나의 엔티티로 여러 용도의 API가 만들어진다.

 

@GetMapping("api/v2/members")
public Result memberV2() {
    List<Member> findMembers = memberService.findMembers();
    List<MemberDto> collect = findMembers.stream()
            .map(m -> new MemberDto(m.getName()))
            .collect(Collectors.toList());
    //stream() 방식 아니면 iter 쓰기

    return new Result(collect.size(), collect);
}

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

@Data
@AllArgsConstructor
static class MemberDto {
    private String name;
}

엔티티가 바뀌어도 API 스펙이 바뀌지 않도록 하는 것이 중요하다. 

728x90