RxJS를 이용해 리턴받은 HTTP Data를 매핑하는 방법을 알아봅니다.
원문입니다 : https://www.thisdot.co/blog/mapping-returned-http-data-with-rxjs
리액티브 프로그래밍과 RxJS에 관해 이미 알고 있는 것을 결합하면
RxJS가 제공하는 몇 가지 유용한 연산자를 사용하여 이러한 상황을 매우 우아한 방식으로 처리할 수 있습니다.
이 아티클에서는 두 시나리오를 처리하면서
map, mergeMap, concatMap 및 switchMap의 네 가지 연산자를 살펴보겠습니다.
또한 이를 실시간으로 볼 수 있도록 일부 StackBlitz 예제에 대한 링크도 제공합니다.
Star Wars API를 사용하여 데이터를 가져오고 Angular를 Frontend 프레임워크로 사용할 것입니다.
Angular의 HTTP 라이브러리에 리액티브 바인딩이 기본으로 포함되어 있기 때문입니다.
세부사항이 많은 경우
시나리오는 다음과 같습니다.
우리는 루크 스카이워커의 이름, 생년월일, 키, 몸무게, 눈 색깔과 같은 몇 가지 세부 사항을 알고 싶습니다.
this.http.get("https://swapi.dev/api/people/1")
.subscribe(response => console.log(response));
이렇게 하면 필요한 정보를 얻을 수 있지만
API 항목이 생성 및 편집된 시기, Luke의 종족, 그의 차량 등 필요하지 않은 많은 정보도 반환합니다.
우리는 지금 그런 세부사항에 관심이 없습니다.
this.http.get("https://swapi.dev/api/people/1")
.pipe(map(response => ({
name: response.name,
birthYear: response.birth_year,
height: Number(response.height),
weight: Number(response.mass),
eyeColor: response.eye_color
})))
.subscribe(luke => console.log(luke))
Note
Live Example
StackBlitz의 라이브 예제(live example here)에서 이 코드를 실제로 확인할 수 있습니다.
데이터의 갯수가 많은 경우
너무 많은 데이터가 있는 또 다른 일반적인 사용 사례는 검색 결과입니다.
여러 검색 결과의 첫 번째 결과만 표시하려는 경우가 있습니다.
이 시나리오에서는 map 연산자와 switchMap 연산자를 함께 사용합니다.
또한 Angular의 Reactive Forms Module을 사용하여 일부 리액티브 바인딩을 제공합니다.
코드는 매우 간단합니다.
this.searchResult$ = this.search.valueChanges.pipe(
// 사용자가 입력한 검색어를 얻습니다.
// 그리고 switchMap을 사용하여 모든 in-flight 요청을 취소합니다.
// 그런 다음 새 요청을 만들고 해당 요청을
// 관찰 가능한 스트림으로 전환합니다.
switchMap(term =>
this.http.get<any>(`https://swapi.dev/api/people/?search=${term}`)
),
// 다음으로 결과가 있는지 확인합니다.
// 결과가 있다면 첫 번째 결과를 선택합니다.
// 그렇지 않은 경우 결과가 없음을 표시하는 개체를 만듭니다.
map(response =>
response.count > 0 ? response.results[0] : { name: "No results" }
),
// 그런 다음 전체 응답 데이터를 우리가 원하는 필드만 매핑합니다.
map(
response =>
({
name: response.name,
birthYear: response.birth_year,
height: Number(response.height),
weight: Number(response.mass),
eyeColor: response.eye_color
} as PeopleData)
)
);
주 : angular는 rxjs와 긴밀하게 결합되어 http 라이브러리에서 취소 기능을 제공합니다.
axios를 이용한 요청을 취소하고 싶으면 해당 링크를 확인하세요
너무 적은 데이터 다루기
지금까지 RxJS를 사용하여 API 응답에서 너무 많은 데이터를 처리하는 방법을 살펴보았습니다.
하지만 너무 적은 데이터가 있는 경우는 어떻게 하나요?
검색 코드를 변환하여 결과와 관련된 더 많은 데이터를 가져와
데이터를 렌더링하는 데 사용하는 최종 객체에 매핑하는 방법을 살펴보겠습니다.
취소할 필요가 있으면 switchMap, 아니면 mergeMap
concatMap을 사용하면 이전 단계가 전부 끝나야 다음 단계 처리로 넘어감
this.searchResult$ = this.search.valueChanges.pipe(
// 다시 검색어를 가져와 새 API 요청에 매핑합니다.
switchMap(term =>
this.http.get<any>(`https://swapi.dev/api/people/?search=${term}`)
),
// 이제 취소할 필요가 없으므로 mergeMap을 사용합니다.
mergeMap(response =>
// 캐릭터에 대한 각 필름을 반복하기 위해 from을 사용합니다.
from(response.films).pipe(
// 스타워즈 API가 http를 반환하기 때문에 https로 변환
map(
(film: string) => `${film.substring(0, 4)}s${film.substring(4)}`
// 이제 RxJS가 각 요청을 기다리도록 강제로 concatMap을 사용합니다.
// 이후 단계 작업을 위해 모든 필름에 대한 정보를 얻기 위함입니다.
concatMap((film: string) => this.http.get<any>(film)),
// 영화 API는 또한 우리가 관심 있는 것보다 더 많은 데이터를 반환하므로 관심있는 필드만 매핑합니다.
map(film => ({
title: film.title,
releaseDate: film.release_date
})),
// 그런 다음 이러한 각 API 응답을 수집하여 필름 배열로 매핑합니다.
reduce((films, film) => [...films, film], []),
// 마지막으로 캐릭터 데이터와 필름 데이터를 하나의 객체로 통합합니다.
map(
films =>
({
name: response.name,
birthYear: response.birth_year,
height: Number(response.height),
weight: Number(response.mass),
eyeColor: response.eye_color,
films
} as PeopleData)
)
)
)
);
Conclusion
이 게시물은 RxJS를 사용하여 HTTP 요청에서 반환된 데이터를 매핑하는 방법에 관한 간단한 소개이지만,
추가 API 요청과 관련된 복잡한 데이터 매핑을 수행해야 하는 경우 유용하게 참조할 수 있으면 합니다.
참고
해당 게시물을 번역하면서 알게 된 내용인데
react-query도 인터페이스를 수정하면 쿼리를 자동으로 취소해 주는군요!
https://tanstack.com/query/v4/docs/guides/query-cancellation
'FrontEnd' 카테고리의 다른 글
[CSS] 타이포그래피 프레임워크 구축 (0) | 2022.10.12 |
---|---|
UI 치트 시트 : 간격의 우정(UI cheat sheet: Spacing friendships) (0) | 2022.10.11 |
RxJS를 이용하여 오류 처리하기 (0) | 2022.10.08 |
RxJS Subscriptions(구독) 관리 모범 사례 (0) | 2022.10.08 |
RxJS로 옵저버블을 만드는 방법 (0) | 2022.10.08 |