PromleeBlog
sitemapaboutMe

posting thumbnail
리액트 쿼리(TanStack Query) 사용하기 - 기초
Guide to React Query (TanStack Query) - Basic

📅

🚀

들어가기 전에🔗

React로 웹 애플리케이션을 만들다 보면 외부 API에서 데이터를 불러와 화면에 표시해야 하는 경우가 많습니다. 이때 데이터를 어떻게 불러오고, 로딩 중이거나 실패했을 때는 어떻게 처리하며, 동일한 데이터를 반복해서 불러오지 않도록 효율적으로 캐싱하는 방법이 중요해집니다.
이러한 문제를 해결하기 위해 등장한 도구 중 하나가 바로
TanStack Query
입니다. 이전에는
React Query
라는 이름으로 더 많이 알려져 있었으며, 현재는 다양한 프레임워크를 지원하는 범용적인 상태 관리 도구로 발전하였습니다. 이번 글에서는 React를 기준으로 TanStack Query를 사용하는 방법을 기초부터 고급까지 예제와 함께 차근차근 설명드리겠습니다.

🚀

TanStack Query란 무엇인가요?🔗

TanStack Query는 서버 상태(server state)를 클라이언트 애플리케이션에서 효율적으로 다룰 수 있도록 도와주는 라이브러리입니다. 쉽게 말해, 서버에서 받아오는 데이터를 관리하고, 로딩, 에러 처리, 캐싱, 리패칭 등의 과정을 간단하게 처리해주는 도구입니다.
예를 들어, 다음과 같은 상황에서 유용합니다:

🚀

설치 방법🔗

먼저 프로젝트에 TanStack Query를 설치해야 합니다. 다음 명령어를 터미널에 입력해 주세요:
npm install @tanstack/react-query
또한 React 애플리케이션에서 Query 기능을 사용하기 위해 QueryClientProvider를 앱 최상위에 설정해야 합니다:
// main.tsx 또는 App.tsx
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
root.render(
  <QueryClientProvider client={queryClient}>
    <App />
  </QueryClientProvider>
);

🚀

기본적인 useQuery 사용법🔗

이제 가장 기본적인 사용법부터 살펴보겠습니다. JSONPlaceholder의 게시글 API(/posts)를 예로 들어보겠습니다.
import { useQuery } from '@tanstack/react-query';
import axios from 'axios';
 
const fetchPosts = async () => { // 정보를 fetch하는 함수
  const res = await axios.get('https://jsonplaceholder.typicode.com/posts');
  return res.data;
};
 
function PostList() {
  const { data, isLoading, isError, error } = useQuery({ // 쿼리 결과를 가져오는 컴포넌트
    queryKey: ['posts'], // 쿼리의 고유 식별자
    queryFn: fetchPosts, // 정보를 fetch하는 함수
  });
  
  if (isLoading) return <p>불러오는 중입니다...</p>;
  if (isError) return <p>오류가 발생했습니다: {(error as Error).message}</p>;
  return (
    <ul>
      {data.map((post: any) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}
먼저, 정보를 fetch하는 함수를 정의합니다. 이 함수는 비동기로 데이터를 가져오고, 그 결과를 반환합니다.
그리고 이 함수를 useQueryqueryFn 옵션에 전달합니다.
useQuery는 이 함수를 호출하고, 그 결과를 캐시에 저장합니다.

🚀

쿼리 키(queryKey)의 중요성🔗

queryKey는 TanStack Query에서 매우 중요한 역할을 합니다. 요청을 고유하게 식별하고, 캐시를 구분하며, 리패칭의 기준이 되는 핵심 요소입니다.

기본 사용법🔗

단순한 쿼리에서는 문자열로 작성할 수 있습니다:
useQuery({
  queryKey: ['posts'],
  queryFn: fetchPosts,
});
API 파라미터를 포함하는 경우 배열로 구조화하는 것이 좋습니다:
useQuery({
  queryKey: ['user', userId],
  queryFn: () => fetchUser(userId),
});
이렇게 하면 userId가 다르면 서로 다른 쿼리로 인식되어 별도의 캐시로 관리됩니다.

고급 패턴: 중첩 키🔗

보다 복잡한 구조를 가지는 경우, 다음처럼 중첩된 queryKey를 구성할 수 있습니다:
useQuery({
  queryKey: ['users', userId, 'posts'],
  queryFn: () => fetchUserPosts(userId),
});
이렇게 하면 특정 사용자의 게시글 쿼리를 명확하게 식별할 수 있어 유연한 캐싱이 가능합니다.

🚀

Suspense 통합 사용하기🔗

React의 Suspense와 TanStack Query를 함께 사용하면 로딩 상태를 더 간결하고 선언적으로 처리할 수 있습니다. 먼저 React의 Suspense 컴포넌트로 쿼리 컴포넌트를 감싸고, useQuerysuspense: true를 설정합니다.
// App.tsx
<Suspense fallback={<p>로딩 중입니다...</p>}>
  <PostList />
</Suspense>
// PostList.tsx
const { data } = useQuery({
  queryKey: ['posts'],
  queryFn: fetchPosts,
  suspense: true,
});
이 방식은 코드가 더 간결해지고, 로딩 상태를 전역적으로 관리할 수 있는 장점이 있습니다. 단, 컴포넌트의 에러 처리를 위해 ErrorBoundary와 함께 사용하는 것이 좋습니다.

🚀

React Query Devtools 사용하기🔗

개발 중에 쿼리 상태를 실시간으로 모니터링할 수 있는 Devtools 도구도 제공합니다.
npm install @tanstack/react-query-devtools
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
<QueryClientProvider client={queryClient}>
  <App />
  <ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
이 도구를 사용하면 현재 캐시된 데이터, 쿼리 상태, 요청 시간 등을 시각적으로 확인할 수 있어 디버깅에 매우 유용합니다.

🚀

SSR 환경에서 사용하기🔗

Next.js 같은 프레임워크에서 SSR을 사용할 경우, 쿼리를 서버에서 미리 실행하고 데이터를 HTML에 포함시켜 초기 로딩을 빠르게 할 수 있습니다.
이를 위해 dehydrateHydrate 컴포넌트를 사용합니다.
// 서버에서
const queryClient = new QueryClient();
await queryClient.prefetchQuery({ queryKey: ['posts'], queryFn: fetchPosts });
const dehydratedState = dehydrate(queryClient);
// 클라이언트에서
<Hydrate state={dehydratedState}>
  <App />
</Hydrate>
서버와 클라이언트가 동일한 캐시 상태를 공유함으로써 깜빡임 없이 데이터를 보여줄 수 있습니다.

🚀

고급 에러 핸들링 전략🔗

쿼리나 뮤테이션이 실패했을 때 사용자에게 알림을 표시하거나 재시도할 수 있습니다. 다음과 같은 옵션들이 있습니다:
useQuery({
  queryKey: ['posts'],
  queryFn: fetchPosts,
  retry: 2,
  onError: (error) => {
    toast.error('데이터를 불러오는 데 실패했습니다');
  },
});
useMutation도 비슷한 방식으로 처리할 수 있으며, 에러 로그를 콘솔에 출력하거나 Sentry 등 외부 서비스에 전송할 수도 있습니다.

🚀

결론🔗

TanStack Query는 React 환경에서 비동기 데이터를 다루는 데 있어 매우 강력하고 유연한 도구입니다. 기본적인 useQuery 사용법부터 useMutation, 캐싱, 무효화, 조건부 실행, 무한 스크롤, Suspense 통합, SSR까지 다양한 기능을 제공하며, 복잡한 로직을 간단하게 구현할 수 있도록 도와줍니다.
이번 글에서 다룬 예제와 전략들을 토대로 실제 프로젝트에서 TanStack Query를 적극 활용해 보시길 권장드립니다.

참고🔗