서버 데이터 상태를 다루는 라이브러리인 React Query에 대해 알아보자. 본인도 실제로 업무에 사용해보면서 전역 상태 의존도를 낮춰주기 때문에 매우 유용하게 사용하는 라이브러리이다.
기존에 프레임워크는 서버에서 내려온 데이터를 다루기가 힘들었다. 왜냐하면 서버의 상태는 반드시 달라지기 때문이다. 그 이유는 다음과 같다.
이러한 이유 때문에 아래와 같은 요구들이 생겨났다.
근데 이거 직접 구현하려면 개빡세다. 그래서 React Query는 이것들을 그냥 제공해준다.
쿼리는 유니크한 키와 데이터가 종속적으로 묶여 있다. 쿼리는 Promise로 동작한다. 서버에서 데이터를 가져올 때 쓴다.
쿼리를 사용하기 위해서 두가지가 필요한다.
데이터를 가져오는 행위는 useQuery를 사용한다.
const Vendor = () => {
const { data, error } = useQuery({
queryKey: ['vendor'],
queryFn: getVendor
});
}
유니크 키는 리패칭, 캐싱, 현재 쿼리를 다른 쿼리와 공유할 때 사용한다. 리턴하는 값은 여기를 참고해라.
핵심 내용은 데이터를 패칭해오기 전, 패칭하는 도중, 패칭 완료 이후, 에러가 나타난 경우 등 데이터를 가져오는 각 과정마다 개발자가 알 수 있도록 여러가지 값을 제공한다는 것이다.
쿼리 키는 쿼리 캐싱을 위해 필요한 요소이다. 배열로 저정한다.
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),
})
}
쿼리 함수는 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()
},
})
쿼리 키와 쿼리 함수를 관리하는 가장 좋은 방법은 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))
네트워크 커넥션이 없을 때 쿼리와 뮤테이션이 동작하는 방법을 세 가지로 구분한다. 경우에 따라 사용하면 된다. 기본값은 online이다.
online에서는 네트워크가 연결되어 있지 않으면 쿼리와 뮤테이션을 실행하지 않는다. 기본값이다. 네트워크 연결이 없는 상태로 패치가 쿼리에 의해 처음으로 실행되면 state(pending, error, success) 항상 유지된다. 하지만 fetchStatus에서 현재 어떤 과정이 진행되는지 알 수 있다.
쿼리를 실행했다 network가 끊긴다면 자동으로 재시도하는 메커니즘도 가지고 있다. 쿼리를 멈추고 다시 네트워크 커넥션을 실행하는 것이다.
always에서는 online 상태와 offline 상태 모두 무시하고 데이터를 패칭한다는 것이다. 이것은 네트워크 활성화가 되지 않은 환경에서 쿼리로 데이터를 패칭할 때 사용한다.
offlineFirst에서는 데이터 패칭 시 cache나 storage를 먼저 방문하니까 성공을 한다. 하지만 캐시 미스가 난다면 네트워크 요청은 실행 되었다가 실패할 것이고 이 경우 online 상태에 중지 및 실행 과정과 같이 쿼리 동작이 일어날 것이다.