본문 바로가기

개발바닥/GraphQL

[개발] GraphQL - Apollo Client Cache

안녕하세요. devport 입니다. Apollo Client에서는 다양한 방법의 Cache 전략을 가지고 있습니다. 이번 포스팅에서 알아보도록 하겠습니다.

Cache?

캐쉬는 임시로 데이터를 보관하는 장소입니다. 브라우저에서 같은 데이터 및 파일을 매번 네트워크를 거쳐서 요청한다는 것은 불필요할 수도 있습니다. 이럴때 매번 요청을 할 필요가 없는 경우에 한번 요청한 정보를 Cache에 저장하고 이곳에서 가져온다면 불필요한 네트워크 요청을 줄일 수 있게 됩니다.

Apollo client cache

Apollo Client는 쿼리를 하였을때에 결과물을 정규화하여 InMemoryCache에 저장을 하게 됩니다. 정규화 된 캐시를 통해서 GraphQL의 쿼리 성능을 크게 높일수 있게 됩니다. 이렇게 될 경우 GraphQL 서버에 네트워크 요청수를 줄임으로써 클라이언트의 응답성을 향상시킬 수 있게 됩니다. 

InMemoryCache

InMomoryCache를 생성하고 ApolloClient  생성자를 생성합니다.

import { InMemoryCache, ApolloClient } from '@apollo/client';

const client = new ApolloClient({
  // ...other arguments...
  cache: new InMemoryCache(options)
});

아래는 InMemoryCache의 옵션 구성입니다.

이름 유형 기술
addTypename bool true일 경우 모든 쿼리에 __typename필드가 자동으로 추가됩니다. (default: true)
resultCaching bool true일 경우 기본데이터가 변경되지 않는 캐시는 동일한 쿼리를 실행할 때마다 응답 객체를 반환합니다. 이렇게 되면 쿼리 결과의 변경사항을 더쉽게 감지 할 수 있게 됩니다. (default: true)
possibleTypes { [supertype:string]:string[] } 여러 유형의 스키마간의 관계를 정의하려면 이 개체를 포함해야합니다.
이렇게 했을 경우 인터페이스 또는 union으로 Cache된 데이터를 조회 할 수 있습니다.
typePolicies { [typename:string]:TypePolicy } type별로 Cache의 동작을 지정하려면 이 개체를 포함하여야 합니다.
각 항목의 __typename을 키로 합니다.

데이터 정규화

InMemoryCache는 응답데이터를 내부 데이터에 저장하기전에 정규화를 합니다. 정규화는 아래 단계로 진행됩니다.

  1. 캐시는 응답 데이터에 식별이 가능한 객체에 대해 고유한 ID를 생성합니다.
  2. 캐시는 플랫 룩업 테이블에 ID별로 객체를 저장하게 됩니다.
  3. 들어오는 객체는 기존객체와 동일한 ID로 확인하여 객체 병합됩니다.
    • 들어오는 객체와 기존 객체의 필드를 공유하는 경우 들어오는 객체는 해당 필드의 캐시값 덮어 씌웁니다.
    • 기존 객체 또는 들어오는 객체에만 나타나는 필드는 유지 됩니다.

정규화는 애플리케이션의 상태를 변경하게 될때에 그래프를 읽고 업데이트하는데 최적화 된 형식으로 클라이언트에서 데이터 그래프를 부분 복사하여 구성하게 됩니다.

fetchPolicy

 

  • cache-first: 항상 Cache를 먼저 확인한다. Cache 데이터가 없을경우 network 요청
  • network-first: Cache에서 초기데이터를 반환하지 않고 항상 network 요청
  • cache-only: Cache만 확인. Cache에 데이터가 없을 경우 Error를 반환한다.
  • cache-and-network: Cache를 확인하여 데이터를 반환. 이후 network요청을 하여 새로운 데이터를 가져와 Cache를 업데이트하며 Cache 데이터를 다시 반환한다.
  • no-cache: Cache를 확인하지 않고 항상 network 요청을 한다. network-only 정책과 달리 쿼리가 완료된 후 Cache 데이터를 읽지 않는다.