본문 바로가기

카테고리 없음

TIL -커뮤니티 게시판 로딩 최적화 트러블 슈팅

문제 상황

  • TanStack Query로 커뮤니티 게시판 카테고리별 로딩 시 초기 데이터 매번 로딩 화면 표시
  • 사용자 경험 저하 우려

의사 결정 과정 및 해결 방안

  1. 문제 인식: 반복되는 로딩 화면이 사용자 경험에 부정적 영향
  2. 해결 방안 검토:
    • SSR로 초기 데이터를 props로 전달
    • 하이드레이션을 통한 로딩
    • 카테고리별 프리페칭
  3. 최종 결정: 카테고리별 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 구조화로 효율적인 쿼리 관리