728x90
728x90
※ 본 포스팅은 김영한 강사님의 인프런 '실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화' 강의를 들으며 작성한 수강일지 입니다.
| API 개발 기본
1. 회원 등록 API
2. 회원 수정 API
3. 회원 조회 API
3. 회원 조회 API
조회만 하는 것이기 때문에 jpa.hibernate.ddl-auto: none으로 변경해 한 번 데이터를 넣어두면 그 DB에 있는 데이터를 그대로 쓸 수 있음
회원조회 V1 : 응답 값으로 엔티티를 직접 외부에 노출
// 회원 목록 조회
@GetMapping("/api/v1/members")
public List<Member> membersV1() {
return memberService.findMembers();
}
-> 순수하게 회원 정보만 얻고싶은 것인데, 주문 정보가 있다면 그것까지 모두 노출되게 됨
-> @JsonIgnore 써주기
-> orders 정보는 제외하고 노출되는 모습(상황에 따라 entity 안에 JsonIgnore를 써주기 곤란함. 다른 조치 필요)
조회 V1: 응답 값으로 엔티티를 직접 외부에 노출
- 문제점
- 엔티티에 프레젠테이션 계층을 위한 로직이 추가됨
- 기본적으로 엔티티의 모든 값이 노출됨
- 응답 스펙을 맞추기 위해 로직이 추가됨(@JsonIgnore, 별도의 뷰 로직 등등)
- 실무에서는 같은 에티티에 대해 API가 용도에 따라 다양하게 만들어지는데, 한 엔티티에 각각의 API를 위한 프레젠테이션 응답 로직을 담기는 어려움
- 엔티티가 변경되면 API 스펙이 변함
- 추가로 컬렉션을 직접 반환하면 향후 API 스펙을 변경하기 어려움(별도의 Result 클래스 생성으로 해결).
- 결론
- API 응답 스펙에 맞추어 별도의 DTO를 반환한다.
참고: 엔티티를 외부에 노출하지 마세요!
실무에서는 member 엔티티의 데이터가 필요한 API가 계속 증가하게 됨. 어떤 API는 name 필드가 필요하지만, 어떤 API는 name 필드가 필요없을 수 있음. 결론적으로 엔티티 대신에 API 스펙에 맞는 별도의 DTO를 노출해야 함
회원조회 V2: 응답 값으로 엔티티가 아닌 별도의 DTO 사용
- 엔티티를 DTO로 변환해서 반환
- 엔티티가 변해도 API 스펙이 변경되지 않음
- 추가로 Result 클래스로 컬렉션을 감싸서 향후 필요한 필드를 추가할 수 있음
아래처럼 결과값이 나오게 되는데 count를 넣어달라는 등.. -> JSON 스펙이 깨져버림
바로 array로 반환하면 스펙이 고정되어 버림
[
{
"id": 1,
"name": "new-hello",
"address": null
},
{
"id": 2,
"name": "member1",
"address": {
"city": "서울",
"street": "test",
"zipcode": "1111"
}
},
{
"id": 3,
"name": "member2",
"address": {
"city": "부산",
"street": "부산거리",
"zipcode": "54597"
}
},
{
"id": 4,
"name": "test1",
"address": {
"city": "test city",
"street": "test street",
"zipcode": "559755"
}
}
]
-> 이럴 때는 아래처럼!! array를 바로 반환한는게 아니라 아래같은 방식으로
{
"count": 4,
"data": [
[
{
"id": 1,
"name": "new-hello",
"address": null
},
{
"id": 2,
"name": "member1",
"address": {
"city": "서울",
"street": "test",
"zipcode": "1111"
}
},
{
"id": 3,
"name": "member2",
"address": {
"city": "부산",
"street": "부산거리",
"zipcode": "54597"
}
},
{
"id": 4,
"name": "test1",
"address": {
"city": "test city",
"street": "test street",
"zipcode": "559755"
}
}
]
]
}
-> Result로 한번 감싸기
@GetMapping("/api/v2/members")
public Result memberV2() {
List<Member> findMembers = memberService.findMembers(); // MemberDTO로 변환 필요
List<MemberDto> collect = findMembers.stream()
.map(m -> new MemberDto(m.getName()))
.collect(Collectors.toList());
return new Result(collect);
}
@Data
@AllArgsConstructor
static class Result<T> { // Result 라는 껍데기로 한번 감싸주기
private T data;
}
@Data
@AllArgsConstructor
static class MemberDto {
private String name;
}
{
"name": "new-hello"
},
// memberDto로 감싼 것
@GetMapping("/api/v2/members")
public Result memberV2() {
List<Member> findMembers = memberService.findMembers(); // MemberDTO로 변환 필요
List<MemberDto> collect = findMembers.stream()
.map(m -> new MemberDto(m.getName()))
.collect(Collectors.toList());
return new Result(collect.size(), collect);
}
@Data
@AllArgsConstructor
static class Result<T> { // Result 라는 껍데기로 한번 감싸주기
private int count;
private T data;
}
한 번 감싸주면 다른 데이터들도 함께넘겨줄 수 있음
728x90
728x90
'프로그래밍 > spring boot' 카테고리의 다른 글
[스프링부트] 실전! 스프링 부트와 JPA 활용2 지연 로딩과 조회 성능 최적화 #1 간단한 주문 조회 V1: 엔티티를 직접 노출 (0) | 2023.11.15 |
---|---|
[스프링부트] 실전! 스프링 부트와 JPA 활용2 #2 API 개발 고급 - 준비 (0) | 2023.11.15 |
[스프링부트] 실전! 스프링 부트와 JPA 활용2 #1 API 개발(2) 회원 수정 (0) | 2023.11.14 |
[스프링부트] 실전! 스프링 부트와 JPA 활용2 #1 API 개발 기본 feat. postman 설치 (1) (0) | 2023.11.14 |
[스프링부트] 실전! 스프링 부트와 JPA 활용2 #0 API 개발과 성능 최적화 (0) | 2023.11.14 |