완벽 가이드 - Tanstack Query

primav·2025년 1월 3일

React

목록 보기
30/35
post-thumbnail

Tanstack Query란?

HTTP 요청을 전송하고 프론트엔드 UI와 백엔드 데이터가 동기화된 상태로 유지하는데 이용하는 라이브러리이다.

❗️반드시 필요한 것이 아니라 useEffect / fetch 를 사용하여도 된다.
하지만 Tanstack Query를 사용하면 더 쉽고 간단하게 프로젝트가 가능하다.

✔️ Before : useEffect 사용

단점

코드가 길어지고, HTTP 요청을 받을 때마다 모든 컴포넌트에서 이렇게 작성해야 한다.
이때 useHTTP라는 커스텀 훅을 만들어 이 코드를 전부 넣은 후 재사용을 할 수 있다.

하지만,

  1. 다른 사이트에 갔다가 왔을 때 데이터가 업데이트된 경우, 변경된 데이터를 가져와 UI를 업데이트 하려고 할 때.

  2. 가져온 데이터를 캐시처리하고 메모리에 저장해서, 필요할 때 다시 사용하려고 할 때

➡️ 이러한 기능들을 넣으려고 할 때 직접 커스텀하기는 어려우므로 Tanstack 쿼리가 제공하는 고급 기능을 통해 적용할 수 있다.

 useEffect(() => {
    async function fetchEvents() {
      setIsLoading(true);
      const response = await fetch('http://localhost:3000/events');

      if (!response.ok) {
        const error = new Error('An error occurred while fetching the events');
        error.code = response.status;
        error.info = await response.json();
        throw error;
      }

      const { events } = await response.json();

      return events;
    }

    fetchEvents()
      .then((events) => {
        setData(events);
      })
      .catch((error) => {
        setError(error);
      })
      .finally(() => {
        setIsLoading(false);
      });
  }, []);

✔️ After : Tanstack Query 사용

장점

백엔드 데이터를 수정했을 때 사이트에서 바로 반영이 된다.

const { data, isPending, isError, error, refetch } = useQuery({
    queryKey: ["events"],
    queryFn: fetchEvents
  });

📌 Tanstack Query 사용법

1. 라이브러리 설치

npm install @tanstack/react-query

2. 라이브러리 import (데이터 받을 곳.jsx)

import { useQuery } from "@tanstack/react-query"

3. React Query 설정 및 초기화

  • QueryClient 객체 생성
import { QueryClient } from "@tanstack/react-query";
const queryClient = new QueryClient();
  • QueryClientProvider 로 감싸기
import { QueryClientProvider } from "@tanstack/react-query";

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

🎯 useQuery

이 훅을 사용하면, 원하는 데이터 정보, 로딩 상태 정보, 오류 정보를 알 수 있다.
객체를 전달하며, promise 를 반환하므로 원하는 값을 구조 분해 할당으로 빼올 수 있다.
ex) data, isPending, isError, error, refetch

  • Tanstack Query 는 HTTP 요청을 전송하는 로직이 내장되어 있지 않고, 요청을 관리하는 로직을 제공한다.
    ➡️ 요청과 관련된 데이터, 발생 가능한 오류, 로딩 상태 등을 추적하는 역할을 하는 것이다.
  • 요청을 전송하는 코드는 우리가 직접 작성해야 한다!

useQuery 주요 속성

  • queryKey : 쿼리를 식별하는 고유한 값으로, 배열 형태로 지정한다.

    • 쿼리 키와 일치하는 캐시된 데이터가 없으면 - 서버에서 새로운 데이터를 가져온다.
    • 서버에서 데이터를 가져오면 그 데이터는 캐시되고 그 이후 요청부터는 캐시된 데이터를 사용할 수 있다.
  • queryFn : 실제 요청을 전송할 때 실행할 코드
    직접 HTTP 요청 코드를 작성해야 한다.

  • staleTime
    TanStack Query는 캐시한 데이터를 신선(Fresh)하거나 상한(Stale) 상태로 구분해 관리한다.
    즉, 캐시된 데이터가 신선하다면 캐시된 데이터를 사용하고, 만약 데이터가 상했다면 서버에 다시 요청해 신선한 데이터를 가져온다.

    • 데이터가 상하는 데까지 걸리는 시간은 staleTime 옵션으로 지정할 수 있다.
    • 기본 값은 0 으로 상한 상태이므로, 다른 페이지에 갔다오면 데이터를 다시 받아오는 것이 기본인 것이다.
    • 신선한지 상했는지 여부는 isStale 로 확인할 수 있다.
  • gcTime - 캐시된 데이터를 언제 버릴지 (garbage Collection) 시간 설정

    • 기본적으로 React Query는 데이터를 캐시된 상태로 유지하되, 데이터가 더 이상 필요하지 않을 때 gcTime이 경과하면 데이터를 삭제한다.
    • gcTime이 경과하기 전까지는 캐시된 데이터를 재사용할 수 있다.
    • 기본값은 5분 (1000 * 60 * 5) 이다.
  • enabled - 쿼리가 실행될지 여부를 제어한다.

    • false : 실행 x true : 실행 o
import { useQuery } from '@tanstack/react-query'

export default function DelayedData() {
  const { data } = useQuery({
    queryKey: ['delay'],
    queryFn: async () => (await fetch('https://api.primav.dev/v0/delay?t=1000')).json()
  })
  	enabled: searchTerm !== undefined
  return <div>{JSON.stringify(data)}</div>
}

isLoading 과 isPending 차이점

isLoading

  • 쿼리가 처음 실행될 때만 true
  • 쿼리가 성공적으로 데이터를 가져오거나 실패하면 false

isPending

  • 쿼리가 실행 중인 상태
  • 비동기 작업을 진행하는 중에 true로 설정
  • 데이터가 로딩 중일 뿐만 아니라 리패칭이나 재요청이 있을 때 true
상태isLoadingisPending
의미첫 번째 쿼리 로딩 상태쿼리가 진행 중일 때 (로딩/리패칭)
언제 true?컴포넌트 렌더링 시 처음 쿼리가 실행될 때쿼리가 로딩 중이거나 재요청 중일 때
주요 용도처음 데이터를 요청할 때 로딩 상태를 표시데이터가 로딩되거나 새로고침/리패칭 중일 때 표시
해제 시점쿼리가 완료되면 false로 변경쿼리가 완료되면 false로 변경

🎯 useMutation

데이터를 수정할 때 사용한다. (write)
useQuery와 달리, useMutation은 자동으로 실행되지 않으며, 주로 이벤트 핸들러나 특정 조건에 의해 명시적으로 호출될 때 실행된다.

  • mutationKey - 지정할 수는 있지만 필요 없음

  • mutationFn - 실행할 함수
    실제 데이터 변경 작업을 처리하며, mutate 호출 시 인자로 전달된 데이터를 처리한다.

  • mutate - 요청을 언제 실행할 것인지 지정해주는 함수
    호출 시에 비동기 작업을 실행한다.

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

const createNewEvent = async ({ event }) => {
  // API 호출 또는 데이터 처리
  const response = await fetch('/api/events', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(event),
  });

  if (!response.ok) {
    throw new Error('Event creation failed');
  }

  return response.json();
};

function EventForm() {
  const { mutate, isLoading, isError, error } = useMutation({
    mutationFn: createNewEvent,
  });

  const handleSubmit = (formData) => {
    mutate({ event: formData });
  };

  return (
    <div>
      <form onSubmit={(e) => {
        e.preventDefault();
        const formData = { name: 'New Event', date: '2025-01-01' }; // 예시 데이터
        handleSubmit(formData);
      }}>
        <button type="submit" disabled={isLoading}>Create Event</button>
      </form>

      {isError && <p>Error: {error.message}</p>}
      {isLoading && <p>Loading...</p>}
    </div>
  );
}

참고 링크 - 이해가 안되는 부분에서 도움을 많이 받음

0개의 댓글