컨텐츠를 불러오는 중...
tanstack query
를 활용하여 캐싱을 진행해야 겠다고 판단 했습니다. 사용자의 상태가 변화되지 않았을 경우 새로운 네트워크 요청은 불필요하기 때문에 를 활용하여 캐싱을 진행하는 것이 좋을 것이라고 판단하였습니다. 또한 불필요한 인증 요청을 줄이면서도 필요할 때 (예: 로그아웃, 세션 만료 등) 자동으로 캐시를 무효화하는 방법을 이용하여 성능을 개선 시키고자 하였습니다.QueryClient
라는 중앙 관리자가 존재합니다. 해당 중앙 관리자는 QueryCache
라는 특별한 저장소를 생성하여 데이터를 관리합니다.QueryClient
입니다. 쿼리문 내에서의 모든 작업들은 QueryClient
를 중심으로 작업이 이루어지고 있다는 것을 알 수 있습니다.정적인
특성은 오히려 코드의 예측 가능성과 유지보수성을 높여주는 장점이 되기도 합니다.prefetchQuery
를 이용하여 데이터를 미리 불러오고 prefetching 시 queryKey 를 이용하여 해당 데이터를 캐싱할 수 있습니다.낙관적 업데이트
가 유용한 경우입니다. 낙관적 업데이트는 무엇일까요?- Caching... (possibly the hardest thing to do in programming)
- Deduping multiple requests for the same data into a single request
- Updating "out of date" data in the background
- Knowing when data is "out of date"
- Reflecting updates to data as quickly as possible
- Performance optimizations like pagination and lazy loading data
- Managing memory and garbage collection of server state
- Memoizing query results with structural sharing
const result = await context.queryClient.ensureQueryData(authQueries);
const parsedResult = AuthStatusTypeSchema.safeParse(result);
if (!parsedResult.success) {
return {
isAuthenticated: false,
userInfo: {
message: "로그인이 필요합니다.",
role: "guest",
nickname: "",
duck: 0,
},
};
}
function TodoList() {
const { data } = useQuery({
queryKey: ["todos"],
queryFn: fetchTodos,
// 선언적 캐싱 설정
gcTime: 5 * 60 * 1000, // 5분
staleTime: 30 * 1000, // 30초
retry: 3, // 실패시 3번 재시도
refetchOnMount: true, // 컴포넌트 마운트시 재요청
refetchOnWindowFocus: true, // 윈도우 포커스시 재요청
});
}
const prefetchNextPage = async (currentPage) => {
const nextPage = currentPage + 1;
// 다음 페이지 데이터를 미리 가져와서 캐시에 저장
await queryClient.prefetchQuery({
queryKey: ["items", nextPage],
queryFn: () => fetchItems(nextPage),
staleTime: 30 * 1000, // 30초 동안 신선한 상태 유지
});
};
// 특정 조건에 따른 캐시 무효화
const invalidateMatchingQueries = async (category) => {
await queryClient.invalidateQueries({
predicate: (query) =>
query.queryKey[0] === "items" && query.queryKey[1].category === category,
});
};
// tanstack query
const { data } = useSuspenseQuery({
queryKey: bettingRoomQueryKey(roomId),
queryFn: () => getBettingRoomInfo(roomId),
staleTime: 1000 * 60 * 5, // ttl 시간을 설정
});
// swr
const { data, error } = useSWR("/api/data", fetcher, {
refreshInterval: 3000, // ttl 시간을 설정
});
component: () => (
<QueryClientProvider client={queryClient}>
{" "}
<LayoutProvider>
{" "}
<RootLayout>
<RootHeader />
<RootSideBar />
<Outlet /> {" "}
</RootLayout>
{" "}
</LayoutProvider>
{" "}
</QueryClientProvider>
);