Jaeilit

Appollo Client 공식문서 캐시 + 캐시 맛보기(머지,리드) 본문

TIL

Appollo Client 공식문서 캐시 + 캐시 맛보기(머지,리드)

Jaeilit 2023. 1. 18. 14:41
728x90

공식문서
https://www.apollographql.com/docs/react/caching/overview#data-normalization

 

Caching in Apollo Client

Overview

www.apollographql.com

캐시 동작방법

예를들어 book5 를 두번 호출했을 경우에 inMemoryCache에 저장 된 캐시 데이터가 반환됩니다.

네트워크 호출을 하지않습니다.

 

캐시는 어디에 저장하는 걸까요?

데이터를 정규화하여 로컬 메모리내에 저장합니다.

 

캐시는 어떻게 저장 하는 걸까요?

아폴로 클라이언트의 캐시는 falt lookup table 로 저장합니다.

데이터를 서로 참조할수있는 조회테이블(look up table)로 저장하지만 실제로 반환되는 쿼리는 그렇지 않은 경우가 많습니다.

look up table 은 하나의 key 와 value 를 가진 테이블을 말합니다.

오른쪽 작은 테이블이 look up table 입니다 이름처럼 단순 조회할때 쓰기 좋아보입니다.

key value 한쌍이라는 특징때문에 보통 필터 값으로 쓰이는 경우도 있다고합니다.

 

 

캐시는 정규화하여 저장한다고 했습니다.

정규화란? (normalization)

 

예시 쿼리)

캐시를 저장할때 식별자 : 캐시id 로 저장하게 됩니다.

기본적으로 식별자는 __typename id 는 data 의 id 가 됩니다.

현재 단계에서 저장 된 캐시는 이렇게(아래) 저장되어있습니다. 평평하지 않습니다.

Planet 를 참조관계로 바꾸게 됩니다.

참조 관계에서 __ref 라는 참조 아이디는 다시 캐시의 식별자:캐시id 로 저장됩니다.

그리고 __ref 가 root query 밖의 캐시를 참조합니다.

여기서 참조할 객체의 id 값이 없으면 __ref 로 참조관계를 만들지 못하고 정규화된 캐시를 하지못합니다.

공식문서에서는 id 가 없으면 참조 관계가 아닌 상위캐시 내부에 직접적으로 캐시되기 때문에 항상 평평하지는 않다고 합니다.

정규화 된 캐시 데이터는 중복을 크게 줄일 수 있으며 로컬데이터를 서버에서  최신상태로 유지하는데 도움이 됩니다.

마지막으로 결과 개체는 모두 캐시의 flat lookup table 에 저장됩니다.

 

이전 캐시 데이터와 incoming 데이터가 있습니다.
이전 캐시 데이터를 exsiting 이라고 하는데

exsiting 데이터와 incoming 데이터의 캐시 id 가 같다면 두 데이터는 merge 됩니다.

merge 방법에 대해서

같은 필드를 공유하는 경우에는 incoming data 로 기존 캐시를 오버라이딩하게 됩니다.
나머지 데이터들은 보존됩니다.

 

실제 캐시를 살펴보기

 

아폴로 devtool 을 설치하면 개발자도구에서 캐시를 확인할수 있습니다.

https://www.apollographql.com/docs/react/development-testing/developer-tooling/#apollo-client-devtools

 

Developer tools

Improve your developer experience with these services and extensions

www.apollographql.com

본문

먼저 리스트를 불러오는 부분인데

 

ROOT QUERY

premiumContracts 라는 gql 쿼리가 캐시되어 있습니다.

edegs  =>  node 는 __ref 로 ROOT_QUERY 밖을 참조하고 있습니다.

__ref 의 캐시 아이디는 식별자: (필드 값의 id) id 로 되어있습니다.

 

여기까지가 캐시가 저장되는 실습입니다.

 

캐시 다뤄보기 맛보기

 

1. 페이지네이션 캐시머지 (커서)

 

보통 무한스크롤로 페이지네이션을 하게되면 리스트 개체가 10개가 -> 다음 10개와 합쳐져서 20개가 되야합니다.

 

데이터를 state 로 관리할 경우에 무한스크롤을 하면 concat 으로 데이터를 지속적으로 새 배열로 합쳐줘야합니다.

하지만 아폴로는 캐시에서 merge 를 해주고 merge 캐시를 반환 받음으로써 데이터를 바로 가져다쓸수 있습니다.

 

캐시 머지

https://www.apollographql.com/docs/react/pagination/core-api/#improving-the-merge-function

 

Core pagination API

Fetching and caching paginated results

www.apollographql.com

 

2. keyArgs 로 캐시 나누기

아까 캐시를 살펴볼때 같은 캐시 id 가 들어오면 기존 필드를 덮어씌우거나 보존한다고 했었습니다.

 

예를들어서 페이지네이션을 하는 리스트에 옵션으로 필터가 있는 경우에는

args 로 필터값을 받고 같은 쿼리를 보내면서 캐시를 덮어씌우게 됩니다.

 

이런 경우에 다시 다른 페이지를 갔다가 캐시로 리스트 된 페이지를 오게 되면

옵션으로 기존 캐시를 덮어씌워진 리스트가 보여지게 됩니다.

 

이럴 때 저는 캐시를 비워줘야한다고 생각을 했는데,

keyAgrs 로 filter 를 나눠서 캐싱하면 된다는 해결법을 찾았습니다...

https://www.apollographql.com/docs/react/pagination/key-args

 

Key arguments in Apollo Client

Using the keyArgs API

www.apollographql.com

keyArgs 를 지정해준 값으로 캐싱이 따로 됩니다.

이젠 리스트에 필터를 조작하더라도 다른 페이지를 다녀와도 캐싱 된 데이터를 안전하게 불러올수있습니다.

 

** fetchMore 과 refetch 의 차이

 

fetchmore 은 말 그대로 fetch 를 더 한다는 뜻이고 페이지네이션에서 사용합니다.

refetch 는 variable 이 달라진 경우 새로운 variable 로 fetch를 하는데 nextwork 옵션이 cache 에 관한것이 먼저이면 UI 업데이트를 하지 않습니다. (경험상)

 

 

728x90