Tanstack query란?
서버 상태를 관리하기 위한 라이브러리로, 데이터를 패칭하고 캐싱, 동기화, 무효화 등의 기능을 제공한다.
> 개발자는 이전에 비해 훨~씬 비동기 로직을 간편하게 작성하고 유지보수성을 높일 수 있다.
주요 기능
- 데이터 fetching 및 캐싱: Tanstack Query 는 데이터를 자동으로 캐싱하여 동일한 요청을 반복적으로 하지 않도록 한다. 이는 네트워크 요청을 최소화하고 성능을 향상시킨다.
- 자동 갱신: 데이터를 stale(구식)로 간주하면 자동으로 최신 데이터를 가져온다. 이 기능을 통해 항상 최신 상태의 데이터를 유지할 수 있다.
- 배경에서 갱신: 사용자가 현재 페이지를 보고 있지 않아도 배경에서 데이터를 갱신할 수 있다.
- 간편한 리트라이: 네트워크 요청이 실패하면 자동으로 다시 시도한다. 이 기능은 일시적인 네트워크 문제를 처리하는 데 유용하다.
- 구성 가능한 Query: 다양한 설정 옵션을 통해 데이터 fetching, 캐싱, 갱신 등의 동작을 세부적으로 조정할 수 있다.
사용방법 - useQuery
- 프로젝트 생성
yarn create vite tanstack-query-app --template react
- 설치
yarn add @tanstack/react-query
- 적용할 범위(ex:전역)에 Provider를 이용하여 적용
App.jsx또는 main.jsx(index.jsx)에 세팅하는 것을 권장
// main.jsx
import ReactDOM from "react-dom/client";
import App from "./App.jsx";
import "./index.css";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
const queryClient = new QueryClient();
ReactDOM.createRoot(document.getElementById("root")).render(
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
);
useQuery의 개념
- useQuery는 데이터를 가져오기 위해 사용되는 Tanstack Query의 대표적인 훅이다. 쿼리 키와 비동기 함수(패칭 함수)를 인자로 받아 데이터를 가져오고, 로딩 상태, 오류 상태, 그리고 데이터를 반환한다.
로딩 상태, 오류 상태 등을 자동으로 반환하기 때문에 redux-thunk에서 처럼 일일히 모든 상태를 직접 세팅할 필요가 없다.
- 이 훅을 통해 서버에서 데이터를 가져오고, 가져온 데이터를 컴포넌트에서 쉽게 사용할 수 있다. useQuery는 캐싱, 자동 리패칭, 백그라운드 데이터 동기화 등의 기능을 제공한다.
useMutation의 개념
- useMutation은 데이터를 생성, 수정, 삭제하는 등의 작업에 사용되는 훅이다. CUD에 대한 비동기 작업을 쉽게 수행하고, 성공 또는 실패 시에 추가적인 작업을 실행할 수 있기 때문에 useQuery와 함께 가장 대표적인 TanStack Query hook 이라고 할 수 있다.
- 비동기 작업을 쉽게 처리한다는 말 안에는 작업이 완료된 후에 관련된 쿼리를 무효화하는 과정이 포함되는데 이 역시 TanStack Query의 핵심 개념이라고 할 수 있다. 최신 데이터를 유지하는 데에 필수적인 요소이다.
invalidateQueries의 개념
- invalidateQueries는 특정 쿼리를 무효화하여 데이터를 다시 패칭하게 하는 함수이다. 주로 useMutation과 함께 사용하여 데이터가 변경된 후 관련 쿼리를 다시 가져오도록 한다.
- 이를 통해 데이터가 항상 최신 상태로 유지될 수 있도록 도와준다. 예를 들어, 새로운 할 일을 추가한 후 기존의 할 일 목록을 다시 가져오도록 할 수 있다.
Query Cancellation
- Query Cancellation 이란 무엇이고, 언제 사용할까?
- 다운로드 UI가 있을 때, 또는 UX 저해시키는 불필요한 네트워크 요청을 제거하기 위해 사용된다.
- 대용량 fetching을 중간에 취소하거나 사용하지 않는 컴포넌트에서 fetching이 진행중이면 자동으로 취소시켜 불필요한 네트워크 비용을 줄일 수 있다.
- queryFn의 매개변수로 Abort Signal을 받을 수 있고, 이를 이용해서 Query 취소를 가능하게 한다.
- 사용방법
- QueryFunctionContext
queryFn은 매개변수로 QueryFunctionContext 이란 객체를 받는다.
export const getTodos = async (queryFnContext) => {
const { queryKey, pageParam, signal, meta } = queryFnContext;
// queryKey: 배열형태의 쿼리키
// pageParam: useInfiniteQuery 사용 시 getNextPageParam 실행 시 적용
// signal: AbortSignal 을 의미 (네트워크 요청을 중간에 중단시킬 수 있는 장치)
// meta: query에 대한 정보를 추가적으로 메모를 남길 수 있는 string 필드
const response = await axios.get("http://localhost:5000/todos", { signal });
return response.data;
};
useQuery({
queryKey: ["todos"],
queryFn: getTodos,
})
// example: <div onClick={(event) => {}}
- 페이지 컴포넌트 umount시 Query 취소
API 요청 시 기본설정은 컴포넌트가 unmount 되도 네트워크 요청은 중단되지 않는다.
GET 요청 시 abort signal이 옵션으로 들어간 경우에만 unmount 시 자동으로 네트워크 취소가 된다.
import axios from 'axios'
const query = useQuery({
queryKey: ['todos'],
queryFn: ({ signal }) =>
axios.get('/todos', {
// Pass the signal to `axios`
signal,
}),
})
- 수동으로 Query 취소
const query = useQuery({
queryKey: ['todos'],
queryFn: async ({ signal }) => {
const resp = await fetch('/todos', { signal })
return resp.json()
},
})
const queryClient = useQueryClient()
return (
<button
onClick={(e) => {
e.preventDefault()
queryClient.cancelQueries({ queryKey: ['todos'] })
}}
>
Cancel
</button>
)
- 사용시 주의사항
모든 GET 요청마다 Abort Signal을 심으면 좋을까?
불필요한 네트워크 요청을 최소화 한다는 명분으로 단순하게 모든 GET 요청마다 Abort Signal 을 심는 것은 작업 부하를 올리고 바람직하지 않다.
동영상 다운로드 같은 대용량 fetcing이 아닌 이상 대부분의 GET 요청은 빠르게 완료 및 캐싱처리되어 성능에 유의미한 영향을 끼치지 못한다.
대용량 fetching이 있는 경우 또한 Optimistic UI를 구현할 때 처럼 필요한 경우에만 적용하는 것을 권장한다.
'React' 카테고리의 다른 글
Tailwindcss에 원하는 color 추가하기 (0) | 2024.06.18 |
---|---|
리액트 개인과제 map 오류 (0) | 2024.05.14 |