1. 과정
1. 프로필 데이터 불러오기
export const useGetProfile = () =>
useSuspenseQuery(Keys.getProfile(), getProfile,
staleTime: Infinity,
});
export const useGetProfileById = (userId: number) =>
useSuspenseQuery(Keys.getProfileById(userId),
staleTime: Infinity,
});
프로필 데이터는, 본인이 직접 바꾸지 않는 한 데이터가 바뀌지 않는다. 그래서, 프로필 수정을 했을 경우에만 데이터를 서버에서 다시 받아오면 된다.
- staleTime을
Infitnity로 설정했다. - 즉, 서버로부터 전달받은 데이터는 영원히 fresh상태이며, 캐싱된 데이터라 사라지지 않는 한 데이터를 refetch하지 않는다.
- 캐싱된 데이터가 사라지는 경우 : 웹사이트 종료되어 QueryClient객체가 사라졌을 때
❓ cache? stale?
cache: cacheTime만큼 데이터를 메모리에 저장
- reaat-query에서 cache : QueryCache객체의 queries배열과 queriesInMap객체에 Query 객체가 존재하는 것
- cache가 존재하더라도 해당 데이터가 stale상태라면 refetch를 수행한다
stale: staleTime만큼 데이터가 fresh상태로 존재하였다가 그 후에는 stale 상태로 바꾼다
정리하자면, staleTime은 데이터를 refetch하기까지의 시간이고, cacheTime은 캐싱된 데이터가 보존되기 까지의 시간이다. 즉, cacheTime이 만료되지 않더라도 staleTime이 지났다면 데이터를 재요청한다.
위 그림처럼 데이터를 요청하고 나면 데이터는 fresh상태가 된다. 그리고, staleTime이 지나면 stale상태가 된다.
2. invalidateQueries를 통해 캐시를 초기화
export const usePatchProfile = () => {
const queryClient = useQueryClient();
const { back } = useAppRouter();
return useMutation(patchProfile, {
onSuccess: () => {
queryClient.invalidateQueries(Keys.getProfile());
back();
},
});
};
queryClient.invalidateQueries를 사용하여 캐싱된 데이터를 초기화하여, 데이터를 refetch한다.
❓ 그렇다면, Stale과 Cache 두 개가 있을 필요가 있을까?
stale없이 cache만으로 데이터를 관리할 경우, 데이터를 받아오는 ‘로딩’상태가 생기게 된다.
새로운 데이터를 받아올 때를 가정해보자.
- stale과 cache가 모두 존재한다면, 데이터를 받아오는 동안 staleTime은 지났지만, cacheTime은 지나지 않은 stale캐싱 값을 보여주면 된다.
- cache만 존재한다면, 데이터를 받아오는 동안 보여줄 데이터가 없다. 로딩 화면을 보여줘야한다. 왜냐하면 cacheTime이 지난 데이터는 폐기했기 때문이다.
이러한 이유로 react-query는 stale과 cache 두 개로 나누어 캐싱 데이터를 관리한다.
2. 결론
무조건 staleTime은 1분. 이런 식으로 정해놓고 하는 것이 아니라, 데이터의 성격에 따라 다시 불러올 것인지, 상황에 따라서 데이터를 불러올 것인지 고려를 하면서 개발을 하면 더 효율적인 데이터 요청을 할 수 있을 것이라 생각했다.