[TIL] 나는 React Query를 왜 사용했을까?

📌 들어가며

React를 사용하며 처음에는 API 요청을 useEffect와 useState로 직접 관리했다.
단순한 데이터 요청이라면 괜찮았지만, 프로젝트가 커질수록 아래와 같은 문제가 생겼다.

  1. 동일한 데이터를 여러 컴포넌트에서 사용하면서 중복 요청이 발생
  2. 데이터가 갱신되어도 화면에 즉시 반영되지 않음
  3. 로딩/에러 상태를 직접 관리해야하는 불편함 발생

결국 "서버에서 가져온 비동기 응답을 어떻게 효율적으로 처리할 것인가" 가 중요한 과제가 되었다.


📌 React Query가 뭔데?

React Query는 위와 같은 문제를 해결하기 위해 만들어진 서버 상태 관리 라이브러리다. Zustand나 Redux가 클라이언트 상태를 관리하는 데 초점을 둔다면, React Query는 서버의 데이터(fetch, cache, sync) 관리에 집중한다.

🔧 핵심 기능

  • 데이터 캐싱: 동일한 쿼리 키(queryKey)로 요청한 데이터는 자동으로 캐시되어 재요청 시 즉시 응답
  • 자동 리패칭: 포커스 복귀나 네트워크 재연결 시 최신 데이터로 자동 동기화
  • 상태 자동 관리: isLoading, isError, isFetching 등 로딩/에러 상태를 자동 제공
  • Mutation 관리: POST, PUT, DELETE 이후 관련 쿼리를 자동 갱신 (invalidateQueries)

💡 도입 후 변화

  1. 데이터 요청
    각 컴포넌트에서 중복 호출 → 캐싱으로 요청 수 감소
  2. 데이터 갱신
    useEffect로 state 갱신 필요 → 자동으로 최신 데이터 유지
  3. 코드 복잡도
    로딩/에러 처리로 인한 복잡한 코드 → 단순한 선언적 코드
 

React Query를 도입한 후, 데이터를 직접 다루는 부담이 줄어들고, 비즈니스 로직에 더 집중할 수 있게 되었다.

✍️ 코드 예시

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

function TodoList() {
  const { data, isLoading, isError } = useQuery({
    queryKey: ['todos'],
    queryFn: () => axios.get('/api/todos').then((res) => res.data),
  });

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

  return (
    <ul>
      {data.map((todo) => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  );
}

 

단 10줄 남짓의 코드로 로딩, 에러, 캐싱, 최신화가 모두 해결된다. “서버 상태를 선언적으로 관리한다”는 React Query의 철학이
이 한 예시로 명확하게 드러난다.


📌 SWR과 비교했을 때 React Query를 선택한 이유

React Query와 비슷한 서버 상태 관리 라이브러리 SWR도 있지만, 나는 다음과 같은 이유로 React Query를 선택했다.

  1. Query Key 관리가 구조적이라 캐시 무효화(invalidateQueries)가 명확하다.
    → [‘posts’, userId] 형태로 데이터 스코프를 세밀하게 구분할 수 있었다.
  2. 옵션과 제어가 풍부하다.
    → staleTime, cacheTime, retry, refetchOnWindowFocus 등으로 API 특성별 최적화 가능.
  3. 공식 문서의 완성도가 높다.
    → API Reference뿐 아니라 캐시 전략, 에러 처리, Suspense 등 고급 사례까지 다룸.
  4. npm trend 및 커뮤니티 신뢰도가 높다.
    → 유지보수 주기가 빠르고, 대규모 서비스에서도 안정적으로 채택 중.

📚 오늘의 배움

  • 클라이언트 상태와 서버 상태를 구분하여 비즈니스 로직을 구분하고 사용할 수 있게 되었다.
  • stale 데이터와 fresh 데이터를 구분하고, 캐시처리에 대한 이해를 한 층 높일 수 있었다.

🔖 레퍼런스