SWR은 최신 데이터가 도착하기 전까지 기존 캐시 데이터를 사용하는 전략이다. 이를 통해 사용자는 최신 데이터를 기다리는 동안에도 빠른 응답을 받을 수 있다. TanStack Query는 이 SWR 전략을 사용하여 효율적으로 데이터를 관리한다. 그렇다면 캐시 데이터는 어디에 보관할까?
TanStack Query는 캐시 데이터를 전역적으로 관리한다. QueryClientProvider를 사용하여 React 애플리케이션 전체에서 캐시 데이터에 접근할 수 있다.
이렇게 될 수 있는 이유는 TanStack Query는 내부적으로 React Context API를 사용하여 구현되며, 모든 자식 컴포넌트가 캐시 데이터에 접근할 수 있기 때문이다.

TanStack Query의 생명주기는 데이터가 캐시되고, 사용되고, 갱신되는 과정을 포함한다.
| 상태 | 설명 |
|---|---|
| fresh | 데이터를 새로 패칭할 필요가 없는 상태이다. staleTime이 지나지 않은 상태로, 캐시 데이터를 그대로 사용할 수 있다. |
| stale | 데이터를 새로 패칭해야 하는 상태이다. staleTime이 지난 후로, 새로운 데이터를 가져오기 위해 쿼리가 실행된다. |
| active | 현재 컴포넌트에서 사용 중인 쿼리 상태이다. 컴포넌트가 마운트되어 쿼리를 사용하고 있을 때를 말한다. |
| inactive | 더 이상 사용되지 않는 쿼리 상태이다. 컴포넌트가 언마운트되거나 쿼리가 더 이상 필요하지 않을 때를 말한다. |
| deleted | 캐시에서 제거된 쿼리 상태이다. gcTime 이 지나면 쿼리가 캐시에서 삭제되어 이 상태가 된다. |
| fetching | 데이터를 서버에서 가져오고 있는 상태이다. 이 상태에서는 isFetching이 true로 설정된다. |
| 기본 설정 | 의미 |
|---|---|
| staleTime: 0 | useQuery 또는 useInfiniteQuery에 등록된 queryFn 을 통해 fetch 받아온 데이터는 항상 stale data 취급 |
| refetchOnMount: true | useQuery 또는 useInfiniteQuery 가 있는 컴포넌트가 마운트 시 stale data 를 refetch 자동 실행 |
| refetchOnWindowFocus: true | 실행중인 브라우저 화면을 focus 할 때 마다 stale data를 refetch 자동 실행 |
| refetchOnReconnect: true | Network 가 끊겼다가 재연결 되었을 때 stale data를 refetch 자동 실행 |
| gcTime(cacheTime): 5분(1000 60 5 ms) | useQuery 또는 useInfiniteQuery가 있는 컴포넌트가 언마운트 되었을 때 inactive query라 부르며, inactive 상태가 5분 경과 후 GC(가비지콜렉터)에 의해 cache data 삭제 처리 |
| retry: 3 | useQuery 또는 useInfiniteQuery에 등록된 queryFn 이 API 서버에 요청을 보내서 실패하더라도 바로 에러를 띄우지 않고 총 3번까지 재요청을 자동으로 시도 |
enabled 옵션은 쿼리(queryFn) 실행 여부를 제어한다. 기본값은 true이며, false로 설정하면 쿼리가 자동으로 실행되지 않는다. 이 옵션을 사용하여 특정 이벤트 발생 시 쿼리를 실행할 수 있다.
useQuery({
queryKey: ["todos"],
queryFn: getTodos,
enabled: true // boolean
})
select 옵션은 쿼리 함수에서 반환된 데이터를 변형하여 사용할 수 있도록 한다. 데이터의 특정 부분만 선택하거나, 데이터를 변환하여 사용할 때 유용하다. 단, 캐시 데이터는 원본 데이터를 유지한다.
import { useQuery } from 'react-query'
function User() {
const { data } = useQuery({
queryKey: ["user"],
queryFn: fetchUser,
select: user => user.username
});
return <div>Username: {data}</div>
}