API 개발 (1) - 회원 조회, 수정, 생성

2021. 7. 28. 23:13·스프링/스프링부트 API 설계 정리

API 구현

회원 생성 API 구현

  • 회원 객체 생성 api
  • POST ("api/v2/members")
{
    "name": "최똥꼬",
    "email": "dnstlr2933@naver.com7",
    "address": {
        "zipcode" : "139xx",
        "streetAdr": "안양시 동안구 동편로 xxx",
        "detailAdr": "xxx-xxx"
        }
}

 

Member 객체

@Entity
@Getter @Setter
public class Member {

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

	private String name;

	private String email;

	@Embedded
	private Address address;

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

 

DTO를 사용하지 않고 Entity 그대로 api를 통해 구현하는 경우

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

등록

  • 요청 값으로 Member 엔티티를 직접 받는다.

문제점

  • 엔티티에 프레젠테이션 계층을 위한 로직이 추가된다.
    1. 널값을 방어하기 위해 @NotNull 등을 달아줘야 하는 등 Entity에 대해 추가 제약이 붙는다
    2. API마다 필수 요소들이 다를수 있는데도 일률적으로 제한해야 한다.
    3. 엔티티에 API 검증을 위한 로직이 들어간다. (@NotEmpty, @NotNull)
  • 엔티티가 변경되면 API 스펙이 같이 변한다.
    • 즉 api가 Entity에 의존적이게 된다.

결론

  • API 요청 스펙에 맞추어 별도의 DTO를 통해서 받는다.

DTO를 사용하여 api와 Entity를 구분하는 경우

@PostMapping("api/v2/members")
public CreateMemberResponse saveMemberV2(@RequestBody @Valid CreateMemberRequest request) {

	Member member = new Member();
	member.setName(request.getName());
	member.setEmail(request.getEmail());
	member.setAddress(request.getAddress());

	Long id = memberService.join(member);
	return new CreateMemberResponse(id);
}

등록

  • 요청 값으로 Member 엔티티 대신에 별도의 DTO를 받는다

회원 생성을 위한 DTO

@Data
static class CreateMemberRequest {
	private String name;
	private String email;
	private Address address;
}

응답

@Data
@AllArgsConstructor
static class CreateMemberResponse {
	private Long id;
}

회원 수정 API 구현

  • 회원 이름 수정 api
  • PATCH ("api/v2/members/{id}")
{
	"name": "운식이짱"
}

 

회원 이름을 수정하기 위한 DTO를 통해서 api를 받아서 처리

@PatchMapping("api/v2/members/{id}")
public UpdateMemberResponse updateMemberV2 (
			@PathVariable("id") Long id,
			@RequestBody @Valid UpdateMemberRequest request)
{
		memberService.update(id, request.getName());
		Member findMember = memberService.findMember(id);
		return new UpdateMemberResponse(findMember.getId(), findMember.getName());
}

회원 이름 변경용 DTO (이름만 받아서 변경)

@Data
static class UpdateMemberRequest{ 
	private String name; 
}

응답

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

회원 조회 API 구현

  • GET ("api/v2/members")

회원 목록을 바로 반환시 문제점

  • 기본적으로 Entity의 모든값이 노출되므로 매우 위험하다.
  • 엔티티에 프레젠테이션 계층을 위한 로직이 추가된다.
    • 값을 내보내지 않기 위한 @JsonIgnore 등..
  • 하나의 엔티티에 연결된 각각의 API를 위한 프레젠테이션 응답 로직을 담기는 매우 어렵다.
  • 엔티티가 변경되면 API 스펙이 변한다.
    • 회원의 이름을 name: "이름"으로 가져왔는데, entity의 name이 username으로 변경되어서 username으로 가져오게 되면 전체적인 api구조가 꼬이게 된다.
  • 컬렉션을 직접 반환하면 항후 API 스펙을 변경하기 어렵다.
    • 따라서 별도의 반환을 위한 Result 클래스를 생성해 해당 클래스를 값으로 갖도록해서 api의 유연한 확장성을 유지하자
    • 예를 들어 회원 목록의 개수를 추가한다는 등 수정에 용이해진다.

결론

  • API 응답 양식에 맞추어 별도의 DTO를 생성해서 반환하자

회원 조회 용 DTO를 통해서 api 처리

@GetMapping("api/v2/members")
public Result<?> memberV2() {
	List<Member> members = memberService.findAllMembers();
	List<MemberDto> collect = members.stream()
			.map(m -> new MemberDto(m.getName(), m.getEmail()))
			.collect(Collectors.toList());

	return new Result<>(collect);
}

 

회원 리스트를 배열로 바로 보내지 않고 data로 포함해서 보내기 위한 응답 객체

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

 

회원 조회용 DTO (이름과 이메일만 반환)

@Data
@AllArgsConstructor
static class MemberDto {
	private String name;
	private String email;
}
반응형
저작자표시 (새창열림)

'스프링 > 스프링부트 API 설계 정리' 카테고리의 다른 글

API 개발 (4) - One to Many관계 - DTO 직접 조회  (0) 2021.07.29
API 개발 (3) - One to Many관계 - Entity조회 후 DTO로 변환  (0) 2021.07.29
API 개발 (2) - X to One관계  (0) 2021.07.28
웹 애플리케이션 API 개발 (DTO)  (1) 2021.07.25
(springboot) 회원가입시 주소입력을 위한 카카오 주소 API 활용  (1) 2021.07.17
'스프링/스프링부트 API 설계 정리' 카테고리의 다른 글
  • API 개발 (3) - One to Many관계 - Entity조회 후 DTO로 변환
  • API 개발 (2) - X to One관계
  • 웹 애플리케이션 API 개발 (DTO)
  • (springboot) 회원가입시 주소입력을 위한 카카오 주소 API 활용
구름뭉치
구름뭉치
구름의 개발일기장
  • 구름뭉치
    구름 개발일기장
    구름뭉치
  • 전체
    오늘
    어제
    • ALL (283)
      • 프로젝트 (23)
        • 토스페이먼츠 PG 연동 시리즈 (12)
        • JWT 방식 인증&인가 시리즈 (6)
        • 스우미 웹 애플리케이션 프로젝트 (1)
        • 스프링부트 기본 보일러 플레이트 구축 시리즈 (2)
        • 마이크로서비스 아키텍쳐 시리즈 (1)
      • 스프링 (43)
        • 스프링부트 API 설계 정리 (8)
        • 스프링부트 RestAPI 프로젝트 (18)
        • 스프링부트 WebSocket 적용기 (3)
        • 스프링 JPA 정리 시리즈 (5)
        • 스프링 MVC (5)
        • 스프링 배치 (2)
        • 토비의 스프링 정리 (2)
      • 기술 학습 (28)
        • 아파치 카프카 (9)
        • 클린 코드 (4)
        • 디자인 패턴의 아름다움 (2)
        • 모던 자바 인 액션 (7)
        • JVM 스레드 딥다이브 (6)
      • Web (25)
        • 정리글 (20)
        • GraphQL 정리글 (2)
        • Jenkins 정리글 (3)
      • 취업 (6)
      • CS (77)
        • 네트워크 전공 수업 정리 (11)
        • OSI 7계층 정리 (12)
        • 운영체제 정리 (19)
        • 데이터베이스 정리 (5)
        • MySql 정리 (17)
        • GoF의 Design Pattern 정리 (12)
      • 알고리즘 (70)
        • 백준 (56)
        • 프로그래머스 (12)
        • 알고리즘 정리본 (1)
      • 기초 지식 정리 (2)
      • 일상 (8)
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    부다페스트
    크로아티아
    류블라냐
    동유럽
    키보드 손목 받침대
    마우스
    mx master s3 for mac
    레이저
    마우스 패드
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
구름뭉치
API 개발 (1) - 회원 조회, 수정, 생성
상단으로

티스토리툴바