
TanStack Query 알아보기
2024-08-10
TanStack Query의 특징과 사용하는 법을 알아봅니다.
이 글은 TanStack Query v5를 기준으로 작성되었습니다.
Contents
- TanStack Query란?
- TanStack Query 설치하기
- Caching
- Fresh and Stale
- useQuery
- useQueries
- useSuspenseQuery
- 마무리
TanStack Query란?
TanStack Query는 fetching, caching, synchronizing, updating 등을 지원하는 라이브러리입니다.
즉 서버 상태 관리 라이브러리로 대표적으로 TanStack Query와 SWR이 있습니다. 기존 상태 관리 라이브러리로 관리하기 어려웠던 비동기 데이터, 서버 상태 등을 관리할 수 있습니다.
TanStack Query 설치하기
React 프로젝트를 생성한 뒤 아래의 명령어를 입력하여 TanStack Query를 설치합니다.
yarn add @tanstack/react-query
설치 이후 사용하기 위해 QueryClientProvider로 컴포넌트를 감싸주세요. QueryClientProvider는 context api를 기반으로 하여 데이터를 전역에 사용할 수 있도록 해줍니다.
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
const queryClient = new QueryClient();
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<Example />
</QueryClientProvider>
);
}
React가 아닌 다른 프레임워크에서 사용하려면 공식 문서를 참고해주세요.
Caching
Caching이란 데이터를 받아온 뒤에 임시로 저장하여 보다 빠르게 접근할 수 있도록 하는 프로세스입니다.
앞서 말했듯 TanStack Query는 데이터를 Caching합니다. 정해진 cacheTime (기본 값은 5분입니다.) 만큼 데이터를 메모리에 저장합니다. 하지만 Cache가 존재한다고 해서 data fetching을 하지 않는 것은 아닙니다. cacheTime이 지나지 않았지만 해당 데이터를 필요로하는 컴포넌트가 mount되면 새로운 데이터를 fetching하는 동안 Caching된 데이터를 보여줍니다.
const MINUTE = 1000 * 60;
const queryClient = new QueryClient({
defaultOptions: {
queries: {
gcTime: 10 * MINUTE,
},
},
});
위와 같이 queryClient에서 (혹은 queryOptions에서) gcTime (cacheTime에서 gcTime으로 변경되었습니다.) 을 변경할 수 있습니다.
Fresh and Stale
이번에는 Fresh와 Stale에 대해 알아보겠습니다. 데이터에 상태는 Fresh와 Stale로 나뉩니다. Fresh는 의미에서 알 수 있듯이 데이터가 사용할 수 있는 신선한 상태라는 뜻 입니다. Stale 또한 의미에서 알 수 있듯이 데이터가 refetching이 필요할 만큼 신선하지 못한 상태라는 뜻 입니다. 데이터는 초기에 Fresh 상태였다가 staleTime (기본 값은 0입니다.) 이후 Stale 상태가 됩니다.
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: Infinity,
},
},
});
위와 같이 queryClient에서 (혹은 queryOptions에서) staleTime을 변경할 수 있습니다.
useQuery
Fetch는 서버로 요청을 보내고 응답을 받을 수 있는 API입니다. 원래 Fetch API를 사용하려면 아래와 같은 코드를 작성해야 합니다.
async function fetchData() {
const response = await fetch("http://example.com/movies.json");
const data = await response.json();
console.log(data);
}
아래는 TanStack Query의 useQuery를 사용한 경우입니다.
import {
QueryClient,
QueryClientProvider,
useQuery,
} from "@tanstack/react-query";
const queryClient = new QueryClient();
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<Example />
</QueryClientProvider>
);
}
function Example() {
const { isPending, error, data } = useQuery({
queryKey: ["repoData"],
queryFn: () =>
fetch("https://api.github.com/repos/TanStack/query").then((res) =>
res.json()
),
});
if (isPending) return "Loading...";
if (error) return "An error has occurred: " + error.message;
return (
<div>
<h1>{data.name}</h1>
<p>{data.description}</p>
<strong>👀 {data.subscribers_count}</strong>{" "}
<strong>✨ {data.stargazers_count}</strong>{" "}
<strong>🍴 {data.forks_count}</strong>
</div>
);
}
useQuery 사용 시 isPending으로 로딩 중인지 확인
TanStack Query의 경우에는 useQuery (GET), useMutation (POST, PUT, UPDATE, DELETE) 등을 사용하여 fetch를 하게 됩니다. useQuery의 경우 기본적으로 queryKey에 Caching에 필요한 쿼리 키를 입력받고, queryFn에 기본 fetch 함수를 입력받습니다.
또한 결과 값으로 isPending, error, data 등 여러가지 옵션을 가져올 수 있는데, isPending의 경우 data가 불러와 지고 있는지 (로딩 중인지)를 알 수 있고, error는 data를 가져오는 과정에서 발생한 error를 확인할 수 있습니다.
만약 fetch에 대해 더 알아보고 싶다면 mdn web docs를 확인하고 useQuery의 더 자세한 입력, 결과 값들을 확인하고 싶다면 useQuery를 확인해주세요.
useQueries
useQueries는 여러개의 query를 사용할 수 있습니다.
const ids = [1, 2, 3];
const results = useQueries({
queries: ids.map((id) => ({
queryKey: ["post", id],
queryFn: () => fetchPost(id),
staleTime: Infinity,
})),
});
요청을 하면 배열로 결과가 반환됩니다.
useSuspenseQuery
앞서 useQuery의 isPending을 사용하여 데이터가 로딩 중인지 확인할 수 있습니다. 하지만 isPending이 아닌 Suspense를 사용하고 싶은 경우, useSuspenseQuery를 사용하면 됩니다.
import { useSuspenseQuery } from "@tanstack/react-query";
import { Suspense } from "react";
export function Example() {
return (
<Suspense fallback={<Loading />}>
<DataComponent />
</Suspense>
);
}
function Loading() {
return <p>Loading...</p>;
}
function DataComponent() {
const { data, error } = useSuspenseQuery({
queryKey: ["repoData"],
queryFn: () =>
fetch("https://api.github.com/repos/TanStack/query").then((res) =>
res.json()
),
});
if (error) return error.message;
return (
<div>
<h1>{data.name}</h1>
<p>{data.description}</p>
<strong>👀 {data.subscribers_count}</strong>
<strong>✨ {data.stargazers_count}</strong>
<strong>🍴 {data.forks_count}</strong>
</div>
);
}
마무리
혹시 TanStack Query로 GET요청이 아닌 POST, PUT, UPDATE, DELETE 등의 요청을 보내고 싶다면, useMutation에 대해 알아보시길 바랍니다.
사실 위에 설명한 내용만으로는 TanStack Query를 모두 이해했다고 하기는 어렵습니다. 저도 TanStack Query를 공부하고 이 글을 쓰면서 어떻게 글을 써야할지 많이 고민해 보았지만 최대한 간결하게 쓰고 다양한 아티클을 읽어보는게 좋을 것 같다고 생각했습니다.
이 글을 읽고 계시는 분들도 공식문서를 비롯해 TanStack Query의 동작 원리를 설명한 글, 카카오페이, 우아한형제들 등 여러 기업이 TanStack Query를 도입한 계기와 많은 개발자들이 블로그에 작성한 글 등 수 많은 글들을 찾아 읽어보셨으면 좋겠습니다.
긴 글 읽어주셔서 감사합니다.