[React-query] 캐싱 (Caching)

SoShy·2024년 5월 8일

React-Query

목록 보기
5/13
post-thumbnail

🏷️ 캐시 (Cache)


캐시란 데이터를 미리 복사해 놓은 임시 장소를 말한다.

보통 저장 공간의 크기는 작지만, 데이터를 가져오는 속도는 아주 빠르다는 특징이 있다.

때문에, 자주 사용하는 데이터를 캐시에 저장해두면, 해당 데이터를 훨씬 빠르게 가져와서 사용할 수 있다.

웹 브라우저는 기본적으로 캐시를 사용해서 속도를 높이고 네트워크 비용을 아낀다.

웹 브라우저는 사이트에 접속했을 때 받아 온 데이터를 캐시 형태로 저장해서, 사용자가 같은 사이트에 접속하면, 서버에 매번 데이터를 다시 요청하는 게 아닌 저장해놓은 데이터를 유저에게 보여주는데,

이렇게 캐시를 사용하는 것을 캐싱이라고 한다.



🏷️ React-query의 캐싱


React-query 역시, 매번 데이터를 백엔드에서 받아오는 게 아니라, 캐시에 저장되어 있는 데이터를 유저에게 보여주기도 한다.

그렇다면, 언제 데이터를 백엔드에서 다시 받아오는 refetch를 하고, 언제 캐시에 저장되어 있는 데이터를 보여주는 것일까?

이를 이해하기 위해서는, 우선 React-query의 data life cycle을 이해해야 한다.

아래 코드를 보면, HomePage라는 컴포넌트가 렌더링되면, useQuery()가 실행되고, 여기서 쿼리 함수로 설정한 getPosts() 함수를 통해 백엔드로부터 post 데이터를 받아온다.

function HomePage() {
  const result = useQuery({ queryKey: ['posts'], queryFn: getPosts });
  console.log(result);

  return <div>홈페이지</div>;
}

여기서, 한 가지 주의해야 할 점이 있는데, useQuery()를 사용한다고 무조건 쿼리 함수가 실행되어 백엔드로부터 데이터를 받아오는 것은 아니라는 것이다.

위 코드를 다시보면, useQuery()에서 쿼리 함수 말고도 쿼리 키를 설정해두었다.

React-query 개발자 도구를 열어보면, 현재 캐시에 저장되어 있는 데이터를 확인할 수 있는데,

여기에 ['posts']라는 쿼리 키로 받아온 post 데이터가 캐시에 저장되어 있는 것을 볼 수 있다.

useQuery()는 먼저 전달받은 쿼리 키로 캐시에 저장된 데이터가 있는 지를 확인한다.

만약, 저장되어 있는 데이터가 없다면 쿼리 함수를 실행해 데이터를 백엔드로부터 받아오게 되며, 그 후 쿼리 키(['post'])로 데이터를 캐시에 저장한다.

반대로, useQuery()가 실행되었는데, 이미 쿼리 키로 저장된 데이터가 캐시에 있다면 어떻게 될까?

React-query는 백엔드에서 이제 막 데이터를 받아와 캐시에 저장한 데이터는 fresh로 판단하며, stale time이라고 불리는 특정 시간이 지나면 데이터는 stale 상태가 된다.

이후, 컴포넌트가 언마운트되면 (DOM 트리에서 제거되면) 해당 데이터가 쓰이지 않는 상태가 되어서 데이터는 inactive 상태가 된다.

다시 본론으로 돌아와서, useQuery()가 실행되었는데, 이미 쿼리 키로 저장된 데이터가 있는 경우, useQuery는 캐시에 저장되어 있는 데이터를 리턴한다.

만약, 데이터가 fresh 상태라면 캐시에 저장된 데이터를 리턴하고 끝내지만,

데이터가 stale 상태라면 백그라운드에서 refetch를 진행하여, 백엔드에서 새로 받아온 데이터로 기존의 쿼리 키로 저장된 데이터를 갱신한다.

데이터가 stale 상태일 때, React-query는 기본적으로 다음 네 가지 상황에서 refetch를 진행하게 된다.

  • 새로운 쿼리 인스턴스가 마운트 되었을 때
  • 브라우저 창에 다시 포커스가 갔을 때
  • 네트워크가 다시 연결되었을 때
  • 미리 설정해 둔 refetch interval 시간이 지났을 때

이를 변경하고 싶다면, 각각 refetchOnMount, refetchOnWindowFocus, refetchOnReconnect, refetchInterval 옵션을 변경하면 된다.



🏷️ Stale Time


React-query에서는 디폴트 값으로 stale time이 0으로 설정되어 있다.

때문에, 사실상 모든 데이터는 백엔드에서 막 받아왔어도 바로 stale 상태가 되고, 데이터가 필요할 때마다 매번 refetch를 하게 된다.

만약, 구현하려는 사이트의 특성 상, 매번 refetch를 할 필요가 없는 상황이라면, stale time 값을 적절하게 변경해주는 것도 좋다.

Stale Time의 기본 값이 0인 이유

데이터를 항상 최신 상태로 유지함으로써, 클라이언트에게 신뢰성 있는 데이터를 제공해주기 위함이다. 또한, 데이터가 변경될 때마다 자동으로 업데이트를 요청할 수 있기 때문에, 애플리케이션의 반응성을 향상시킬 수 있다.



🏷️ Garbage Collection Time (gcTime)


캐시에 저장된 데이터는 영영 캐시에 남아있을까? 그렇지 않다.

캐시는 한정된 공간이기 때문에 필요없는 데이터는 삭제해서 다른 데이터가 사용할 수 있는 공간을 마련해주어야 하는데,

React-query는 이렇게 필요 없는 데이터를 삭제하는 것도 알아서 해준다.

쿼리 컴포넌트가 언마운트되어 해당 데이터가 쓰이지 않는 상황이 되면, 데이터는 inactive 상태가 되며, inactive 상태의 데이터는 garbage collection time이 지나면 캐시에서 삭제된다.

Garbage collection time은 기본적으로 5분으로 설정되어 있으며, 수정이 가능하다.



🏷️ Life Cycle 정리


  • useQuery()가 실행되는 컴포넌트가 마운트되면, useQuery()를 통해 쿼리 함수가 실행되고 데이터를 받아온다.

  • 받아온 데이터는 useQuery()에서 지정해 준 쿼리 키를 이용하여 캐싱된다.

  • 캐시에 저장된 데이터는 fresh 상태에서 staleTime이 지나면 stale 상태로 변경된다.

  • 유저가 데이터를 요청하게 되면, 캐시된 데이터를 먼저 보여주며, 이 때 데이터가 fresh 상태가 아닌 stale 상태라면 백그라운드에서 refetch를 진행한다.

  • refetch가 끝나면 새로운 데이터를 유저에게 보여준다.

  • 컴포넌트가 언마운트되어서 데이터가 inactive 상태가 되면 gcTime 동안 캐시에 저장되어 있다가, 그 이후에 garbage collector에 의해 삭제된다.



🏷️ Life Cycle 시간 설정


staleTimegcTime 설정은 다음 코드와 같이 해주면 되며, 둘 다 ms를 기준으로 한다.

function HomePage() {
  const result = useQuery({
    queryKey: ['posts'],
    queryFn: getPosts,
    staleTime: 60 * 1000,
        gcTime: 60 * 1000 * 10,
  });
  console.log(result);

  return <div>홈페이지</div>;
}
profile
프론트엔드 개발자가 되기 위해 노력 중인 새싹🌱 입니다.

0개의 댓글