CS 잡지식

Rest API 개발 시, List<E> 등의 [컬렉션]을 [직접] 반환하지 말 것!

JIN_YOUNG _KIM 2023. 5. 3. 15:50

결론부터 말을 하자면, 

컬렉션을 [직접] 반환하면 항후 API 스펙을 변경하기 어렵기 때문에,

컬렉션을 별도의 클래스로 한 번 Wrapping을 한 후에 넘겨줘야 한다(무슨 말인지는 아래를 천천히 읽어 보자).

(사전 지식 : JSON은 실체는 <KEY,T>쌍의 배열이다

EX)

         "id"1,
 
         "name""jin young kim",
 
위와 같은 JSON이 있다고 하자.
 
이것의 실체는 List<[key,value]> json = new ArrayList<>()에 불과하다. 
 
 
        "id"1,
 
        "name""jin young kim",
 
        "address": {
 
            "city""해운대구",
 
            "street""해운대로781번길23, 101동 1702호",
 
            "zipcode""48102"
 
        }
 
위 address는 컬렉션이 반환이 된 것이다. 
 
 json[x] == <"address" , 컬렉션 >이 화면에 뿌려진 것이다. 
 
 
)
 
 

근데,  address 컬렉션을 [직접] 반환하여 화면에 뿌리는 것에는 어떠한 문제점이 있을까??

-> API 개발 시, [유연성]이 떨어진다는 것이다. 

이런 시나리오를 생각해 보자.

"COUNT" : 1

"DATA"     : [

{ "id"1,
"name""jin young kim",
"address": {
   "city""해운대구",
   "street""해운대로781번길23, 101동 1702호",
   "zipcode""48102" }

]

위와 같은 형태로 Rest API의 호출 결과를 [변경]을 한다고 해보자. 

@GetMapping("/api/v1/members")
public List<Member> membersV1(){ //[회원 조회]용 Rest API - 1

    return memberService.findMembers(); // [도메인 엔티티]를 반환! ( memberV2()에서 개선할 예정 )
                                        // 그리고 컬렉션(List<Member>)를 [직접] 반환하고 있다.
}

위와 같이 컬렉션을 [직접] 반환을 하는 형태로는 도저히 위와 같이 JSON 형태를 변경할 재간이 없다. 

즉, [유연성]이 떨어 진다. 

아래에 해결 방안이 있다.

@GetMapping("api/v2/members")
public Result membersV2(){ //[회원 조회]용 Rest API - 2

    List<Member> findmembers = memberService.findMembers();

    //1] findMembers 컬렉션을 [MemberDTO 컬렉션]으로 변환
    List<MemberDTO> memberDTO = findmembers.stream()
            .map(m -> new MemberDTO(m.getName()))
            .collect(Collectors.toList());
    // 2] [MemberDTO 컬렉션]을 Result 클래스의 필드값으로 넘겨서 반환함으로서, 컬렉션을 [직접] 반환하는 것이 아닌,
    // Result 객체의 필드값으로[간접적]으로 컬렉션을 넘김.
    // 즉, 컬렉션을 한 번 Wrapping을 해서, 넘겨야 한다.
    return new Result(1,memberDTO);

}

 

@Data
@AllArgsConstructor
public static class Result<T>{

    private int count;
    private T data; // Rest API를 호출한 개발자의 화면에는 "data" : "[회원 목록1,2,3,,,,,n]" 형태로 보여질 것이다.
                // https://jbluke.tistory.com/411 사이트를 참조하면 보여지는 화면의 차이점인지 파악 가능할 것이다.
}

@Data
@AllArgsConstructor
public static class MemberDTO{

    private String name;

}

 

컬렉션을 직접 반환하는 것이 아니라, 컬렉션을 별도의 클래스로 한 번 Wrapping을 하여 [간접적]으로 반환을 하였다.

결론 : Collection은 반드시 별도의 클래스를 작성하여 1번 Wrapping해서 전달하자!!!!