Skip to content

prefetchQuery 와 suspense

Jooyeob Na edited this page Dec 4, 2024 · 1 revision

prefetchQuery 와 ensureQueryData

Tanstack Query 에는 비동기 데이터를 캐싱하고, 관리하는 많은 도구가 있다.
그중 prefetchQueryensureQueryData 를 적절히 선택해 사용해보려고 한다.


prefetchQuery

  • 쿼리가 필요해지거나, useQuery 친구들이 포함된 컴포넌트가 렌더링되기 전에 미리 데이터를 가져오는 비동기 메서드이다.
  • 데이터를 불러와 캐싱하고, queryKey 가 동일한 쿼리가 실행되면 이 캐싱된 데이터를 사용하게 된다.
  • Promise<void> , 즉, 반환값이 없다.

ensureQueryData

  • 캐시된 데이터가 있으면 반환하고, 없으면 데이터를 가져오는 비동기 메서드이다.
  • 반환값이 있다.

선택하기

현재 라우트는 다음과 같이 구성되어 있다.

export const Route = createFileRoute('/_auth/$project/board')({
  ...
  
  loader: ({ context: { queryClient }, params: { project } }) => {
    const projectId = Number(project);

    // prefetchQuery or ensureQueryData ?

    return { projectId };
  },
  
  component: () => (
    <Suspense fallback={<LoadingFallback />}>
      <Board />
    </Suspense>
  ),
});

칸반보드를 그려내기 위해 최초 1회 전체 태스크 목록을 불러오는데, (그 후에는 5분 간격으로 갱신). 어떤 것이 더 알맞는 사용방식일까?


우선, 데이터를 가져오는 방식을 확인해본다.
실제 이 라우트의 loader 에서 해당 데이터를 사용할 필요가 있는가? 아니다.. 데이터는 <Board> 컴포넌트 내부의 useSuspenseQuery 에서 사용할 것이다.


그 다음은 캐싱 여부이다.
ensureQueryData 는 기존의 캐싱된 데이터가 있다면, 이를 활용한다.
하지만, 사용자가 이 보드 페이지에 접근을 시도하면, 기존에 캐시 되어있던 데이터가 아닌 최신 데이터를 불러와야 한다. 따라서, prefetchQuery 가 적합해 보인다.


Suspense 는 왜 필요한가?

prefetchQuery 는 사용자가 페이지를 이동하기 전에 데이터를 미리 캐싱해준다.

graph TD
    A[라우트 전환 시작] --> B[loader 실행]
    B --> C[prefetchQuery 실행]
    C --> D[캐시에 데이터 저장]
    D --> E[Board 컴포넌트 마운트]
    E --> F[useSuspenseQuery 실행]
    F --> G[캐시된 데이터 즉시 사용]
Loading

그렇다면 Suspense 왜 필요한걸까?

prefetchQuery 가 미리 데이터를 캐싱하려 시도하긴 하지만,
네트워크가 불안정하거나, prefetchQuery 가 느리게 동작한다면, 컴포넌트는 이미 렌더링이 시작되었을 수 있다.
즉, 데이터 캐싱이 완료되기 전에 컴포넌트가 마운트되는 것을 방지하기 위함이다.

캐싱이 끝나기전에 <Board> 컴포넌트가 마운트를 시도하면, Suspense 가 이 컴포넌트의 렌더링을 막고 기다리는 것이다.
따라서, prefetchQuery 가 느리게 동작할 때에도, 더 나은 사용자 경험을 제공할 수 있게 된다.



아래 블로그에 잘 정리되어 있어서 많이 배웠습니다.

https://bichoninthefront.tistory.com/112

Clone this wiki locally