문제 상황
- TanStack Query로 커뮤니티 게시판 카테고리별 로딩 시 초기 데이터 매번 로딩 화면 표시
- 사용자 경험 저하 우려
의사 결정 과정 및 해결 방안
- 문제 인식: 반복되는 로딩 화면이 사용자 경험에 부정적 영향
- 해결 방안 검토:
- SSR로 초기 데이터를 props로 전달
- 하이드레이션을 통한 로딩
- 카테고리별 프리페칭
- 최종 결정: 카테고리별 1 페이지 단위 클라이언트 사이드에서 프리페칭 구현
- 이유: 초기 로딩 후 추가 로딩 최소화로 사용자 경험 개선
- 이유: 초기 로딩 후 추가 로딩 최소화로 사용자 경험 개선
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, error, prefetchAllCategories } =
useGetCommunityPosts(selectedCategory, categories.map((c) => c.value));
export const useGetCommunityPosts = (category: string, categories: string[]) => {
const queryClient = useQueryClient();
const query = useInfiniteQuery(queryOptions.posts(category));
const prefetchAllCategories = async () => {
const prefetchedCategories = queryClient.getQueryData(['prefetchedCategories']);
if (!prefetchedCategories) {
await prefetchCommunityPosts(queryClient, categories);
queryClient.setQueryData(['prefetchedCategories'], true);
}
};
return {
...query,
prefetchAllCategories,
};
};
export const prefetchCommunityPosts = async (queryClient: QueryClient, categories: string[]) => {
const prefetchPromises = categories.map((category) =>
queryClient.prefetchInfiniteQuery(queryOptions.posts(category)),
);
await Promise.all(prefetchPromises);
};
const queryOptions = {
posts: (category: string) => ({
queryKey: communityQueryKeys.posts(category),
queryFn: ({ pageParam = 1 }) => api.community.getPosts({ pageParam, category }),
initialPageParam: 1,
getNextPageParam: (lastPage: { data: CommunityPostData[]; page: number; limit: number }) => {
if (lastPage.data.length < lastPage.limit) {
return undefined;
}
return lastPage.page + 1;
},
staleTime: 5 * 60 * 1000, // 5 minutes
}),
};
const communityQueryKeys = {
posts: (category: string) => ['community', 'posts', category] as const,
};
- TanStack Query의 useInfiniteQuery를 활용한 무한 스크롤 구현
- prefetchAllCategories 함수로 모든 카테고리의 첫 페이지 데이터 프리페칭
- staleTime 설정으로 불필요한 리페칭 방지
- queryKey 구조화로 효율적인 쿼리 관리