Tanstack Query v5.0 알아보기

이종경·2024년 6월 20일
0
post-thumbnail

Tanstack Query는 과거에 react-query라는 이름으로 알려져있었다.
업데이트가 되면서 리액트 외에도 Vue, Svelet, Angular 등을 지원하게 되면서 이름이 변경되었다.

React Query는 서버의 데이터를 가져와 캐싱해주는 것에 최적화 되어 있어 사용된다.

Tanstack Query 설치

# npm
npm i @tanstack/react-query
# or yarn
yarn add @tanstack/react-query

추가적으로 DevTool을 설치해준다.

# npm
npm i -D @tanstack/react-query-devtools
# or yarn
yarn add -D @tanstack/react-query-devtools

React Query 사용방법

1. Provider 생성하기

우선, 다음과 같이QueryClientProviderReactQueryDevtools를 사용한 컴포넌트를 생성해준다.
이렇게 Provider를 생성해주어야 이 Provider로 감싼 컴포넌트끼리 데이터를 공유할 수 있다.

import React, { useState } from "react";
import { QueryClientProvider, QueryClient } from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";

type Props = {
  children: React.ReactNode;
};

function RQProvider({ children }: Props) {
  const [client] = useState(
    new QueryClient({
      defaultOptions: {
        // react-query 전역 설정
        queries: {
          refetchOnWindowFocus: false,
          retryOnMount: true,
          refetchOnReconnect: false,
          retry: false,
        },
      },
    })
  );

  return (
    <QueryClientProvider client={client}>
      {children}
      <ReactQueryDevtools initialIsOpen={process.env.NEXT_PUBLIC_MODE === "local"} /> 
        // initailIsOpen이 True면 devtool을 활성화해준다.
    </QueryClientProvider>
  );
}

export default RQProvider;

2. (선택) SSR을 위한 react query 설정

v4에서는 Hydrate 컴포넌트였지만 v5에서는 HydrationBoundary로 명칭이 바뀌었다.

서버 컴포넌트에 다음과 같이 작성해준다.

import { HydrationBoundary, QueryClient, dehydrate } from "@tanstack/react-query";

export default async function Home() {
  const queryClient = new QueryClient();
  await queryClient.prefetchQuery({ queryKey: ["posts", "recommends"], queryFn: getPostRecommends });
  const dehydratedState = dehydrate(queryClient); // 서버사이드 렌더링을 위한 dehydrate

  return (
    <main>
      <HydrationBoundary state={dehydratedState}>
          <PostRecommends />
      </HydrationBoundary>
    </main>
  );
}

위 코드는 다음과 같은 방식으로 동작한다.

  1. QueryClient를 생성한 후 prefetchQuery를 사용하여 데이터를 서버에서 미리 패칭한다.
  2. 이 데이터는 dehydrate 함수를 통해 직렬화되어 props로 전달된다.
  3. 서버에서 직렬화된 데이터는 클라이언트로 전달되며, QueryClientProviderHydrationBoundary 컴포넌트를 통해 초기 상태로 사용된다. 이렇게 하면 클라이언트가 첫 번째 렌더링 시 이미 서버에서 패칭된 데이터를 사용하게 되어, 추가적인 데이터 패칭 요청 없이 빠르게 렌더링할 수 있다.

클라이언트 측에서는 useQuery 훅을 사용하여 데이터에 접근한다. React Query는 이미 서버에서 패칭된 데이터를 사용하므로, 클라이언트에서 다시 데이터를 패칭하지 않아도 된다. 필요 시 클라이언트 측에서 데이터를 갱신할 수 있다

3. useQuery를 사용한 클라이언트 컴포넌트의 데이터 패칭

useQuery를 통해 데이터를 패칭할 수 있다.
react query는 query keys를 기반으로 해서 쿼리 캐싱을 관리하므로
queryKey는 유니크한 값으로 작성해주어야 한다.
queryFn에는 데이터 패칭을 위한 함수를 작성해주면 된다.

import { useQuery } from "@tanstack/react-query";

export default function PostRecommends() {
  const { data } = useQuery({ queryKey: ["posts", "recommend"], queryFn: getPostRecommends });

  return data?.map((post) => <Post key={post.postId} post={post} />);
}

React Query의 상태

React Query Devtools를 설치하면 다음과 같은 상태를 확인할 수 있다.
react query state

Fresh

기본적으로 서버에서 데이터를 불러오면 Fresh 상태이다.
Fresh는 서버로부터 불러온 데이터가 최신 데이터임을 의미한다.
이는 개발자가 직접 설정할 수 있다.
리액트쿼리는 기본적으로 데이터가 Fresh가 아니라고 기본값으로 설정되어 있다.

Fresh 상태의 지속시간을 설정해주고 싶으면 staleTime을 재설정하면 된다.
기본값은 0으로 되어있고 ms단위로 작성한다.

const { data: post, error } = useQuery<IPost, Object, IPost, [_1: string, _2: string]>({
    queryKey: ["posts", id],
    queryFn: getSinglePost,
    staleTime: 60 * 1000, // 1분뒤 Stale 상태로 변경된다.
    gcTime: 300 * 1000,
  });

Stale

Stale은 기회가 되면 서버에서 데이터를 가져오라는 의미이다.
여기서 기회란, 보통 3가지 설정에 따라 데이터를 가져온다.
useQuery에서 따로 설정을 해줄 수 있으며, 다음과 같이 전역설정을 해주어도 된다.

const [client] = useState(
    new QueryClient({
      defaultOptions: {
        // react-query 전역 설정
        queries: {
          refetchOnWindowFocus: false, // 탭전환시
          retryOnMount: true, // 컴포넌트가 Unmount/Mount시
          refetchOnReconnect: false, // 인터넷 연결시
          retry: false,
        },
      },
    })
  );
  • refetchOnWindowFocus : 다른 탭으로 이동했다가 다시 돌아오는 경우 데이터를 새로 가져온다
  • retryOnMount : 컴포넌트가 Unmount되었다가 Mount될 때 데이터를 새로 가져온다.
  • refetchOnReconnect : 인터넷 연결이 끊겼다가 다시 연결이 된 경우 데이터를 새로 가져온다.

Inactive

데이터가 Inactive는 데이터를 현재 페이지에서 사용하고 있는지 여부를 확인할 수 있다.
Inactive 상태가 되면 기본적으로 gcTime(garbage collection)이 시작된다. gcTime에 설정된 시간이 지나고나면 메모리에서 제거된다.

const { data: post, error } = useQuery<IPost, Object, IPost, [_1: string, _2: string]>({
    queryKey: ["posts", id],
    queryFn: getSinglePost,
    staleTime: 60 * 1000, 
    gcTime: 300 * 1000, // 5분, 기본값
  });

주의해야할 점
staleTime(캐시 타임을 얼마나 오랫동안 가지고 있을지)은 gcTime(캐시를 언제 지울지)보다 짧아야한다.

Paused

리액트 쿼리 기능중에 데이터를 가져오는 것을 멈추게하는 기능이 있는데, 그상태를 나타낸다.

Fetching

데이터를 가져오는 순간적인 상황

React Query Actions

React Query Actions

  • Refetch : 데이터를 무조건 새로 가져온다.
  • Invalidate : Refetch와 유사하나, Refetch와 달리 어떤 데이터의 Query Details의 Observers 가 0일 때, Invalidate를 누르면 해당 데이터를 가져오는 로직이 실행될 때, 그 순간에 데이터를 가져온다.
  • Reset : useQuery에 initailData가 있는 경우 해당 데이터로 Reset된다. 정의가 되어 있지 않으면 데이터를 새로 가져온다.
  • Remove : 데이터를 제거한다.
  • Trigger Loading/Restore Loading : 로딩 상태를 확인하고자 할 때 사용한다.
  • Trigger Error/Restore Error : 에러 상태를 확인하고자 할 때 사용한다.

참고
Next + React Query로 SNS 서비스 만들기
Overview | Tanstack Query React Docs

profile
작은 성취들이 모여 큰 결과를 만든다고 믿으며, 꾸준함을 바탕으로 개발 역량을 키워가고 있습니다

0개의 댓글