TanStack Query의 staleTime과 gcTime 정리
staleTime과 gcTime(v4까지는 cacheTime)은 이름이 비슷하지만 제어하는 대상이 다르다.
staleTime: 데이터를 언제 다시 가져올지gcTime: 아무도 쓰지 않는 데이터를 얼마나 오래 보관할지
staleTime: 언제 다시 가져올까
fetch한 데이터가 fresh(신선) 상태로 유지되는 시간이다.
fetch 완료 ──[fresh: staleTime]──▶ stale
fresh인 동안은 컴포넌트가 마운트되거나 창에 포커스가 돌아와도 다시 요청하지 않는다. stale이 되면 다음 트리거(마운트, 창 포커스, 네트워크 재연결) 때 백그라운드 refetch가 일어난다. 캐시된 데이터를 먼저 보여주고 뒤에서 새 데이터를 받아 교체하는 방식이라, 사용자는 로딩 없이 화면을 본다.
기본값 0
fetch가 끝나는 즉시 stale이 된다. 캐시가 있어도 마운트할 때마다 백그라운드 refetch가 일어난다.
staleTime: 0; // 기본값. 트리거마다 최신화
staleTime: 5 * 60 * 1000; // 5분간 fresh. 코드 목록·설정값처럼 잘 안 바뀌는 데이터
staleTime: Infinity; // 자동 refetch 없음. invalidate나 refetch()로만 갱신
Infinity여도 invalidateQueries나 refetch()를 호출하면 다시 가져온다. "자동으로는 다시 가져오지 않는다"는 뜻이다.
gcTime: 얼마나 오래 보관할까
쿼리를 구독하는 컴포넌트가 모두 언마운트되어 inactive가 된 뒤, 캐시에서 삭제되기까지의 시간이다.
마지막 구독자 언마운트 ──[inactive: gcTime]──▶ 캐시 삭제
구독자가 하나라도 있으면 타이머가 돌지 않는다.
기본값 5분
언마운트 후에도 5분간 캐시를 남겨 둔다. 그 안에 다시 방문하면 저장된 데이터를 즉시 보여주고, stale이라면 백그라운드 refetch도 함께 실행된다. (SSR 서버 쪽에서는 기본값이 Infinity다.)
gcTime: 0; // inactive 되는 즉시 삭제. 다음 마운트는 항상 로딩부터
gcTime: Infinity; // 삭제하지 않음. 메모리 사용량 주의
한눈에 비교
| 항목 | staleTime | gcTime |
|---|---|---|
| 제어 대상 | 자동 refetch 여부 | inactive 캐시 보관 기간 |
| 기준 시점 | 마지막 fetch 완료 | 마지막 구독자 언마운트 |
| 기본값 | 0 | 5분 |
0일 때 | 트리거마다 백그라운드 refetch | inactive 즉시 삭제 |
Infinity일 때 | 자동 refetch 없음 | 삭제하지 않음 |
자주 쓰는 조합
staleTime 0 + gcTime 5분 (기본)
화면에 있는 동안 트리거마다 최신화하고, 떠났다가 5분 안에 돌아오면 이전 데이터를 즉시 보여준 뒤 갱신한다.
staleTime 5분 + gcTime 5분 이상
잘 바뀌지 않는 데이터. 5분 안에 다시 마운트하면 요청 자체를 보내지 않는다.
staleTime Infinity + gcTime 기본값
"한 번 받으면 명시적으로 무효화하기 전까지 그대로 쓴다". 변경 시점을 앱이 알고 있는 데이터(사용자가 직접 수정하는 설정 등)에 쓰고, 수정 후 invalidateQueries로 갱신한다.
staleTime 0 + gcTime 0
캐시 재사용 없이 마운트할 때마다 로딩부터 새로 받는다. 탭이나 카드를 전환할 때 이전 값이 잠깐이라도 보이면 안 되는 화면에 쓴다.
카드 A 선택 → fetch → 카드 B 선택 (A는 inactive → 즉시 삭제) → 카드 A 재선택 → 로딩 후 fetch
gcTime이 기본값이면 A를 다시 선택했을 때 이전 A 데이터가 먼저 보이고 뒤에서 갱신된다. 이 "이전 데이터 → 새 데이터" 전환 시점에 로컬 상태를 초기화하는 로직이 엮여 있으면, 순서에 따라 엉뚱한 값이 남을 수 있다.
staleTime이 gcTime보다 길면?
문제없는 조합이다. 두 타이머는 서로 다른 구간에서 동작한다. 화면에서 쓰는 동안(active)은 staleTime만 의미가 있고, 아무도 쓰지 않을 때(inactive)는 gcTime이 흐른다. staleTime: Infinity + 기본 gcTime은 공식 문서에도 나오는 흔한 설정이다. 다만 inactive 상태에서 gcTime이 지나 캐시가 지워지면, 남은 staleTime과 관계없이 다음 마운트는 새로 요청한다.
요약
- 얼마나 자주 다시 가져올지 →
staleTime - 안 쓰는 데이터를 얼마나 들고 있을지 →
gcTime