이번에 온판 온보딩 프로젝트를 진행하면서 react-query를 처음 사용해 보게 됐다 .. 🐥
앞으로 진행할 모든 프로젝트에서 공통으로 사용되는 기술 스택인것 같아 제대로 이해할 겸 한 번 정리해 보려고 한다😗
React Query는 React Application에서 서버 상태 가져오기, 캐싱, 동기화 및 업데이트 작업을 쉽게 수행할 수 있도록 도와주는 라이브러리이다.
이미 한 줄 요약에서 설명했듯이, react-query는 fetching, caching, 서버 데이터와의 동기화 등을 지원해주고, 무엇보다 클라이언트와 서버 데이터를 온전하게 분리 할 수 있도록 도와준다.
데이터를 가져오거나 업데이트하는 로직을 store 내부에 구현하는 경우가 많은데, 이러한 경우에 클라이언트 상태와 서버 상태가 공존하기 때문에 로직이 복잡해질 수 밖에 없다 ( 과거의 나.. 😵 )
이러한 문제점과 더불어 비동기 데이터를 다루면서 마주했던 여러 문제점들을 react-query의 여러 기능들을 통해 편리하게 해결할 수가 있다!
( Quick Start는 공식 문서를 참고해주세요 😉 )
React-Query는 캐싱을 통해 불필요한 API 호출을 방지하여 서버에 대한 부하를 줄일 수 있다.
react-query에서 캐싱은 어떤 방식으로 진행될까? 🤔
캐싱 사이클에 대해 알아보기 전에, 먼저 react-query는 다음과 같은 기본 옵션들을 제공한다.
refetchOnMount,
refetchOnWindowFocus,
refetchOnReconnect,
refetchInterval,
staleTime,
cacheTime,
react-query는 기본적으로 캐싱된 데이터를 stale한 상태로 여긴다.
stale이란 신선하지 않은, 오래된 낡은 데이터를 의미한다. 데이터가 stale하면 신선하지 않은 상태이기 때문에, 업데이트가 필요한 것이다.
따라서 react-query는 아래 옵션들을 기본적으로 제공하고, 설정에 따라 다음과 같은 시점에 해당 쿼리를 refech한다.
refetch 옵션들과 함께 staleTime과 cacheTime 또한 설정할 수 있다. staleTime의 기본값은 0초, cacheTime의 기본값은 5분이다.
staleTime
: 데이터가 fresh에서 stale한 상태로 변경되는 데 걸리는 시간
cacheTime ( react-query v5에서는 gcTime )
: 데이터가 inactive 상태일때 캐싱된 상태로 남아있는 시간
이제 react-query의 기본 옵션들에 대해 이해했으니 캐싱 사이클에 대해 알아볼 수 있다! 😎
react-query의 캐싱 라이프 사이클은 다음과 같다.
- 쿼리 인스턴스가
mount
되고,- 네트워크에서 데이터를 fetch하고 해당 queryKey로
caching
한다.- 이 데이터는
fresh
상태에서 staleTime 이후에stale
상태로 변경된다.- 해당 쿼리 인스턴스는
unmount
되고,- 캐시는 cacheTime(gcTime)만큼 유지되다가
가비지 콜렉터 (gc)
로 수집된다.
이러한 과정들로 쿼리 응답 데이터가 캐시되고,
cacheTime(gcTime)이 지나기 전에, 쿼리 인스턴스가 fresh한 상태라면 새로 mount되었을 때 캐시 데이터를 보여주게 되는 것이다!
react-query는 가장 기본적으로 useQuery와 useMutation Hook을 제공한다.
useQuery는 서버로부터 데이터를 조회해올 때 사용되는 Hook이다 (GET)
const { data } = useQuery(
queryKey, // 응답 데이터를 캐시할 때 사용할 Unique Key (required)
fetchFn, // Promise를 Return 하는 함수 (required)
options, // Option 객체 (optional)
);
enabled
옵션을 사용할 경우에는 비동기 함수인 useQuery를 동기적으로 사용할 수 있다.select
옵션을 사용할 경우, 반환값에서 필요한 필드만을 선택하여 효율적으로 활용할 수 있다.const { data } = useQuery(
['queryKey', id],
() => fetchById(id),
{
enabled: !!id, // id가 존재할 때만 쿼리 요청
select: data => data.title // 필요한 필드만을 선택
}
);
status
, isLoading
, isFetching
, isSuccess
, isError
등 세분화된 결과값을 통해 추가적인 상태를 선언하지 않고, 간결하게 조건을 적용하여 사용할 수 있다.useMutation은 서버의 상태를 변경시킬 때 사용되는 Hook이다 (PUT, UPDATE, DELETE)
const { mutate } = useMutation(
mutationFn, // Promise를 Return 하는 함수 (required)
options, // Option 객체 (optional)
);
이번 온보딩 프로젝트에서 react-query를 처음 사용해보았는데, 기존 boiler-plate를 기반으로 api.ts에 비동기 함수를 구현하고, query.ts에 react-query를 사용한 훅을 구현한 후, 여러 옵션들을 활용해서 아주 간결하게 데이터 fetch 로직을 구현할 수 있었다.
아직까지는 기초적인 기능들 위주로 활용해본 것 같은데, 앞으로 더 다양한 프로젝트에서 react-query를 사용하면서 더 다양한 hook들과 option들을 활용해보기 위해 노력해야겠다~ 😉
https://tanstack.com/query/v4/docs/react/overview
https://github.com/ssi02014/react-query-tutorial
https://velog.io/@kandy1002/React-Query-%ED%91%B9-%EC%B0%8D%EC%96%B4%EB%A8%B9%EA%B8%B0
https://tech.kakaopay.com/post/react-query-1/