Frontend/Apollo

Apollo Client 캐시 동작과 관리 방법

wam 2024. 9. 29. 20:00

 

Apollo Client의 캐시

 

  • GraphQL 데이터를 효율적으로 저장하고 관리하기 위한 메커니즘이다.
  • 이를 통해 네트워크 요청을 최소화하고, 사용자 경험을 개선할 수 있다.
  • Apollo Client의 기본 캐시는 InMemoryCache로, 이는 데이터를 메모리에 저장하고, 이를 통해 빠르게 데이터에 접근할 수 있다.

 

 

주요 특징과 사용 방법

 

기본적인 캐싱 동작

 

  • Apollo Client는 쿼리 요청 시 서버로부터 데이터를 받아 캐시에 저장한다.
  • 이후 동일한 쿼리가 발생하면 캐시에서 데이터를 불러오기 때문에 네트워크 요청을 다시 보내지 않아도 된다.

 

 

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

const client = new ApolloClient({
  uri: '<https://example.com/graphql>',
  cache: new InMemoryCache(),
});

client.query({
  query: gql`
    query GetUsers {
      users {
        id
        name
      }
    }
  `,
});

여기서 InMemoryCache가 쿼리 결과를 캐시에 저장하고, 이후 동일한 쿼리 요청이 있으면 캐시에서 바로 데이터를 반환한다.

 

 

캐시 정책

 

Apollo Client는 여러 캐시 정책을 통해 네트워크 요청과 캐시 동작을 제어할 수 있다:

  • cache-first: 기본 설정. 캐시에 데이터가 있으면 네트워크 요청을 보내지 않는다.
  • network-only: 항상 네트워크 요청을 보내고, 응답을 받은 후 캐시에 저장한다.
  • cache-only: 오직 캐시에서만 데이터를 가져온다.
  • no-cache: 캐시를 사용하지 않고 네트워크 요청만을 사용한다.

 

 

client.query({
  query: gql`
    query GetUsers {
      users {
        id
        name
      }
    }
  `,
  fetchPolicy: 'network-only', // 네트워크에서만 데이터 가져오기
});

 

 

캐시 관리

 

자동 업데이트

  • Apollo Client는 GraphQL 객체의 id 필드와 __typename을 기반으로 캐시를 자동으로 업데이트한다.
  • 이를 통해 쿼리나 변이 요청 후 캐시에 있는 관련 데이터를 자동으로 갱신할 수 있다.
const cache = new InMemoryCache({
  typePolicies: {
    User: {
      keyFields: ['id'], // 캐시에서 id를 기반으로 유저를 식별
    },
  },
});

 

 

수동 업데이트

  • 때로는 쿼리나 변이 결과에 따라 캐시를 수동으로 업데이트해야 할 때도 있다.
  • 이를 위해 cache.writeQuery, cache.writeFragment, cache.modify와 같은 메서드를 사용한다.
// 특정 변이 후 캐시 업데이트
client.mutate({
  mutation: gql`
    mutation AddUser($name: String!) {
      addUser(name: $name) {
        id
        name
      }
    }
  `,
  update(cache, { data: { addUser } }) {
    cache.modify({
      fields: {
        users(existingUsers = []) {
          const newUserRef = cache.writeFragment({
            data: addUser,
            fragment: gql`
              fragment NewUser on User {
                id
                name
              }
            `,
          });
          return [...existingUsers, newUserRef];
        },
      },
    });
  },
});

 

 

캐시 초기화 및 재설정

  • cache.reset()은 캐시를 초기화할 때 사용된다.
  • 이는 일반적으로 사용자가 로그아웃하거나 세션이 만료되었을 때 캐시를 비울 필요가 있을 때 사용된다.
client.cache.reset(); // 캐시 초기화

 

 

InMemoryCache 구성 요소

 

Normalization:

  • GraphQL의 구조화된 데이터는 id와 __typename을 이용해 캐시에 효율적으로 저장된다.
  • 이를 통해 중복 데이터가 최소화된다.

 

 

Field Policies

  • 특정 필드에 대한 캐시 동작을 커스터마이징할 수 있다.
  • 예를 들어, 페이지네이션 데이터는 특정 방식으로 병합해야 할 수 있다.
const cache = new InMemoryCache({
  typePolicies: {
    Query: {
      fields: {
        users: {
          keyArgs: false, // keyArgs: false 설정하면 페이지네이션 처리 가능
          merge(existing = [], incoming) {
            return [...existing, ...incoming];
          },
        },
      },
    },
  },
});

이러한 캐시 기능을 통해 Apollo Client는 네트워크 요청을 줄이고, 빠르게 데이터를 제공할 수 있다.