IT 개발2025-07-02

TanStack Query axios 사용법, React API 안정성 높이기

버튼 한 번에 중복 요청 3번? TanStack Query 사용법으로 해결했습니다.

React API 상태관리가 자꾸 불안정해지는 이유

안녕하세요. 사랑받는 IT 프로덕트의 첫걸음, 똑똑한개발자입니다.

3줄 요약

  1. 중복 요청·멈춘 듯한 화면·갱신 안 되는 데이터는 대부분 비동기 처리와 상태 관리의 불안정성에서 시작됩니다.

  2. TanStack Query axios 사용법의 핵심은 axios를 버리는 게 아니라, axios 호출을 queryKey로 캐싱·중복 제거·자동 재시도 레이어에 얹는 것입니다.

  3. 중복 요청 방지, 네트워크 복구 시 자동 refetch, refetchInterval 자동 갱신 세 가지만으로도 서비스 체감 안정성이 달라집니다.

실제 서비스를 운영하다 보면 사용자 측에서 이런 문제가 자주 발생하는데요!

버튼을 누르면 중복 요청이 여러 번 전송됨

네트워크가 느릴 땐 화면이 멈춘 것처럼 보임

데이터 갱신 후에도 화면엔 이전 데이터가 그대로 남아 있음

세 가지 모두 서로 다른 버그처럼 보이지만, 원인은 하나로 모입니다. 비동기 데이터를 화면 상태와 따로 관리하고 있다는 것이죠.

useEffect 안에서 axios를 호출하고 결과를 useState에 담는 구조에서는 요청이 몇 개 떠 있는지, 지금 화면의 데이터가 최신인지 프레임워크가 알 수 없습니다. 그 판단을 전부 개발자가 손으로 짜게 되고, 컴포넌트가 늘어날수록 같은 로직이 복사됩니다.

이 문제를 깔끔하게 해결해주는 도구가 바로 TanStack Query입니다. (과거 이름: react-query)

TanStack Query란? axios만 쓸 때와 무엇이 다른가요?

TanStack Query는 비동기 데이터 처리에 최적화된 리액트 라이브러리로, API 요청·응답을 기반으로 한 데이터 패칭(fetching), 캐싱(caching), 갱신(refetching)을 자동으로 관리해줍니다.

여기서 자주 나오는 오해를 먼저 정리하고 갈게요. TanStack Query는 axios의 대체품이 아닙니다. axios는 HTTP 요청을 보내는 도구, TanStack Query는 그 요청의 상태와 생애주기를 관리하는 도구입니다. 그래서 실무에서는 둘을 함께 씁니다. axios 인스턴스에 baseURL과 인터셉터(토큰 주입, 에러 정규화)를 두고, 그 함수를 TanStack Query의 queryFn으로 넘기는 조합이 가장 흔한 TanStack Query axios 사용법입니다.

TanStack Query 주요 기능 요약

  • 서버 상태 캐싱 (데이터 재요청 최소화)

  • 요청 중복 방지 및 요청 병합

  • 자동 재시도, 실패 시 exponential backoff 지원

  • 화면 포커스·네트워크 재연결 시 자동 refetch

  • 전역 데이터 동기화

TanStack Query는 전통적인 useEffect + axios 패턴보다 훨씬 효율적이며, 성능·UX·유지보수 측면에서 큰 장점이 있습니다. 😊

useEffect + axios와 TanStack Query + axios, 무엇이 달라지나요?

판단 기준

useEffect + axios

TanStack Query + axios

중복 요청

컴포넌트마다 각각 요청 → 같은 API가 3~4번 호출

동일 queryKey 요청은 자동 병합, 캐시 재사용

로딩·에러 상태

isLoading·error를 매번 useState로 직접 선언

훅 반환값으로 내장 제공, UI 처리 일관성 확보

실패 시 재시도

try·catch + 재호출 로직을 직접 구현

기본 재시도 내장(클라이언트 3회) + exponential backoff

데이터 신선도

"지금 화면 데이터가 최신인가"를 판단할 방법이 없음

staleTime·gcTime으로 신선도와 캐시 수명을 선언적으로 관리

표의 오른쪽 열에서 axios가 사라지지 않았다는 점에 주목해 주세요. 바뀌는 건 요청 도구가 아니라 요청을 감싸는 관리 레이어입니다.

TanStack Query axios 사용법, 코드로 확인해볼까요?

이제 간단한 예제로 TanStack Query의 기본 사용법을 확인해보겠습니다!

설치

npm install @tanstack/react-query

기본 데이터 패칭 구현

import { useQuery } from '@tanstack/react-query';
import axios from 'axios';

const fetchUsers = () => axios.get('/api/users').then(res => res.data);

function UserList() {
  const { data, isLoading, error } = useQuery({
    queryKey: ['users'],
    queryFn: fetchUsers,
  });

  if (isLoading) return <p>로딩 중...</p>;
  if (error) return <p>에러 발생!</p>;

  return (
    <ul>
      {data.map((user: any) => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

여기서 눈여겨볼 장점은?

  • queryKey로 캐시 키를 관리해 동일한 요청을 재사용할 수 있습니다

  • isLoading, error 상태값이 내장되어 UI 처리 일관성이 올라갑니다

  • 백그라운드에서 데이터가 자동 업데이트됩니다 (staleTime, refetch 설정으로 제어 가능)

코드 양 자체는 크게 줄지 않아 보일 수 있습니다. 하지만 이 컴포넌트가 10개로 늘어났을 때 추가로 써야 할 코드가 거의 없다는 것이 실제 차이입니다. queryKey가 같으면 열 군데에서 호출해도 요청은 한 번입니다.

실무에서 체감한 안정성·성능 최적화 3가지

실제 서비스를 운영하면서 TanStack Query를 도입해 얻은 효과는 다음과 같습니다.

1. 중복 요청 방지

같은 API를 여러 컴포넌트에서 호출하더라도 최초 1회만 요청하고 이후엔 캐시를 사용합니다. → 트래픽 절감 + UX 개선

헤더, 사이드바, 본문에서 각각 사용자 정보를 필요로 하는 흔한 레이아웃을 떠올려 보세요. 기존 방식이라면 요청 3건, TanStack Query라면 1건입니다. 이 중복 요청 방지 효과는 화면이 복잡해질수록 커집니다.

2. 오프라인·온라인 상태 연동

인터넷 연결이 끊겼다가 복구되면 자동으로 최신 데이터를 요청합니다. → 사용자가 새로고침이라는 실수 없이 데이터 동기화

3. 자동 갱신

옵션 설정으로 일정 주기마다 API를 자동 재요청할 수 있습니다(refetchInterval). → 모니터링, 실시간 대시보드 구현에 적합

staleTime과 재시도, 어떻게 설정하면 좋을까요?

TanStack Query axios 사용법에서 가장 자주 잘못 쓰이는 부분이 옵션 기본값입니다. 도입만 하고 기본값을 그대로 두면 "캐싱했는데 왜 계속 요청이 나가지?"라는 상황을 만나게 됩니다.

  • staleTime의 기본값은 0입니다. 즉 데이터를 받는 즉시 stale로 간주되어, 컴포넌트가 다시 마운트되거나 창에 포커스가 돌아올 때마다 refetch가 일어납니다. 변경 주기가 느린 데이터(공통 코드, 카테고리, 프로필)는 staleTime을 넉넉히 주는 것만으로 요청 수가 눈에 띄게 줄어듭니다. 중복 호출을 줄이는 용도라면 최소 20초 이상을 기준으로 잡는 것이 무난합니다.

  • gcTime은 캐시가 메모리에 남아 있는 시간입니다. inactive 상태가 된 쿼리도 gcTime이 지나기 전에 다시 마운트되면, 새 데이터를 받아오는 동안 이전 캐시를 먼저 보여줍니다. 화면이 하얗게 비는 구간이 사라지는 이유가 여기에 있습니다.

  • retry 기본값은 클라이언트 3회, 서버 0회입니다. 네트워크 흔들림에는 큰 도움이 되지만, 401이나 404처럼 재시도해도 결과가 같은 응답까지 세 번씩 두드리게 됩니다. axios 인터셉터에서 상태 코드를 정규화한 뒤 retry를 함수 형태로 주어 4xx는 즉시 포기하도록 분기하는 편이 안전합니다.

정리하면, 도입 자체가 목적이 아니라 우리 데이터의 성격에 맞게 신선도와 재시도 정책을 선언하는 것이 실제 안정성으로 이어집니다.

자주 묻는 질문

1. TanStack Query를 쓰면 axios는 지워야 하나요?

아니요. axios는 요청을 보내는 계층, TanStack Query는 그 요청의 상태를 관리하는 계층이라 역할이 겹치지 않습니다. axios 인스턴스에 인터셉터와 공통 에러 처리를 유지한 채 queryFn으로 넘기는 조합이 실무 표준에 가깝습니다.

2. Redux 같은 전역 상태 관리 라이브러리를 대체할 수 있나요?

서버에서 내려오는 데이터(서버 상태)는 대체할 수 있습니다. 다만 모달 열림 여부, 폼 입력값처럼 서버와 무관한 클라이언트 상태는 여전히 별도 수단이 필요합니다. 전역 스토어에 API 응답만 쌓아두던 코드라면 상당 부분 정리됩니다.

3. POST, PUT, DELETE 요청은 어떻게 처리하나요?

조회는 useQuery, 변경은 useMutation을 사용합니다. 변경 후 관련 queryKey를 무효화하면 화면 데이터가 자동으로 최신 상태로 갱신되어, "갱신했는데 이전 데이터가 그대로 남는" 문제가 구조적으로 사라집니다.

비동기 처리의 복잡함, 이제 관리할 수 있습니다

서비스가 성장할수록 API 요청 흐름은 복잡해지고, 그에 따라 상태 관리도 점점 어려워지는데요! 기존의 로컬 상태 + useEffect 방식으로는 한계가 명확하죠.

TanStack Query는 비동기 데이터의 흐름을 하나의 통일된 구조로 관리하면서, 서비스의 신뢰성과 일관성을 유지할 수 있도록 돕습니다.

화면을 새로 고치지 않아도 자동으로 최신 데이터가 반영되고, 사용자는 로딩과 에러 상황을 명확하게 인지하며, 개발자는 중복 로직 없이 깔끔한 코드를 유지할 수 있는 상태관리 방식! 이 모든 걸 가능하게 하는 건 단순한 라이브러리가 아니라 서비스 수준을 끌어올리는 데이터 관리 전략이라고 할 수 있는데요.

그리고 그것이 TanStack Query가 필요한 이유입니다.

그리고 이런 구조를 서비스에 제대로 녹이고 싶다면?

실제 서비스 환경에서 TanStack Query 기반 아키텍처를 도입하고, 데이터 흐름과 UX를 안정적으로 설계할 수 있는 검증된 프론트엔드 외주 개발팀, 똑똑한개발자를 추천드립니다 :)

복잡한 상태관리 없이, 믿을 수 있는 데이터 흐름을 구축하고 싶으신가요?

지금 바로 똑똑한개발자와 함께하세요!

클립보드에 복사되었어요 ✓
이 글을 공유해보세요!