
오늘은 Tanstack Query (리액트 쿼리) 사용법을 정리할 것이다. 이전에 정리해둔 내용이 있지만 직접 실전에서 사용해보고 해당 내용이 너무 부실하다는 생각이 들어서 다시 정리를 하며 공부해봐야 될 듯 하다.
리액트 쿼리란 리액트 어플리케이션에서 서버 상태를 효율적으로 관리하는 라이브러리!
npm i @tanstack/react-querypnpm add @tanstack/react-queryyarn add @tanstack/react-queryApp.tsx, App.jsx, index.tsx, main.tsx, index.js 등 최상위 루트 컴포넌트 또는 엔트리 포인트 에 간단히 추가해줘야 하는 것들이 있다.QueryClient 생성하기QueryClientProvider에 로 감싸기QueryClientProvider에 생성한QueryClient 넣기// main.tsx
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App.tsx';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
createRoot(document.getElementById('root')!).render(
<QueryClientProvider client={queryClient}>
<StrictMode>
<App />
</StrictMode>
</QueryClientProvider>
);
QueryClientProvider는 QueryClient 인스턴스를 받아서 자식 컴포넌트들이 React Query의 기능(데이터 페칭, 캐싱 등)을 사용할 수 있는 환경을 제공한다.QueryClient 는 React Query에서 데이터 캐싱, 페칭, 동기화 등의 핵심 로직을 담당하는 객체이다.QueryClientProvider의 자식이기 때문에 내부에서 React Query의 훅들을 자유롭게 사용할 수 있다.서버에서 데이터를 가져오는(GET) 데 사용되는 Tanstack Query 훅이다.
queryKey와 queryFn을 전달해야 한다.useQuery가 데이터를 필요로 할 경우 자동으로 호출된다.const {
data,
dataUpdatedAt,
error,
errorUpdatedAt,
failureCount,
failureReason,
fetchStatus,
isError,
isFetched,
isFetchedAfterMount,
isFetching,
isInitialLoading,
isLoading,
isLoadingError,
isPaused,
isPending,
isPlaceholderData,
isRefetchError,
isRefetching,
isStale,
isSuccess,
isEnabled,
promise,
refetch,
status,
} = useQuery(
{
queryKey,
queryFn,
gcTime,
enabled,
networkMode,
initialData,
initialDataUpdatedAt,
meta,
notifyOnChangeProps,
placeholderData,
queryKeyHashFn,
refetchInterval,
refetchIntervalInBackground,
refetchOnMount,
refetchOnReconnect,
refetchOnWindowFocus,
retry,
retryOnMount,
retryDelay,
select,
staleTime,
structuralSharing,
subscribed,
throwOnError,
},
queryClient,
)
undefined이므로 에러가 발생했거나 아직 응답이 완료되지 않았을 때도 undefined이다.?. 사용 등)boolean 값이다.true면 첫 번째 데이터 페칭이 아직 진행 중이고 아직 데이터를 가져오지 않았음을 의미한다.boolean 값이다.isPending 과의 차이점은 처음이 아니더라도 데이터 페칭 작업이 진행 중이면 true를 반환한다.🔥 둘의 차이점
true. 데이터 요청에 초점을 둔다.🔥 refetch를 실행 시 isPending과 isFetching의 차이점
true가 된다.refetch 를 함수를 호출하면 isFetching만 true로 변화하고 isPending은 반응하지 않는다. isError로 에러 발생 여부를 확인할 수 있고 error로 해당 에러를 확인할 수 있다.if (isError) {
return "에러 발생 : " + error.message;
}

false이면 fetching 실패 후 재시도를 하지 않는다.true이면 재시도를 무한 반복합니다.3이고 실패 이후 재시도를 3번 반복한다.ms 마다 재시도 (retry)할 지 명시할 수 있는 옵션이다.retry 옵션과 연계된다.boolean 값을 받는다.false 인 경우 데이터 페칭이 실행되지 않는다.refetch하는 옵션이다.true 이다. 무분별한 refetch를 실행하지 않으려면 false로 설정하면 된다.alwyas로 설정하면 데이터가 최신 상태여도 무조건 refetch한다.fresh 상태로 유지된다.stale 상태가 된다. 이 때는 컴포넌트가 리마운트되거나 브라우저가 포커스되면 항상 데이터를 가져온다.
active 상태가 된다.inactive 상태가 되고 gcTime 카운트가 시작되고 이 시간동안에는 메모리에 데이터가 남아있다.gcTime이 지나기 전에 컴포넌트가 다시 마운트되고 같은 쿼리키가 active 된다면 타이머는 멈추고 데이터가 fresh하다면 네트워크 요청 없이 캐시된 데이터를 반환한다.gcTime이 지나게 되면 해당 쿼리 데이터는 메모리에서 삭제되고 동일한 쿼리키를 요청한다면 네트워크를 통해 데이터를 새로 받아온다.서버의 데이터를 변경 (POST, PUT, DELETE) 할 때 사용하는 Tanstack Query 훅이다.
useMutation에도 useQuery와 비슷하게 mutationKey와 mutationFn가 있다. useQuery와는 다르게 서버 데이터 캐싱할 때 쓰이지 않는데 왜 필요할까? 아래와 같은 3가지 이유가 있다고 하는데 추후 자세히 알아보도록 하자.const {
data,
error,
isError,
isIdle,
isPending,
isPaused,
isSuccess,
failureCount,
failureReason,
mutate,
mutateAsync,
reset,
status,
submittedAt,
variables,
} = useMutation(
{
mutationFn,
gcTime,
meta,
mutationKey,
networkMode,
onError,
onMutate,
onSettled,
onSuccess,
retry,
retryDelay,
scope,
throwOnError,
},
queryClient,
)
mutate(variables, {
onError,
onSettled,
onSuccess,
})
mutationFn에 전달한 함수가 실행된다.🔥 화면에 바로 변화를 보여주고 싶다면?
- 성공하는 시점 (onSuccess)에
useQuery의refetch함수를 실행시키는 방법- 쿼리 캐시를 무효화해서 최신 데이터를 가져오도록 하는 방법
queryClient객체의invalidateQueries를 사용한다.- 이 때 무효화시킬 쿼리키를 넣어준다.
qc.invalidateQueries("post");
=> 둘 중에 보통 두 번째 방법을 많이 사용한다. 쿼리 캐시를 stale로 만들어주기 때문에 자동으로 최신 데이터를 반영하는데 더 효율적이다. refetch는 사용자 액션에 의한 강제 새로고침이 필요한 경우에 사용하는 것이 좋다.
useQuery 와 동일하게 반환한다.Tanstack Query에 대해 간단히 정리해보았다. 이전에 정리할 당시에는 사용해보지 않고 정리했던 것이라 머리로만 이해하고 넘어갔었는데 사용해보며 작성하니 확실히 이해가 더 잘 되는 것 같다.
더 다양한 기능이 많아 사용해보며 필요한 것들을 추가해야 할 것 같다. 다음에는 간단히 useInfiniteQuery를 활용한 무한 스크롤에 대해 정리해보겠다.
사용해보니 더욱 이해가 잘 된다니 너무 좋습니다!