React Query 1

한상욱·2024년 3월 27일

React Query

목록 보기
1/2

서버 데이터 상태를 다루는 라이브러리인 React Query에 대해 알아보자. 본인도 실제로 업무에 사용해보면서 전역 상태 의존도를 낮춰주기 때문에 매우 유용하게 사용하는 라이브러리이다.

Motivation

기존에 프레임워크는 서버에서 내려온 데이터를 다루기가 힘들었다. 왜냐하면 서버의 상태는 반드시 달라지기 때문이다. 그 이유는 다음과 같다.

  • 여러 사람들이 접근해서 데이터 수시로 업데이트
  • 데이터 패칭이나 업데이트하면서 비동기로 동작
  • 내가 주의하지 않으면 오래된 데이터가 되어버림

이러한 이유 때문에 아래와 같은 요구들이 생겨났다.

  • 캐싱되면 좋겠어
  • 오래된 데이터 알아서 업데이트 해줘
  • 페이지네이션이랑 레이지 로딩이 되었으면 좋겠어
  • 메모리와 가비지 콜렉션도 관리하면 좋겠어
  • 쿼리 메모이제이션이 되었으면 좋겠어

근데 이거 직접 구현하려면 개빡세다. 그래서 React Query는 이것들을 그냥 제공해준다.

Query Basics

쿼리는 유니크한 키와 데이터가 종속적으로 묶여 있다. 쿼리는 Promise로 동작한다. 서버에서 데이터를 가져올 때 쓴다.

쿼리를 사용하기 위해서 두가지가 필요한다.

  • 유니크한 키
  • 데이터를 리턴하거나 에러를 뱉을 수 있는 함수

데이터를 가져오는 행위는 useQuery를 사용한다.

const Vendor = () => {
	const { data, error } = useQuery({
      queryKey: ['vendor'], 
      queryFn: getVendor
    });
}

유니크 키는 리패칭, 캐싱, 현재 쿼리를 다른 쿼리와 공유할 때 사용한다. 리턴하는 값은 여기를 참고해라.

핵심 내용은 데이터를 패칭해오기 전, 패칭하는 도중, 패칭 완료 이후, 에러가 나타난 경우 등 데이터를 가져오는 각 과정마다 개발자가 알 수 있도록 여러가지 값을 제공한다는 것이다.

Query Keys

쿼리 키는 쿼리 캐싱을 위해 필요한 요소이다. 배열로 저정한다.

useQuery({ queryKey: ['vendor'], })
useQuery({ queryKey: ['vendor', 1 ]})
useQuery({ queryKey: ['vendor', 1, { manager: 12 } ]})

한 가지 조심해야 되는 것은 쿼리 키 배열 순서 바꿔도 같은 쿼리로 본다는 것이다.

파라미터가 필요한 쿼리는 아래와 같이 짜면 된다. 그러면 staleTime에 맞게 필요한 데이터를 알아서 가져올 것이다.

const Vendor = ({ vendorId }: VendorProps) => {
  const result = useQuery({
    queryKey: ['vendor', vendorId],
    queryFn: () => getVendor(vendorId),
  })
}

Query Functions

쿼리 함수는 Promise를 반환한다. Promise는 data를 반환하거나 error를 던진다.

fetch 기반의 라이브러리를 쓰면 성공하지 못한 HTTP 콜에 대한 것을 알아서 처리해야 된다는 것이다.

useQuery({
  queryKey: ['todos', todoId],
  queryFn: async () => {
    const response = await fetch(`vendor/${vendorId}`)
    if (!response.ok) {
      throw new Error('Network response was not ok')
    }
    return response.json()
  },
})

Query Options

쿼리 키와 쿼리 함수를 관리하는 가장 좋은 방법은 queryOptions를 사용하는 것이다. 타입스크립트 쓸 때 엄청 이점이 있다. 넘겨주는 값에 대한 타입 추론과 체크를 스스로 해준다.

import { queryOptions } from '@tanstack/react-query'

function groupOptions(vendorId: number) {
  return queryOptions({
    queryKey: ['vendor', vendorId],
    queryFn: () => getVendor(vendorId),
    staleTime: 5 * 1000,
  })
}

...

useQuery(groupOptions(1))

Network Mode

네트워크 커넥션이 없을 때 쿼리와 뮤테이션이 동작하는 방법을 세 가지로 구분한다. 경우에 따라 사용하면 된다. 기본값은 online이다.

online

online에서는 네트워크가 연결되어 있지 않으면 쿼리와 뮤테이션을 실행하지 않는다. 기본값이다. 네트워크 연결이 없는 상태로 패치가 쿼리에 의해 처음으로 실행되면 state(pending, error, success) 항상 유지된다. 하지만 fetchStatus에서 현재 어떤 과정이 진행되는지 알 수 있다.

쿼리를 실행했다 network가 끊긴다면 자동으로 재시도하는 메커니즘도 가지고 있다. 쿼리를 멈추고 다시 네트워크 커넥션을 실행하는 것이다.

always

always에서는 online 상태와 offline 상태 모두 무시하고 데이터를 패칭한다는 것이다. 이것은 네트워크 활성화가 되지 않은 환경에서 쿼리로 데이터를 패칭할 때 사용한다.

offlineFirst

offlineFirst에서는 데이터 패칭 시 cache나 storage를 먼저 방문하니까 성공을 한다. 하지만 캐시 미스가 난다면 네트워크 요청은 실행 되었다가 실패할 것이고 이 경우 online 상태에 중지 및 실행 과정과 같이 쿼리 동작이 일어날 것이다.

profile
그냥 뛰는 사람

0개의 댓글