
리액트 쿼리는 캐싱된 데이터를 gcTime과 staleTime으로 관리한다. gcTime은 메모리에 저장하는 시간이고, staleTime은 설정한 시간이 지나면 데이터를 fetch한다.
이렇게만 보면 gcTime과 staleTime이 구분되는 이유와 리액트 쿼리의 캐싱된 데이터 사용 과정을 한 번에 이해하기 어려울 수 있다. 그래서 gcTime과 staleTime의 개념을 더 자세히 알아보고자 한다.
gcTime의 gc는 가비지 콜렉션을 뜻하는 것으로, 4버전 이하에 존재했던 cacheTime을 5버전부터 이름만 바꾼 것이다.
gcTime은 비활성화된 데이터를 설정한 시간(기본 5분) 만큼 메모리에 저장하며, gcTime이 지나면 메모리에 있던 데이를 삭제하고 서버에 데이터를 요청하여 최신 데이터를 가져온다. 만약 gcTime을 infinity로 설정하면 가비지 콜렉터는 비활성화된다.
이때, gcTime을 카운트하는 시점의 기준은 캐싱된 데이터가 비활성화된 시점부터이다.

QueryInstance가 unmount되면 데이터는 inactive 상태로 변경된다. 이 시점부터 캐싱된 데이터는 gcTime만큼 메모리에 유지되고, gcTime이 지나면 가비지 콜렉터에 수집되어 메모리에서 데이터가 삭제된다.

만약 gcTime이 지나기 전에 QueryInstance가 다시 mount 되어 데이터가 다시 active 상태로 변하면, gcTime은 데이터가 inactive 되기 전까지는 중지된다. 이후 데이터가 다시 inactive로 변하면 리셋된 gcTime으로 카운트한다.
staleTime의 stale은 '신선하지 않은'이라는 뜻으로, 설정된 시간(기본값 0초) 만큼만 캐싱된 데이터를 fresh(신선한) 상태로 보고 staleTime이 지나면 데이터를 신선하지 않은 상태로 본다.
데이터가 fresh한 상태라면 기존 데이터를 그대로 사용하지만, staleTime이 지나고 stale한 데이터가 된다면 백그라운드에서 fetch를 수행한다.
사용자가 A 페이지에서 B 페이지로 이동 후 다시 A 페이지로 돌아왔다고 가정하자. 사용자가 페이지를 이동하는 사이 DB에 있던 데이터가 바뀌었고 서버에 fetch를 요청하여 최신 데이터를 요청해야한다. 이때 데이터를 요청하는 동안 사용자에게 로딩화면 대신 stale한 데이터를 보여준다. 그 후 fetch가 완료되면 fresh한 데이터를 보여주는 것이다.
리액트 쿼리는 마치 SWR처럼 작동하기 때문에 사용자의 경험을 개선할 수 있다.
gcTime과 staleTime에 대해 공부하던 중 한가지 궁금증이 생겼다.
데이터 업데이트 주기는
gcTime만으로 충분히 관리할 수 있지 않을까? 왜staleTime이 추가적으로 필요한걸까?
이는 Background re-fetching을 막기 위함이다. Background re-fetching은 캐싱된 데이터를 사용한 직후 다음과 같은 과정으로 항상 발생한다.
이 Background re-fetching은 gcTime이 지나지 않아도 암묵적으로 실행된다. 즉, 데이터 변화가 없어도 fetch가 일어나는 것이다. 이러한 불필요한 fetch를 방지하기 위해서 staleTime이 필요한 것이다.
staleTime을 설정함으로써 데이터가 fresh한 상태라면 Background re-fetching이 발생하지 않는다. 이후 데이터가 fresh하지 않은 상태가 되면 다시 암묵적인 Background re-fetching이 실행된다.
gcTime과 staleTime 설정 시 staleTime을 gcTime보다 작게 설정하는 것이 좋다. 그 이유는 다음과 같다.

gcTime이 지나면 캐싱된 데이터는 메모리에서 삭제된다. 즉 데이터의 fresh 상태 여부와 상관없이 오로지 gcTime을 기준으로 캐싱 데이터 삭제 여부가 결정된다.
만약 gcTime보다 staleTime을 더 길게 설정하면 데이터는 fresh한 상태임에도 불구하고 메모리에서 삭제되는 것이다. 이러한 경우는 리액트 쿼리의 캐싱 메커니즘을 제대로 활용하지 못하는 것이고 staleTime의 존재 이유도 사라지는 것이다.
캐싱 데이터를 제대로 활용하고 서버 요청을 줄이고 싶다면 gcTime보다 staleTime을 작게 설정해야 한다.
리액트 쿼리의 캐싱 메커니즘은 다음과 같이 진행된다.
staleTime 동안 데이터는 fresh 상태로 취급된다. staleTime이 지나면 데이터는 stale 상태가 된다. 만일 QueryInstance가 다시 mount 된다면 stale 데이터를 보여주며 백그라운드에서 fetch를 수행한다.gcTime을 경과했다면 캐싱 데이터는 가비지 콜렉터로 수집되고 메모리에서 삭제된다. 이후에 QueryInstance가 mount 된다면 서버에 데이터를 요청한다.📚[React Query] stale & cache 동작원리
📚[ReactQuery] StaleTime과 CacheTime에 대해서 알아보자
📚react-query | staleTime vs gcTime(cacheTime)
📚React Query 튜토리얼(3) - Background Refetch 옵션.md
📚React Query 의 동작원리
📚react-query 파보기 - 캐싱 라이프사이클