React Query(=TanStack Query)는 서버 상태 관리를 간편하게 만들어주는 도구야.
서버에서 데이터를 가져오고, 캐시에 저장하며, 이를 다시 사용할 수 있도록 관리하는 것을 도와줘. 특히, 비동기 작업(데이터 요청, 응답 처리, 상태 관리)을 자동화해서 개발자 경험을 크게 향상시켜주지!
데이터 패칭 (Fetching): 서버에서 데이터를 가져오는 작업. (예) API 호출로 게시글 목록을 가져오기.
캐싱 (Caching): 한 번 가져온 데이터를 메모리에 저장해서, 같은 요청을 다시 보낼 필요가 없게 만듦.
빠른 성능과 효율적인 데이터 관리를 제공.
자동 리프레시 (Refetching): 데이터가 오래되면 자동으로 새로고침하거나, 수동으로 요청할 수 있음.
요청 상태 관리: 로딩 중, 에러 발생, 성공 등 요청의 상태를 자동으로 관리.
SWR 전략: "오래된 데이터를 사용하면서 새 데이터를 가져오는(Stale-While-Revalidate)" 방식으로, 화면을 빠르게 렌더링하고 최신 데이터를 유지.
1️⃣ React Query설치
| 패키지 매니저 | 설치 명령어 |
|---|---|
| yarn | yarn add @tanstack/react-query |
| pnpm | pnpm add @tanstack/react-query |
2️⃣ 기본 설정 (QueryClientProvider)
React Query는 QueryClient라는 관리자를 추가해야해.
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<MyComponent />
</QueryClientProvider>
);
}
3️⃣ 데이터를 가져오기 (useQuery)
useQuery는 데이터를 가져오는 데 사용해.
import { useQuery } from '@tanstack/react-query';
import axios from 'axios';
function MyComponent() {
const { data, isLoading, error } = useQuery(['posts'], async () => {
const response = await axios.get('https://jsonplaceholder.typicode.com/posts');
return response.data;
});
if (isLoading) return <p>로딩 중...</p>;
if (error) return <p>에러 발생: {error.message}</p>;
return (
<div>
<h1>게시글 목록</h1>
<ul>
{data.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}
데이터 변경 작업(예: POST, PUT, DELETE 요청)을 처리할 때 사용하는 훅이야.
데이터를 가져오는 useQuery와는 반대로, 데이터를 변경하는 데 사용해!
import { useMutation, useQueryClient } from '@tanstack/react-query';
import axios from 'axios';
function AddPost() {
const queryClient = useQueryClient();
const mutation = useMutation(
(newPost) => axios.post('https://jsonplaceholder.typicode.com/posts', newPost),
{
onSuccess: () => {
// 성공 후 기존 데이터를 다시 가져오게 함
queryClient.invalidateQueries(['posts']);
},
}
);
const addNewPost = () => {
mutation.mutate({ title: '새 게시글', body: '내용입니다.' });
};
return (
<div>
<button onClick={addNewPost} disabled={mutation.isLoading}>
게시글 추가
</button>
{mutation.isLoading && <p>추가 중...</p>}
{mutation.isError && <p>에러 발생: {mutation.error.message}</p>}
{mutation.isSuccess && <p>추가 완료!</p>}
</div>
);
}
invalidateQueries는 React Query의 캐시를 무효화(Invalidate)하는 기능이야.
예를 들어, 새로운 데이터를 추가하거나 삭제한 후 이전에 가져온 데이터를 새로고침할 때 사용해.
queryClient.invalidateQueries(['posts']); // 'posts' 키로 캐시된 데이터를 새로고침
SWR은 Stale-While-Revalidate(오래된 데이터를 사용하면서 새 데이터를 가져옴)의 약자야.
캐시 데이터 제공 (빠르게 화면 표시)
먼저, React Query는 캐시에 저장된 데이터를 화면에 표시해.
화면이 빨리 보여서 사용자 경험이 좋아져.
새 데이터 가져오기 (최신 데이터 유지)
동시에 서버에서 새 데이터를 가져와 캐시를 업데이트해.
화면에 최신 데이터가 반영돼.
React Query: 서버 상태 관리에 특화된 강력한 도구.
SWR: 데이터 페칭과 캐싱을 단순하게 처리하는 도구.
React Query는 SWR 전략을 기본으로 제공해,
먼저 캐시에서 데이터를 보여주고, 서버에서 새 데이터를 가져와 화면을 업데이트함.
React Query는 서버 데이터를 효율적으로 관리하고, 캐싱과 상태 관리를 자동화해 개발을 더 빠르고 쉽게 만들어주는 도구야!
🎯 쉽게 비유하기
React Query를 자동 음식 배달 서비스라고 생각해봐!
음식 주문(데이터 요청): 사용자가 음식(데이터)을 주문.
React Query가 자동으로 서버에서 데이터를 가져와 제공.
배달 상태 관리(요청 상태 관리): 음식이 배달 중인지, 배달 완료되었는지, 실패했는지 상태를
자동으로 관리. "데이터를 가져오는 중..." 같은 로딩 메시지를 쉽게 표시할 수 있어.
음식 보관소(캐싱): 가져온 음식(데이터)을 보관소(캐시)에 저장.
같은 데이터가 다시 필요하면 서버에 요청하지 않고, 보관소에서 꺼내줘.
유통기한 관리(자동 리프레시): 데이터가 오래되면 자동으로 새로 가져오거나, 사용자가 요청했을 때 데이터를 새로고침해.
| 상태 | 설명 |
|---|---|
| fresh | 데이터를 새로 패칭할 필요가 없는 상태. staleTime이 지나지 않은 상태로, 캐시 데이터를 그대로 사용가능. |
| stale | 데이터를 새로 패칭해야 하는 상태. staleTime이 지난 후, 새로운 데이터를 가져오기 위해 쿼리가 실행. |
| active | 현재 컴포넌트에서 사용 중인 쿼리 상태. 컴포넌트가 마운트되어 쿼리를 사용하고 있을 때. |
| inactive | 더 이상 사용되지 않는 쿼리 상태. 컴포넌트가 언마운트되거나 쿼리가 더 이상 필요하지 않을 때. |
| deleted | 캐시에서 제거된 쿼리 상태. gcTime이 지나면 쿼리가 캐시에서 삭제되어 이 상태가 됨. |
| fetching | 데이터를 서버에서 가져오고 있는 상태. 이 상태에서는 isFetching이 true로 설정. |
| 기본 설정 | 의미 |
|---|---|
staleTime: 0 | useQuery 또는 useInfiniteQuery에 등록된 queryFn을 통해 fetch 받은 데이터는 항상 stale 상태로 취급. |
refetchOnMount: true | useQuery 또는 useInfiniteQuery가 있는 컴포넌트가 마운트 시 stale 데이터를 refetch 자동 실행. |
refetchOnWindowFocus: true | 실행 중인 브라우저 화면을 focus 할 때마다 stale 데이터를 refetch 자동 실행. |
refetchOnReconnect: true | 네트워크가 끊겼다가 재연결되었을 때 stale 데이터를 refetch 자동 실행. |
gcTime (cacheTime): 5분 | useQuery 또는 useInfiniteQuery가 있는 컴포넌트가 언마운트된 후 inactive 상태가 5분 경과 시 캐시 데이터 삭제 처리. |
retry: 3 | useQuery 또는 useInfiniteQuery에 등록된 queryFn이 API 요청 실패 시 총 3번까지 재요청 자동 시도. |
🎯 헷갈리는 개념 정리
1. staleTime vs gcTime
2. isPending vs. isFetching