TanStack Query(React Query) API 요청 줄이기

dohun2·2023년 12월 11일
post-thumbnail

무언가 이상하다!! TanStack Query 왜 쓰지? 🤯

현재 일기를 작성하고 친구들의 최근 일기를 볼 수 있는 프로젝트를 진행하고 있다.
이번 프로젝트는 기획때부터 TanStack Query를 사용해야겠다고 생각했는데
새로운 일기가 작성되거나 삭제되는 것이 아니면 나의 일기목록 같은 데이터는 다시 받아올 필요가 없어서 TanStack Query가 제공하는 캐싱을 이용하면 불필요한 API 요청을 줄일 수 있을 것이라 생각했기 때문이다.

하지만 프로젝트 마지막 주에 들어선 지금 홈페이지에서는 초기 도입 의도와 다르게 매 렌더마다 같은 요청 30번이 반복적으로 가고있다는 것을 발견했다.

요청사진

이상하다.. TanStack Query를 쓰면 똑같은 값을 가져오는 요청을 보내면 알아서 캐싱된 데이터를 가져다가 써야하는거 아니야?

하지만 그것은 TanStack Query의 stale과 fresh 개념도 모르고 무턱대고 사용한 나의 착각이었다!

Stale과 Fresh

TanStack Query는 쿼리를 stale(탁한 === 신선하지 않은)과 fresh(신선한)로 구분해 관리한다.
항상 신선한 데이터를 유지하면 될 것 같은데 stale이 존재하는 이유는 뭘까?
그 이유는 새로운 데이터를 받아오기 전에 stale 데이터를 사용해 화면을 출력되는게 더 좋은 사용자 경험을 주기 때문이라고 한다.

TanStack Query Devtools

https://tanstack.com/query/v4/docs/react/devtools
dev tools를 사용하면 현재 쿼리가 어떤 상태인지 쉽게 확인이 가능하다.

상태

  • Fresh : 신선한 상태로 요청을 다시 보내지 않음
  • Fetching : 데이터를 가지고 오고 있는 상태
  • Paused : 네트워크 등의 문제로 멈춰있는 상태
  • Inactive : 쿼리가 있는 컴포넌트가 언마운트 상태인 데이터로 cacheTime의 기본값에 따라 5분 간 사용되지 않는다면 gc(가비지콜렉터)에 의해 삭제됨

데브툴즈현재 홈페이지에서는 프로필, 잔디, 감정통계, 반응목록을 받아오고 모든 쿼리가 stale 상태이다.
기본적으로 stale 상태의 쿼리들은 아래의 상황에 새로운 데이터를 받아오게 된다.

  • 쿼리가 새롭게 마운트 되었을 때
  • 해당 창이 다시 포커스 되었을 때(탭 이동)
  • 네트워크가 다시 연결되었을 때
  • 쿼리에 interval 옵션으로 주기적으로 실행될 때

위의 상황에서 지금 나의 상황은 쿼리가 새롭게 마운트 될 때마다 데이터를 받아오고 있는 상황이다.
그렇다면 다시 받아올 데이터에 대해 요청을 보내지 않는 방법은 무엇일까?
아주 간단하게도 쿼리를 fresh 상태로 만드는 것이다!!

Fresh로 변경하기

홈페이지홈페이지의 구성을 보면 프로필, 잔디, 감정통계, 일기목록으로 구분되어 있다.
어떤 쿼리를 fresh로 변경할 수 있을까?
프로필, 잔디, 감정통계, 일기목록의 데이터가 변경되려면 전부 로그인한 사용자가 어떤 행동(일기작성, 삭제, 수정, 프로필 변경)을 해야한다. 그렇다면 어떤 행동을 하지 않으면 데이터가 변경될 이유가 없다는 뜻이고 이것은 다 fresh로 사용할 수 있다는 뜻이다!
최신 정보를 유지해야하는 일기의 공감부분을 제외하고 fresh로 바꿔보자!

fresh로 변경할 쿼리를 정했으면 이제 해당 쿼리에 staleTime 옵션을 줘서 얼마나 fresh로 유지할 것 인지 설정해주면 된다. (staleTime의 기본값이 0이어서 모든 쿼리는 바로 stale 상태가 된다.)
ms 기준이기때문에 1000 = 1초이고 Infinity를 사용해서 영원히 fresh 상태를 유지할 수 있다.

// 프로필 데이터를 받아오는 쿼리  
const {
    data: profileData,
    isError,
    isLoading,
  } = useQuery({
    queryKey: ['profileData', userId],
    queryFn: () => getCurrentUser(userId ? +userId : 0),
    staleTime: Infinity,
  });

해당 코드처럼 staleTime을 Infinity로 주고 프로필, 잔디, 감정통계, 일기목록에 적용하였고 결과는 다음과 같았다.

개선 결과 👍

개선결과해당 쿼리들이 Fresh로 변경되었고 홈페이지에서의 요청이 30번 > 23번으로 감소한 것을 확인할 수 있었다.
결국 최신 데이터를 유지해야하는 공감을 받아오는 쿼리가 일기의 수만큼 요청을 보내야해서 극적으로 개선되지는 않았지만 그래도 불필요한 요청을 줄였다는 것에 의미가 있었다!

참고자료

TanStack Query 공식문서

0개의 댓글