[React] React Query

SOL·2023년 10월 27일
0

React

목록 보기
8/8
post-thumbnail

기존의 fetch를 사용한 네트워크 통신은 캐시가 되지않습니다. 네트워크 통신이 실패했을 때, 다시 재시도하는 기능도 없습니다. 이런 로직들은 개발자가 직접 작성해야 했으나 React Query 라이브러리의 도움을 받아 간편하게 해결할 수 있습니다.

React Query는 네트워크 통신이나 비동기적으로 상태를 관리, 서버의 데이터를 동기화 시켜주는 등 유용한 기능들을 제공합니다.



설치

npm i @tanstack/react-query
# or
yarn add @tanstack/react-query


기본 사용법

QueryClient를 초기화 시킨 후 Provider로 사용할 App을 감싸줍니다. 하위 컴포넌트에서는 커스텀 훅인 useQuery를 이용하여 네트워크 통신을 할 수 있습니다.

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

const queryClient = new QueryClient()

export default function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <Example />
    </QueryClientProvider>
  )
}

function Example() {
  const { isPending, error, data } = useQuery({
    queryKey: ['repoData'],
    queryFn: () =>
      fetch('https://api.github.com/repos/TanStack/query').then(
        (res) => res.json(),
      ),
  })

  if (isPending) return 'Loading...'

  if (error) return 'An error has occurred: ' + error.message

  return (
    <div>
      <h1>{data.name}</h1>
      <p>{data.description}</p>
      <strong>👀 {data.subscribers_count}</strong>{' '}
      <strong>{data.stargazers_count}</strong>{' '}
      <strong>🍴 {data.forks_count}</strong>
    </div>
  )
}


Query Keys

리액트 쿼리는 키에 의존해서 캐시를 관리합니다. 따라서 캐시를 잘 관리하려면 고유한 키를 잘 명시하고 분리하여 사용해야합니다. 키는 배열로 설정합니다.

세부적인 키 배열을 통해서 조건에 맞게 서로 다른 캐시를 사용할 수 있습니다.

// An individual todo
useQuery({ queryKey: ['todo', 5], ... })

// An individual todo in a "preview" format
useQuery({ queryKey: ['todo', 5, { preview: true }], ...})

// A list of todos that are "done"
useQuery({ queryKey: ['todos', { type: 'done' }], ... })

그러나 컴포넌트가 리렌더링 되거나 윈도우 창을 다시 포커스하게 되면, 캐시된 데이터를 사용하지 않고 네트워크 통신이 재발생하는 것을 볼 수 있습니다. 네트워크 통신으로 받아온 캐시된 데이터는 그 즉시 stale한 상태가 되기 때문입니다.

확인해보기 위하여 리액트 쿼리에서 제공하는 개발 툴을 설치하고 데이터의 상태를 자세히 관찰할 수 있습니다.



Devtools

리액트 쿼리는 개발 툴을 제공해줍니다. 다음과 같이 설치할 수 있습니다.

npm i @tanstack/react-query-devtools
# or
yarn add @tanstack/react-query-devtools

우리의 애플리케이션에는 다음과 같이 적용합니다.

import { ReactQueryDevtools } from '@tanstack/react-query-devtools'

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      {/* The rest of your application */}
      <ReactQueryDevtools initialIsOpen={true} />
    </QueryClientProvider>
  )
}

로컬에서 애플리케이션을 실행하면 다음과 같이 개발 툴이 실행됩니다.

stale에 활성화가 된 의미는 "이 데이터는 상태가 좀 오래되었다" 입니다.



Refetch

stale한 상태의 쿼리는 다음과 같은 상황들에 놓여질 때, 자동으로 백그라운드에서 refetch 됩니다.

  • 컴포넌트에서 쿼리를 다시 이용할 때
  • 윈도우 창이 다시 포커스됐을 때
  • 네트워크가 다시 연결되었을 때
  • 쿼리에 refetch interval이 설정되었을 때

이렇듯 예상하지 못한 refetch를 막기 위해서는 관련된 옵션들을 잘 사용해주어야 합니다.

  • refetchOnMount
  • refetchOnWindowFocus
  • refetchOnReconnect
  • refetchInterval

또는 StaleTime의 설정을 통해 refetch를 막을 수 있습니다.



StaleTime

빈번한 refetch를 방지하기위해 StaleTime을 길게 지정해 줄 수 있습니다. 쿼리의 3번째 인자로 옵션 객체를 넘겨주면 됩니다.

const { isPending, error, data } = useQuery({
    queryKey: ['repoData'],
    queryFn: () =>
      fetch('https://api.github.com/repos/TanStack/query').then(
        (res) => res.json(),
      ),
  	{
		staleTime: 5000
	}
  })

위의 쿼리는 5초 동안 fresh한 상태를 유지하다가 stale 상태로 넘어갑니다. fresh한 상태에서는 refetch 되지 않습니다.



CacheTime

만약 컴포넌트에서 useQuery 또는 useInfiniteQuery를 사용하지 않는 상태(inactive)가 5분 이상 지속된다면, 가비지컬렉터에 의해 캐시가 삭제됩니다. 좀 더 오래 유지하기 위해서는 CacheTime을 더 긴 시간으로 바꿔줄 수 있습니다.

하지만 캐시 시간을 너무 길게 가져가면 업데이트를 놓칠 수 있습니다. 이럴때는 invalidateQueries를 이용하여 해당하는 키의 쿼리를 수동으로 refetch할 수 있습니다.



Retry

쿼리의 네트워크 통신이 실패한다면, 3번의 재시도를 진행합니다. 각 시도마다 시간 간격의 차이가 있습니다. 이런 간격도 retry, retryDelay 옵션들을 통해서 설정할 수 있습니다.


참고
Tanstack Query 공식 홈페이지

profile
개발 개념 정리

0개의 댓글

관련 채용 정보