TanStack Query 세팅
TanStack Query는 서버 상태(비동기 데이터)를 캐싱하고 동기화하기 위한 라이브러리이다.
왜 TanStack Query를 쓸까?
서버 상태의 어려움
React에서 서버 데이터를 단순히 fetch + useEffect로만 관리하면 다음 문제가 자주 발생한다.
- 동일한 API를 여러 컴포넌트에서 중복 요청
- 로딩/에러 처리 코드가 매번 반복됨 (보일러플레이트)
- 캐시 정책이 없어서 화면 이동할 때마다 재요청
- 데이터 수정(POST/PUT) 후 목록을 수동으로 다시 불러와야 함
- 네트워크 복구, 탭 전환 시 데이터 동기화 어려움
이런 문제를 표준화된 방식으로 해결해 주는 것이 TanStack Query다.
TanStack Query를 안 쓰면 무엇을 직접 해야 할까?
아래 기능을 전부 직접 구현해야 한다:
- 요청 중복 방지
- 캐시 저장 및 만료 정책 (staleTime, cacheTime)
- 로딩/에러 상태 표준화
- 실패 시 재시도 로직
- 데이터 수정 후 자동 갱신(invalidate)
- optimistic update(낙관적 업데이트)
가능하지만, 앱이 커질수록 코드가 복잡해지고 유지보수가 급격히 어려워진다.
결국 데이터 fetching 로직이 아니라 상태 관리 문제가 된다.
언제 TanStack Query를 도입하면 좋을까?
다음과 같은 경우 도입을 권장한다:
- API 호출이 많고 화면 간 데이터 공유가 필요한 경우
- 동일 데이터를 여러 화면에서 사용하는 경우
- 로딩/에러 처리 패턴을 표준화하고 싶은 경우
- 데이터 수정 후 목록 갱신이 잦은 경우
- 성능 최적화(캐시 활용)가 필요한 경우
설치
bash
# 서버 상태 관리 라이브러리
npm i @tanstack/react-query
# React Query 상태를 시각적으로 확인하기 위한 개발용 도구
npm install -D @tanstack/react-query-devtools
# TanStack Query 사용 시 실수를 방지하기 위한 ESLint 플러그인
npm i -D @tanstack/eslint-plugin-query기본 설정
실제 프로젝트에서는 유지보수를 위해 QueryClient를 별도 파일로 분리하는 것을 권장한다.
1. QueryClient 분리
ts
// src/lib/queryClient.ts
import { QueryClient } from '@tanstack/react-query';
export const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: 1, // 네트워크 오류 발생 시 1회만 재시도
refetchOnWindowFocus: false, // 브라우저 포커스 시 자동 재요청 방지
},
},
});2. Provider 전역 적용
tsx
// src/main.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import App from './App';
import { queryClient } from './lib/queryClient';
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<App />
{/* 개발 환경에서만 Devtools 렌더링 */}
{import.meta.env.DEV && <ReactQueryDevtools initialIsOpen={false} />}
</QueryClientProvider>
</React.StrictMode>
);이후 모든 서버 데이터는 useQuery, useMutation 훅을 통해 관리한다.
3. ESLint 설정
.eslintrc.cjs 또는 .eslintrc.json에 TanStack Query 플러그인을 추가한다.
javascript
module.exports = {
extends: [
// ... 기존 설정
'plugin:@tanstack/eslint-plugin-query/recommended',
],
plugins: [
// ... 기존 플러그인
'@tanstack/query',
],
rules: {
'@tanstack/query/exhaustive-deps': 'error',
'@tanstack/query/no-unstable-deps': 'error',
},
};ESLint 규칙의 의미
exhaustive-deps: 쿼리 키와 의존성이 누락되지 않도록 보장no-unstable-deps: 불안정한 객체를 쿼리 키로 쓰는 것을 방지
주요 설정 옵션 설명
Query 기본 옵션
| 옵션 | 기본값 | 설정값 | 설명 |
|---|---|---|---|
retry | 3 | 1 | 요청 실패 시 재시도 횟수 |
refetchOnWindowFocus | true | false | 탭 전환 시 자동 재요청 여부 |
왜 이렇게 설정했나?
retry: 1: 네트워크 오류 발생 시 과도한 재시도를 방지하여 서버 부하를 줄인다.refetchOnWindowFocus: false:- 탭 전환할 때마다 자동으로 API를 다시 호출하는 기본 동작 비활성화
- 예기치 않은 네트워크 요청과 화면 깜빡임 방지
참고: 실시간성이 중요한 서비스(주식, 채팅, 대시보드 등)는
true유지 권장
Devtools (개발 도구)
React Query Devtools는 개발 환경에서만 동작하며, 다음을 실시간으로 확인할 수 있다:
- 현재 활성화된 쿼리 목록 및 상태
- 쿼리 상태:
fresh(신선),fetching(요청중),stale(만료됨),inactive(비활성) - 캐시에 저장된 데이터 내용
- 쿼리 무효화(invalidate) 및 수동 리페칭 테스트
사용법
- 앱 실행 후 화면 하단의 TanStack Query 아이콘을 클릭한다.
장단점
장점
- 서버 상태 관리 표준화
- 중복 요청 감소 → 성능 개선
- 로딩/에러 처리 일관성
- Devtools로 디버깅 용이
- Optimistic UI 구현 가능
단점
- 초기 학습 비용이 있음 (staleTime, cacheTime, queryKey 개념)
- queryKey 설계가 중요함
- 단순한 앱에는 과할 수 있음
언제 안 써도 될까?
- API 호출이 1~2개뿐인 단순 앱
- 정적 데이터 중심 프로젝트 (블로그, 랜딩 페이지)
- 서버 상태보다 로컬 UI 상태가 대부분인 경우 (드로잉 앱, 계산기 등)