본문 바로가기
카테캠/2단계

[7/22] React Query

by 쪼꼬에몽 2025. 7. 22.

- 비동기 서버 상태(fetching data)를 위한 React 전용 라이브러리

- 캐싱, 리페칭, 에러 처리, 상태 관리까지 통합적으로 처리하는 서버 상태 관리 도구

1. 서버 상태와 클라이언트 상태의 분리

구분 클라이언트 상태 서버 상태
예시 모달 열림 여부, 폼 입력 값 유저 정보, 게시글 목록
소스 사용자의 UI 상의 임시 값 외부 API 또는 DB
책임 UI 상태 조작 외부와 동기화 유지
추천 도구 React의 useState, useReducer, Recoil 등 React Query

분리하는 이유

  • 클라이언트 상태는 메모리 상에서만 관리되므로 즉시 변경 가능
  • 서버 상태는 fetching, error, loading 상태 등을 항상 고려해야 함
  • Redux 등으로 서버 상태를 관리하면 불필요한 보일러플레이트가 발생하고 유지가 어려워짐

2. 데이터 페칭 및 캐싱 자동화

React Query가 자동으로 해주는 일

  • useQuery()로 API 요청 -> 응답값을 캐시에 저장
  • 같은 key로 요청이 다시 들어오면 캐시에서 불러오기
  • 설정에 따라 자동으로 refetch, background에서 데이터 최신화
const { data, isLoading } = useQuery(['posts'], fetchPosts);

['posts']: Query Key

  • 캐시의 고유 식별자
  • posts라는 이름으로 데이터를 캐싱하고 추후 동일한 키를 사용해서 데이터를 재사용하거나 리페칭
  • 배열 형태로 쓰는 이유는 동적 파라미터(상황에 따라 바뀌는 값)를 함께 넣기 위함
useQuery(['posts', userId], () => fetchUserPosts(userId));

-> userId마다 별도로 캐시됨 

fetchPosts: Query Function

  • 데이터를 가져오는 비동기 함수
async function fetchPosts() {
	const res = await fetch(url);
    return res.json();
}
  • 이 함수를 자동으로 호출해서 데이터를 가져오고, 그 결과를 캐싱함

반환값 구조

const { data, isLoading, error } = useQuery(...);
  • data : fetchPosts() 함수 결과
  • isLoading : 요청 중이면 true
  • error : 요청 실패 시 오류 정보 

자동 refetch 조건 예시

  • 컴포넌트 리마운트
  • 브라우저 포커스
  • 시간 기반 refetch (5분마다)

Redux에서는 직접 구현해야 하지만 React Query는 기본값으로 제공함

3. 복잡한 비동기 로직의 간소화

기존 Redux 방식

const FETCH_POSTS = 'FETCH_POSTS';
const FETCH_POSTS_SUCCESS = 'FETCH_POSTS_SUCCESS';

React Query 방식

const { data, isLoading } = useQuery(['posts'], fetchPosts);
  • 데이터 요청 상태(loading, error, data) 자동 관리
  • 로딩 스피너, 에러 처리도 간단히 연동 가능
  • 콜백이나 Thunk, Saga 등의 미들웨어 설정 없이도 간단하게 비동기 처리 가능

4. 옵티미스틱 업데이트와 실시간 처리

옵티미스틱 업데이트란?

  • 서버 응답이 오기 전에 UI를 먼저 바꿔주는 전략
useMutation(updateLike, {
	onMutate: newData => {
    	queryClient.setQueryData(['likes'], old => old + 1); // 먼저 UI 업데이트 
    },
    onError: () => {
    	queryClient.invalidateQueries(['likes']); // 실패 시 롤백 
    }
});
  • useMutation을 사용해 좋아요를 업데이트하는 비동기 작업을 수행
  • UI를 Optimistic Update 방식으로 빠르게 반응시키는 구조

useMutation(updateLike, ...)

  • updateLike 함수는 서버에 좋아요를 업데이트하는 비동기 함수
  • useMutation은 서버에 변경을 요청하고, 그 과정에서 UI도 제어할 수 있게 해주는 훅

onMutate

  • 서버에 요청을 보내기 바로 직전에 실행됨
  • Optimistic Update를 위해 사용함
    • 실제 서버 응답이 오기 전에 UI를 미리 바꿈
    • 사용자 입장에선 빠르게 반응하는 UI를 보게 됨
queryClient.setQueryData(['likes'], old => old + 1);
  • ['likes'] 캐시 값을 수동으로 업데이트 함
  • 기존 값(old)에 1을 더해 화면에 바로 반영되게 함

onError

  • 서버 요청이 실패했을 때 실행됨
  • 앞서 반영한 Optimistic Update가 틀렸을 수 있으니,
    • invalidateQueries로 ['likes'] 쿼리를 무효화하고,
    • 서버에서 다시 데이터를 다시 가져오게 함 (롤백)

실시간 업데이트 방법

  • Polling : 일정 주기로 데이터 다시 요청
  • WebSocket : 서버에서 직접 푸시 (React Query 자체는 안 하지만, 통합 사용 가능)

5. 개발자 도구 지원

  • 어떤 쿼리가 loading 중인지
  • 어떤 데이터가 캐시돼 있는지
  • 쿼리마다 status / state / refetch 여부
  • 즉시 캐시 무효화 / 수동 refetch 가능
npm install @tanstack/react-query-devtools
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';

<QueryClientProvider client={queryClient}>
	<App />
    <ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>

QueryClientProvider

  • React Query의 context provider
  • 내부에서 useQuery, useMutation 등을 사용할 수 있게 전역으로 설정함
  • client={queryClient}는 QueryClient 인스턴스를 전달함. 이 인스턴스는 쿼리 캐시, 설정 등을 관리함 
const queryClient = new QueryClient();
  • <App />이 QueryClientProvider 안에 있어야 React Query 기능이 동작함

ReactQueryDevtools

  • React Query 상태를 시각적으로 보여주는 개발 도구
  • 브라우저에서 열리는 Devtools 탭처럼, 현재 캐시된 데이터, 쿼리 상태, 에러 상태를 볼 수 있음
  • initialIsOpen={false}는 처음엔 닫힌 상태로 시작하겠다는 의미

6. 커뮤니티 및 생태계

  • GitHub Star 수, 다운로드 수 모두 전역 상태 관리 라이브러리 중 최상위
  • TanStack Query라는 이름으로 Vue, Svelte, Solid까지 확장됨

7. 결론

  • 서버에서 가져온 데이터를 자동으로 캐싱, 리페칭, 동기화
  • 복잡한 상태 로직 없이 간단한 API로 사용 가능
  • 실제 프로덕션에서 개발 속도와 안정성을 크게 향상시켜줌
  • 클라이언트 상태는 useState, Recoil
  • 서버 상태는 React Query

 

'카테캠 > 2단계' 카테고리의 다른 글

[7/22] React Query - useMutation  (1) 2025.07.22
[7/22] React Query - useQuery  (0) 2025.07.22
[7/22] 무한 스크롤 옵저버  (0) 2025.07.22
[7/21] Intersection Observer  (1) 2025.07.22
[7/18] Fetch API Wrapping  (0) 2025.07.18