반응형
250x250
Notice
Recent Posts
Recent Comments
Link
관리 메뉴

짧은코딩

리페칭 본문

인프런, 유데미/React-Query

리페칭

5_hyun 2023. 4. 9. 01:09

리페칭을 할 때 중요하게 봐야 되는 것은 서버가 만료 데이터를 업데이트 한다는 것이다. 창을 포커스하는 트리거를 하면 잠시 로딩 인디테이터가 나타나는데 이는 만료되었던 데이터를 가져오기 때문이다. 데이터는 시간이 지나면 자연스럽게 만료된다. 

stale 쿼리는 어떤 조건 하에서 자동적으로 다시 가져오기가 된다. 새로운 쿼리가 많아지거나 그 쿼리가 처음 호출, 쿼리를 사용하는 컴포넌트 증가, 트리거, 네트워크가 다시 연결되면 리페칭이 일어난다. 그리고 리페칭 간격이 지난 경우에도 리페칭이 다시 일어나는데 이 경우 간격을 둬서 서버를 폴링하고 사용자가 딱히 무엇을 하지 않아도 데이터가 리페칭 된다.

리페칭은 전역 혹은 특정 쿼리로 할 수 있다. refetchOnMount, refetchOnWindowFocus, refetchOnReconnect이 3개는 boolean, refetchInterval은 밀리초 단위 시간이다. useQuery에서 리페칭을 하면 객체를 반환한다.

 

미세한 변동에도 큰 변화를 가져오는 데이터에는 리페칭을 적용하면 안 된다. 하지만 예약 같은 실시간 데이터에서는 리페칭을 자주 해줘야 한다. "데이터가 어떻게 항상 실시간일까?"라는 생각을 하는 것이 중요하다.

 

리페칭 제한 하기

아래 예시는 홈 페이지에 들어왔을 때부터 리페칭을 하는 데이터이다. 마사지 종류를 보여주는 단순한 데이터라서 리페칭을 제한하면 좋다.

 

  const { data = fallback } = useQuery(queryKeys.treatments, getTreatments, {
    staleTime: 600000, // 10분
    cacheTime: 900000, // 15분
    refetchOnMount: false, // 마운트(리렌더링)될 때 데이터를 다시 가져오지 않음
    refetchOnWindowFocus: false, // 브라우저를 포커싱했을때 데이터를 가져오지 않음
    refetchOnReconnect: false, // 네트워크가 다시 연결되었을때 다시 가져오지 않음
  });
  return data;

리페칭을 제한하기 위해서 먼저 staleTime을 10분으로 늘려줬다. 이러면 cacheTime도 같이 늘려줘야 한다. 왜냐하면 데이터가 이미 만료되었는데 캐싱된 데이터가 없으면 보여줄 데이터가 없기 때문이다.

refetchOnMount, refetchOnWindowFocus, refetchOnReconnect도 사용하여 리페칭을 제한해 줬다.

 

export function usePrefetchTreatments(): void {
  const queryClient = useQueryClient();
  queryClient.prefetchQuery(queryKeys.treatments, getTreatments, {
    // 이러면 프리페칭이 staleTime과 cacheTime을 참조해 데이터 새로 고침 여부를 결정한다.
    staleTime: 600000, // 10분
    cacheTime: 900000, // 15분
  });
}

위에서 말했듯이 홈페이지에 들어가자마자 받아오는 프리페칭 데이터라서 이때도 staleTime, cacheTime을 설정해야 한다. 그래야 홈페이지로 갔을 때 다시 데이터를 불러오지 않는다.

전역적으로 리페칭 제한하기

위에서 각 데이터마다 리페칭을 제한하는 예시를 들었다. 사실 전역적으로 리페칭을 제한하는 것은 추천하는 방식은 아니지만 데이터 최신화가 빈번하게 될 필요가 없는 프로젝트에서는 유용할 수도 있을 거 같다. 이 예시는 옵션을 전역적으로 적용하는 방법에 대해 이해하는 것이 더 중요하다.

 

-qeuryClient.ts

export const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      onError: queryErrorHandler,
      // 리패칭 제한
      //  만료 타임이 캐싱 타임보다 길다는 것은 말이 안된다. 왜냐하면 만료된 데이터를 불러오는 동안 캐싱된 데이터를 보여주기 때문이다.
      // 따라서 staleTime은 cacheTime보다 작아야한다. 만약 staleTime이 더 크면 리패칭하는 동안 보야줄 데이터가 없을 것이다.
      staleTime: 600000, // 10분
      cacheTime: 900000, // 15분
      refetchOnMount: false, // 마운트(리렌더링)될 때 데이터를 다시 가져오지 않음
      refetchOnWindowFocus: false, // 브라우저를 포커싱했을때 데이터를 가져오지 않음
      refetchOnReconnect: false, // 네트워크가 다시 연결되었을때 다시 가져오지 않음
    },
  },
});

qeuryClient.ts 파일로 가서 위에서 쓴 코드와 똑같이 적용해 주면 전역적으로 리페칭을 적용할 수 있다.

리페칭 오버라이딩

위에서 전역적으로 리페칭을 제한을 했다. 하지만 예약 같은 부분에서는 데이터가 빠르게 업데이트되어야 한다.

  const commonOptions = { staleTime: 0, cacheTime: 300000 };
   // ...

  const queryClient = useQueryClient();
  useEffect(() => {
    const nextMonthYear = getNewMonthYear(monthYear, 1);
    queryClient.prefetchQuery(
      [queryKeys.appointments, nextMonthYear.year, nextMonthYear.month],
      () => getAppointments(nextMonthYear.year, nextMonthYear.month),
      commonOptions,
    );
  }, [queryClient, monthYear]);
   // ...
  
    const { data: appointments = fallback } = useQuery(
    [queryKeys.appointments, monthYear.year, monthYear.month],
    () => getAppointments(monthYear.year, monthYear.month),
    {
      // showAll이 true면 undefined를 줘서 모든 예약이 나오게 하고, false면 selectFn 실행
      // selectFn이 실행되면 data를 가져와 변환해서 반환한다.
      select: showAll ? undefined : selectFn,
      ...commonOptions,
      refetchOnMount: true,
      refetchOnWindowFocus: true,
      refetchOnReconnect: true,
    },
  );

 

commonOptions에 staleTime, cacheTime을 설정하고 queryClient와 useQuery에 설정을 해줬다.

 staleTime, cacheTime은 시간을 줄여서 빈번하게 업데이트가 되게 하고, 리페칭을 제한하는 것에서 옵션들을 다 반대로 설정했다.

폴링(자동 리페칭)

예약 같은 시스템은 데이터를 빈번하게 불러와야 한다. 그렇기 위해서 폴링을 하면 된다. 폴링은 리페칭을 자동으로 해줄 수 있는 것이다.

  const { data: appointments = fallback } = useQuery(
    [queryKeys.appointments, monthYear.year, monthYear.month],
    () => getAppointments(monthYear.year, monthYear.month),
    {
      // showAll이 true면 undefined를 줘서 모든 예약이 나오게 하고, false면 selectFn 실행
      // selectFn이 실행되면 data를 가져와 변환해서 반환한다.
      select: showAll ? undefined : selectFn,
      ...commonOptions,
      refetchOnMount: true,
      refetchOnWindowFocus: true,
      refetchOnReconnect: true,
      refetchInterval: 60000, // 이러면 정해둔 시간마다 데이터를 최신화한다.
    },
  );

폴링을 하기 위해서 refetchInterval을 60000으로 해줬다. 이것은 1분마다 데이터를 다시 가져오는 것이다.

728x90
반응형
Comments