React Query Cache

준성·2024년 4월 9일
0
post-thumbnail

리액트 쿼리의 캐시에 대해서 알아보자!!🔥🔥🔥🔥

개요


백엔드 측에서 데이터를 가져오는 일은 시간이 꽤 걸리는 일이다. 유저가 만약 방금전 확인한 데이터를 중복해서 보는 경우 매번 똑같은 데이터를 받아야하기에 속도가 저하되고 불필요한 네트워크 비용이 발생한다.
이 상황을 방지하기 위해 유저가 자주 보는 데이터를 어딘가 저장해 두어 데이터를 따로 요청할 필요 없이 바로 보여주기 위해 캐시를 사용한다.

캐시


캐시란 데이터를 미리 복사해 놓는 임시 장소를 얘기한다.
저장 공간의 크기는 작지만 데이터를 가져오는 속도는 빠르다는 특징이 있다.
웹 브라우저는 캐시를 사용해 속도를 높여 네트워크 비용을 아끼고 사이트를 접속하여 받아 온 데이터를 캐시 형태로 저장해 사용자가 같은 사이트에 접속하면
서버에서 매번 데이터를 다시 요청하지 않고 저장해 놓은 데이터를 보여준다
이렇게 캐시를 사용하는 행위를 캐싱 이라고 한다.

데이터 라이프 사이클


리액트 쿼리에도 캐싱을 지원한다. 다만 이 사이클을 이해하기 위해서 우린
리액트 쿼리에서 진행되는 데이터 라이프 사이클을 이해해야한다.
useQueryqueryKey, queryFn 이 두가지를 이용해서 데이터를 받아온다.
하지만 바로 쿼리 함수가 실행되어 데이터를 받아오지 않는다

useQuery 동작원리

쿼리 키로 인해 쿼리 함수에서 불러온 데이터가 캐시에 저장되었다.
이때 우리는 useQuery 의 동작이 어떻게 되는지 잠깐 살펴보자

useQuery는 먼저 전달받은 쿼리 키로 캐시에 저장된 데이터가 있는지 확인을 먼저한다.
만약 저장되어 있는 데이터가 없다면 쿼리 함수를 실행하여 데이터를 받아온다.
그 후 우리가 지정한 queryKey 에 데이터를 캐시로 저장한다.
useQuery 함수가 실행 되었는데 이미 queryKey 가 저장되어 있다면 데이터의 상태에 따라 다르게 동작한다.

fresh

쿼리키가 있어 데이터가 캐시에 저장되어 있을 때, 이제 막 받아온 데이터의 상태를 fresh 라고 표현한다.

Stale

데이터를 받아와 특정 시간이 지나면 Stale 상태가 된다. 이 상태에선 데이터를 다시 받와오는 행동 refetch 를 진행하는데 네 가지 상황에서 다르게 진행된다.

  1. refetchOnMount : 새로운 쿼리 인스턴스가 마운트 될 때
  2. refetchOnWindowFocus : 브라우저 창에 다시 포커스가 될 때
  3. refetchOnReconnect : 네트워크가 다시 연결될 때
  4. refetchInterval : 미리 설정해 둔 refetch interval 시간이 지났을 때

4가지 상황을 판단하고 변경하고 싶다면 옵션을 수정하면 된다.

inactive

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

정리

위 상황을 정리해보자면 쿼리 키로 저장된 데이터가 존재한다면 useQuery 는 캐시에 저장되어 있는 데이터를 리턴
이때 데이터가 fresh 상태라면 캐시에 저장된 데이터를 리턴 stale 상태라면 백그라운에서 refetch 를 진행한다.

Stale Time


Stale Time 은 얼만큼의 시간일까?
리액트 쿼리에서 디폴트 값으로 0으로 설정되어 있다.
그렇기에 모든 데이터는 받아왔을 때부터 바로 stale 상태가 된다.
그렇기에 매번 데이터가 필요할 때마다 refetch를 진행한다. 구현되는 사이트가 매번 refetch가 필요 없다면 stale Time 옵션 값을 변경하면 된다.

Garbage Collection Time


캐시에 저장되어 있는 데이터는 영영 캐시에 남을까? 앞서 설명한 것 처럼 캐시에 저장공간은 한정적이다.

그렇기에 필요 없는 데이터는 삭제해 다른 데이터가 사용할 수 있게 공간을 마련해야한다.

리액트 쿼리에선 필요 없는 데이터를 알아서 정리해주는데 inactive 상태를 위에서 설명했다 그 상태가 된다면

그 상태의 데이터는 가비지 컬렉션 타임이 지나면 캐시에서 삭제가 된다. 디폴트 값으로 5분으로 설정되어 있어 수정하고 싶다면 값을 변경하면 된다.

라이플 사이클 시간 설정


리액트 쿼리에 기본 staleTime 은 0, gcTime (가비지 컬렉션 타임) 은 5분이다. staleTime 은 0 이기에 매번 서버에서 데이터를 다시 받아온다.

따라서 이를 변경하기 위해 staleTime 옵션 값을 변경해주면 그 시간 만큼 fresh 상태로 유지할 수 있다.gcTime 도 이러한 옵션 값을 수정해

임의적으로 시간을 설정할 수 있다. 아래는 예제 코드로 옵션 값을 설정하는 법을 작성해본다.

function HomePage() {
  const result = useQuery({
    queryKey: ['posts'],
    queryFn: getPosts,
    staleTime: 60 * 1000, // 1분은 60초 따라서 1분을 설정하려면 1000 (1초) * 60
        gcTime: 60 * 1000 * 10, // 10분으로 설정하려면 위와 같이 1분으로 지정한 값을 10으로 곱하면 된다.
  });
  console.log(result);

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

둘의 옵션 값은 밀리초(ms)가 기준이기에 1000 이 1초다.

정리


다이어그램

  1. UseQuery() 가 실행되는 컴포넌트가 마운트되면 함수가 실행되어 데이터를 받아온다.

  2. 데이터는 useQuery() 가 지정한 쿼리 키를 이용해 캐시에 저장하는 행위 “캐싱” 을 진행한다.

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

  4. 사용자가 다시 데이터를 요청하면 캐시된 데이터를 먼저 보여준다.

  5. 데이터가 fresh 상태라면 refetch 를 진행하지 않고 stale 상태라면 refetch 를 진행한다.

    5-1. refetch 를 진행한 상태라면 새로운 데이터로 사용자에게 보여준다.

  6. 컴포넌트가 언마운트된 데이터가 inactive 상태라면 가비지 컬렉션 타임 (gcTime) 동안 캐시에 저장되어 있다 삭제된다.

profile
코드를 그리다.

0개의 댓글