프론트엔드 개발 중 서버로부터 데이터를 가져오는 일은 매우 빈번합니다. 이때 매우 유용한 라이브러리가 tanstack-query 였습니다. 그런데 tanstack-query 를 이용해 가져온 데이터를 zustand 등 전역상태관리 라이브러리로 관리하려고 할 때 문제가 발생했습니다. 비동기적일 수 밖에 없는 데이터 fetching 후 바로 데이터를 전역상태에 담으려고 하니 부자연스럽게 느껴졌습니다.
사실 tanstack-query 의 useQuery 로 가져온 data 는 그냥 전역상태와 다름 없었습니다. 굳이 fetch한 데이터를 로컬 전역 상태에 담을 필요가 없고 그냥 어디서든 useQuery 호출 하면 되는 것이었습니다. tanstack-query의 동작방식을 이해하지 못해 발생한 문제였고, 실제 fetching 이 언제 되는지는 dev tool 로 손쉽게 확인이 가능했습니다.
1. tanstack-query 설치 및 설정
프로젝트에 tanstack-query를 설치하고, QueryClient
와 QueryClientProvider
를 설정했습니다.
npm install @tanstack/react-query @tanstack/react-query-devtools
// index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
ReactDOM.render(
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<App />
<ReactQueryDevtools initialIsOpen={true} />
</QueryClientProvider>
</React.StrictMode>,
document.getElementById('root')
);
2. 기존 Zustand를 통한 데이터 관리 제거
Zustand를 사용하여 useQuery
의 데이터를 전역 상태에 저장하던 로직을 제거하고, TanStack Query의 useQuery
훅을 직접 활용하도록 수정했습니다.
// 기존 Zustand 사용 예시
import create from 'zustand';
import { useQuery } from '@tanstack/react-query';
const useStore = create((set) => ({
data: [],
setData: (newData) => set({ data: newData }),
}));
const Component = () => {
const { data, setData } = useStore();
const { data: queryData, isPending, error, } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodos
});
React.useEffect(() => {
if (queryData) setData(queryData);
}, [queryData, setData]);
// ...
};
// TanStack Query 도입 후
import { useQuery } from '@tanstack/react-query';
const Component = () => {
const { data, isPending, error } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodos
});
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error!</div>;
return (
<div>
{data.map(todo => (
<div key={todo.id}>{todo.title}</div>
))}
</div>
);
};
tanstack-query를 도입한 후 다음과 같은 개선 효과를 얻었습니다: