반응형

 

리액트 쿼리(React Query)란?

     React Query리액트에서 서버 상태(Server State)를 쉽게 관리할 수 있도록 도와주는 라이브러리이다.

     일반적인 상태관리 라이브러리(예: Redux, Zustand)는 클라이언트 상태(UI 상태 등)를 주로 다루는데,

     React Query는 서버에서 가져오는 데이터(API 요청 등)를 관리하는 데 특화되어 있다.

[개념 알고 가기 🔍]
1) 서버 상태란?
  - 예를 들어 GET /users, GET /posts 같은 API로 받아오는 데이터를 말한다.
     이 데이터는 서버에 있고, 클라이언트에서 가져와야 하니까 서버 상태라고 불린다.

리액트 쿼리를 사용하는 이유

 

  • 로딩 상태 관리 (loading, isFetching)
  • 에러 상태 처리 (try/catch)
  • 데이터 캐싱
  • 다시 불러오기 (Refetch)
  • 백그라운드 업데이트
  • 페이지네이션, 무한 스크롤
  • 데이터 동기화

    일반적으로 데이터 API를 가져올 때는 위의 내용들이 필요하다.

    하지만 리액트 쿼리에서는 위의 내용들을 지원해주므로 편리하게 사용할 수 있다.

기능 설명
로딩/에러 상태 관리 isLoading, isError 등 자동으로 제공
데이터 캐싱 동일한 요청에 대해 중복 호출 방지
백그라운드 리패칭 오래된 데이터는 자동으로 새로고침
쿼리 무효화 mutation 이후 관련 데이터만 정확히 다시 불러오기
윈도우 포커스시 재요청 사용자 눈에는 항상 최신 데이터처럼 보이도록
페이지네이션/무한 스크롤 쉽게 구현 가능
SSR & prefetch 지원 서버사이드 렌더링도 지원

 


따라서 리액트 쿼리를 사용한다면 다음과 같은 이점을 얻을 수 있다.

 

1. 코드 간결성

    복잡한 상태 관리 로직을 생략할 수 있고, 필요한 건 useQuery, useMutation 두 가지 훅이면 충분하다.

 

2. 성능 향상 
    중복 요청 방지(캐시), 사용자 인터랙션 시 빠르게 응답, 백그라운드 업데이트로 UX 향상

 

3. 유지보수 용이성

    비즈니스 로직과 API 관리가 분리되어 깔끔, 새로운 API 추가나 수정 시에도 일관된 방식


리액트 쿼리 쓰는 이유 정리 🔍

     1) 복잡한 서버 상태 관리간단하게 만들어줌
     2) 로딩, 에러, 캐싱, 재요청 등 필수 기능을 자동으로 처리
     3) 코드가 간결해지고 버그가 줄어듦
     4) 성능사용자 경험(UX)이 좋아짐
     5) 빠른 개발 속도, 유지보수 쉬움


 

그렇다면 이제 React-Query를 사용해보자!

설치 방법
npm install @tanstack/react-query

    * 예전 이름은 react-query였고, 지금은 @tanstack/react-query로 바뀜

 

⚠️ 리액트 쿼리를 설치할 때 리액트 버전과 호환 가능한 버전인지 확인해야한다.

React-Query 버전 호환 가능 React 버전 비고
v3.x (react-query) React 16.8 이상 오래된 버전, 이제는 권장되지 않음
v4.x (@tanstack/react-query) React 17, React 18 이상 최신 기능 대응, 현재 주로 사용되는 버전
v5 (알파/베타) React 18 이상 Suspense/Concurrent 대응 강화, 사용 가능하지만 실험적일 수 있음

설치 후 세팅

    리액트 쿼리를 사용하기 위해서는 QueryClient 만들고, Provider로 감싸줘야한다.

    * Provider를 꼭 써야 React Query 기능이 작동

import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

const queryClient = new QueryClient();

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <MyComponent />
    </QueryClientProvider>
  );
}

리액트 쿼리 주요 기능
기능 설명
useQuery 데이터 조회 (GET)
useMutation 데이터 쓰기 (POST, PUT, DELETE 등)
isLoading, error 상태 자동 관리
refetch() 수동 재요청
invalidateQueries() 쿼리 무효화 (자동 리패칭)
캐싱 동일한 데이터 요청 방지
배경 데이터 갱신 사용자 모르게 데이터 업데이트

1. useQuery로 데이터 불러오기

  • queryKey: 이 쿼리의 고유 키. 데이터를 식별하고 캐시 관리에 사용
  • queryFn: 데이터를 실제로 가져오는 함수 (API 호출 등)
  • data, isLoading, error: 상태 자동 관리

 

[예시 코드]

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

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

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

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

2. useMutaion으로 데이터 쓰기

 

[예시 코드] 

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

function AddUser() {
  const mutation = useMutation({
    mutationFn: (newUser) => axios.post('/api/users', newUser),
    onSuccess: () => {
      // 성공 시 users 쿼리를 다시 불러옴
      queryClient.invalidateQueries({ queryKey: ['users'] });
    },
  });

  return (
    <button onClick={() => mutation.mutate({ name: '홍길동' })}>
      유저 추가
    </button>
  );
}

3. 리패칭 (refetching)

데이터를 수동으로 다시 불러오고 싶을 때 사용한다.

const { data, refetch } = useQuery(...);

<button onClick={() => refetch()}>다시 불러오기</button>

4. 자동 새로고침 (Refetch Interval)

자동으로 새로고침하고 싶을 때는 useQuery에 refetchInterval 옵션을 설정한다.

useQuery({
  queryKey: ['users'],
  queryFn: fetchUsers,
  refetchInterval: 10000, // 10초마다 자동으로 새로고침
});

5. 캐싱과 상태관리

React Query는 자동으로 데이터 캐싱을 하고, 동일한 queryKey로 요청하면 서버에 다시 요청하지 않고 캐시된 데이터를 반환한다.

  • 최초 로딩 시 서버 요청
  • 같은 컴포넌트가 다시 렌더링되면 캐시된 데이터 사용
  • 설정에 따라 일정 시간이 지나면 자동으로 다시 요청 (stale time)
[개념 알고가기 🔍]
1) staleTime이란? - 신선한 상태 유지 시간
    ① 동작 방식 (staleTime: 10000으로 설정된 경우)
         쿼리가 처음 실행되면 데이터를 받아오고, 그 시점부터 10초 동안은 stale 상태가 아님.
         이 기간 동안은 React Query가 자동으로 재요청(refetch) 하지 않음.
         10초가 지나면 데이터가 stale(오래됨)으로 간주되고, 다음 조건 중 하나가 일어나면 다시 데이터를 요청(refetch) 해
          : 컴포넌트가 다시 mount되거나, 창에 다시 포커스되거나, 네트워크가 다시 연결될 때 등

    ② 언제 유용할까?
         너무 자주 데이터를 새로 불러오지 않아도 되는 경우
         (예: 공지사항, 프로필, 상품 목록 등 자주 바뀌지 않는 데이터)

2) cacheTime이란? - 캐시 유지 시간
    ① 동작 방식 (cacheTime: 300000으로 설정된 경우)
         컴포넌트가 unmount되어도 데이터를 바로 삭제하지 않음.
         이 cacheTime이 끝날 때까지 메모리 안에 캐시로 유지
         다시 같은 쿼리가 mount되면, 서버에 요청하지 않고 캐시된 데이터를 바로 사용함.

    ② 언제 유용할까?
         - 사용자가 같은 페이지로 자주 왔다 갔다 할 때
         - 리스트 → 상세 → 다시 리스트 같은 구조에서 유용
         - 불필요한 재요청을 줄여 성능 최적화 가능

  •  staleTime이 길면 = 네트워크 요청 줄어듦, 대신 데이터는 오래됨 가능성 ↑
  • cacheTime이 길면 = 빠른 화면 전환 가능, 하지만 메모리 사용량 ↑
[간단 요약]
옵션 의미 기본 값
staleTime 데이터를 신선하다고 간주할 시간 (ms) 0 (즉시 stale 처리)
cacheTime 데이터가 사용되지 않아도 캐시에 유지되는 시간 (ms) 5분 (300000)
[추천 예시]
1) 실시간 데이터 (ex. 실시간 주가, 라이브 채팅 등) ➡️ staleTime: 0, refetchInterval 사용해서 실시간 유지
2) 일반 리스트 (ex. 게시글 목록) ➡️ staleTime: 30초~1분, cacheTime: 3~5분
3) 잘 바뀌지 않는 데이터 (ex. 유저 프로필) ➡️ staleTime: Infinity (영원히 fresh), cacheTime: Infinity (계속 보관)

자주 사용하는 옵션들
useQuery({
  queryKey: ['posts'],
  queryFn: fetchPosts,
  staleTime: 5000, // 5초 동안은 신선한 데이터로 간주
  cacheTime: 1000 * 60 * 5, // 5분간 캐시 유지
  refetchOnWindowFocus: true, // 창 포커스될 때 refetch
});

 

반응형

+ Recent posts