리액트 쿼리의 캐시에 대해서 알아보자!!🔥🔥🔥🔥
백엔드 측에서 데이터를 가져오는 일은 시간이 꽤 걸리는 일이다. 유저가 만약 방금전 확인한 데이터를 중복해서 보는 경우 매번 똑같은 데이터를 받아야하기에 속도가 저하되고 불필요한 네트워크 비용이 발생한다.
이 상황을 방지하기 위해 유저가 자주 보는 데이터를 어딘가 저장해 두어 데이터를 따로 요청할 필요 없이 바로 보여주기 위해 캐시
를 사용한다.
캐시란 데이터를 미리 복사해 놓는 임시 장소를 얘기한다.
저장 공간의 크기는 작지만 데이터를 가져오는 속도는 빠르다는 특징이 있다.
웹 브라우저는 캐시를 사용해 속도를 높여 네트워크 비용을 아끼고 사이트를 접속하여 받아 온 데이터를 캐시 형태로 저장해 사용자가 같은 사이트에 접속하면
서버에서 매번 데이터를 다시 요청하지 않고 저장해 놓은 데이터를 보여준다
이렇게 캐시를 사용하는 행위를 캐싱
이라고 한다.
리액트 쿼리에도 캐싱을 지원한다. 다만 이 사이클을 이해하기 위해서 우린
리액트 쿼리에서 진행되는 데이터 라이프 사이클을 이해해야한다.
useQuery
는 queryKey
, queryFn
이 두가지를 이용해서 데이터를 받아온다.
하지만 바로 쿼리 함수가 실행되어 데이터를 받아오지 않는다
쿼리 키로 인해 쿼리 함수에서 불러온 데이터가 캐시에 저장되었다.
이때 우리는 useQuery
의 동작이 어떻게 되는지 잠깐 살펴보자
useQuery
는 먼저 전달받은 쿼리 키로 캐시에 저장된 데이터가 있는지 확인을 먼저한다.
만약 저장되어 있는 데이터가 없다면 쿼리 함수를 실행하여 데이터를 받아온다.
그 후 우리가 지정한 queryKey
에 데이터를 캐시로 저장한다.
useQuery
함수가 실행 되었는데 이미 queryKey
가 저장되어 있다면 데이터의 상태에 따라 다르게 동작한다.
쿼리키가 있어 데이터가 캐시에 저장되어 있을 때, 이제 막 받아온 데이터의 상태를 fresh
라고 표현한다.
데이터를 받아와 특정 시간이 지나면 Stale
상태가 된다. 이 상태에선 데이터를 다시 받와오는 행동 refetch
를 진행하는데 네 가지 상황에서 다르게 진행된다.
refetchOnMount
: 새로운 쿼리 인스턴스가 마운트 될 때refetchOnWindowFocus
: 브라우저 창에 다시 포커스가 될 때refetchOnReconnect
: 네트워크가 다시 연결될 때refetchInterval
: 미리 설정해 둔 refetch interval
시간이 지났을 때4가지 상황을 판단하고 변경하고 싶다면 옵션을 수정하면 된다.
컴포넌트가 언마운트(DOM 트리에서 제거)가 된다면 해당 데이터가 쓰이지 않는 상태로 판단 inactive
상태가 된다.
위 상황을 정리해보자면 쿼리 키로 저장된 데이터가 존재한다면 useQuery
는 캐시에 저장되어 있는 데이터를 리턴
이때 데이터가 fresh
상태라면 캐시에 저장된 데이터를 리턴 stale
상태라면 백그라운에서 refetch
를 진행한다.
Stale Time 은 얼만큼의 시간일까?
리액트 쿼리에서 디폴트 값으로 0으로 설정되어 있다.
그렇기에 모든 데이터는 받아왔을 때부터 바로 stale
상태가 된다.
그렇기에 매번 데이터가 필요할 때마다 refetch
를 진행한다. 구현되는 사이트가 매번 refetch
가 필요 없다면 stale 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초다.
UseQuery()
가 실행되는 컴포넌트가 마운트되면 함수가 실행되어 데이터를 받아온다.
데이터는 useQuery()
가 지정한 쿼리 키를 이용해 캐시에 저장하는 행위 “캐싱”
을 진행한다.
캐시에 저장된 데이터는 fresh
상태에서 staleTime
이 지나면 stale
상태로 변경된다.
사용자가 다시 데이터를 요청하면 캐시된 데이터를 먼저 보여준다.
데이터가 fresh
상태라면 refetch
를 진행하지 않고 stale
상태라면 refetch
를 진행한다.
5-1. refetch
를 진행한 상태라면 새로운 데이터로 사용자에게 보여준다.
컴포넌트가 언마운트된 데이터가 inactive
상태라면 가비지 컬렉션 타임
(gcTime) 동안 캐시에 저장되어 있다 삭제된다.