프론트엔드 개발 중 서버로부터 데이터를 가져오는 일은 매우 빈번합니다. 이때 매우 유용한 라이브러리가 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를 도입한 후 다음과 같은 개선 효과를 얻었습니다: