graphql 데이터 연동을 위한 apollo client 적용기 - 2
이전 포스트인 [graphql 데이터 연동을 위한 apollo client 적용기 - 1] 에서는 기본적인 설정 방법 그리고 사용방법에 대해 알아봤습니다. 이번에는 작업을 진행하면서 발생했던 cache 업데이트 관련 이슈에 대해서 작성해보겠습니다.
cache 갱신
apollo cache는 위 그림에서 나타내는것 처럼, 먼저 cache에 원하는 데이터가 있는지 확인하고, 있으면 데이터를 반환하고 없으면 서버로 데이터를 요청한 뒤 재사용 하기 위해 캐시에 쓰고 클라이언트에 넘겨줍니다.
만약 cache가 없었다면 데이터가 필요 할 때 마다 서버에 요청하여 받아오거나 직접 캐싱을 구현해야 했을 겁니다... 다행히 캐시를 지원해주고 있어 불필요한 데이터 요청을 줄일 수 있습니다.
InMemoryCache?
apollo client를 설정하고
useQuery
훅에 graphql query를 전달하여 데이터를 불러오게 되면 해당 데이터들은 InMemoryCache
에 저장이 되어 불필요한 네트워크 요청없이 데이터를 요청하여 사용 할 수 있게 됩니다.공식 문서에서는
InMemoryCache
는 응답 개체를 내부 저장소에 저장하기 전에 아래 단계를 거친다고 소개하고 있습니다.- 캐시는 응답 받은 데이터에 포함된 모든 식별 가능한 객체에 대해 고유 cache ID를 생성
- 캐시는 각 객체를 생성한 cache ID 별로
flat lookup table
에 저장한다
- 들어오는 객체가 기존 객체와 동일한 ID로 저장될때 마다 해당 객체의 필드는 병합된다.
만약 query를 실행 한 뒤 cache를 업데이트 하고 싶다면 아래 방법들 중 하나를 수행하면 됩니다.
- 직접
cache
에 접근하여 데이터를 변경한다
fetchPolicy
를 사용한다
cache.reset()
을 호출한뒤 데이터 요청을 진행한다
첫 번째 이슈
첫번째 문제로 각 페이지에서 활용하는 쿼리가 동일한 경우가 많아 다른 파라미터를 전달해도 원하는 데이터가 아닌 이전에 cache가 저장된 데이터가
useQuery
훅의 data로 부터 출력되는 현상이 발생하게 되었습니다...문서를 서칭하며 알아보니
fetchPolicy
를 기본값인 cache-first
의 특성으로 인하여 발생한 문제인것을 확인하게 되었습니다.fetchPolicy
가 cache-first
로 설정되어 있는 경우 불필요한 데이터 요청을 줄여줄수 있다는 이점이 있었지만 현재 화면에 보여줘야하는 데이터가 자주 업데이트 되어야 한다는 특성을 가지고 있어 cache-and-network
로 설정하게 되었습니다.fetchPolicy
을 cache-and-network
로 설정할 경우 아래 5단계를 거치게 됩니다.- query를 사용할 때 cache 확인
- cache 데이터가 존재 할 경우 일단 반환
- cache 데이터 존재 유무와 관계없이 서버에 쿼리를 통해 데이터를 요청
- cache 데이터를 업데이트
- 데이터를 리턴
cache와 무관하게 네트워크에 데이터 요청이 발생하기 때문에 최신 데이터를 받아올수 있도록 설정을 하여 문제를 해결하게 되었습니다.
두 번째 이슈
두번째 문제로는 인피티니 스크롤을 구현하는데 있어 발생했던 이슈입니다.
useQuery
에서 제공하는 fetchMore 함수 활용하여 스크롤시 다음 데이터를 호출하도록 구현을 진행했지만,정상적으로 다음 데이터들을 이어서 보여주는것 아닌 중복 데이터들을 뒤에 이어 보여주는 현상이 발행하게 되었습니다. 공식문서를 읽어보니 fetchMore로 데이터를 요청하는 것에 대해서는
InMemoryCache
에 typePolicy
에 merge 함수를 설정하여 이전 데이터와 최신 데이터가 합쳐질수 있도록 처리해줘야 된다고 명시가 되어 있어 이전 포스트에서 InMemoryCache 설정을 작성했던거 처럼 아래코드를 작성해줬습니다이렇게 작성을 하니 데이터가 정상적으로 다음 데이터를 이어서 보여주게 되었습니다.
merge 함수는 캐시에 데이터를 쓸 수 있게 해주며 상황에 따라 최신 데이터 값을 가지고 있는 incoming 을 return 할 수도 있지만 객체 혹은 배열로 관리가 되는 데이터인 경우 데이터의 일관성을 위해 기존 데이터를 변경하기 보다는 새로운 객체를 생성하여 반환하는것이 좋다고 한다.
useQuery
훅에 전달한 variable 값들을 함수 세번째 인자에서 받아와 사용 할 수 있어 원하는 조건에 맞춰 데이터를 반환 할 수 있도록 할 수 있습니다.