[React Query / TanStack Query] 쿼리 생성 및 로딩 / 에러 상태

변진상·2025년 1월 8일
0

학습 기록

목록 보기
31/31

최근 회사에서 새로 합류하게 된 스쿼드에서 사용하고 있는 스택 중 TanStack Query를 학습하기 위한 기록입니다.

  • react query는 react app의 서버 상태를 관리하기 위한 라이브러리이다.

client state vs. server state

  • client state: 브라우저 세션과 관계된 모든 정보(ex. 유저가 선택한 언어, 테마)
    - 서버와는 관계가 없고 단순히 사용자의 상태를 추적하는 것이다.
  • server state: 서버에 저장된 클라이언트에 표시하기 위한 정보(ex. db에 저장한 블로그 포스팅 데이터)
    - 사용자에게 게시물을 표시하기 위해 클라이언트에 이 데이터가 있어야하지만, 데이터는 여러 클라이언트에게 표시할 수 있게 서버에 저장된다.

  • React Query는 클라이언트에서 서버 데이터 캐시를 관리한다. 리액트 코드에서 데이터가 필요할 때, fetch나 axios를 사용해 서버로 바로 접근하는 것이 아닌, React Query 캐시를 요청한다.

  • React Query의 역할은 리액트 쿼리 클라이언트를 어떻게 구성했냐에 따라 해당 캐시의 데이터를 유지관리하는 것이다.

  • 캐시의 업데이트하는 시기를 설정하는 것은 사용자의 몫이다.
    - imperatively(명령적): 쿼리 클라이언트에 데이터를 무효화(invalidate)하고 캐시에 교체할 새 데이터를 서버에서 가져오게 지시한다.
    - declaratively(선언적): 리페치(refatch)를 트리거하는 조건을 구성. configure how & when to trigger a re-fetch.

  • 서버 상태 관리에 도움되는 도구를 제공한다.
    - 로딩과 에러 상태를 유지해준다.

    • pagination / infinite scroll를 위한 데이터를 조각으로 가져오는 도구를 제공한다.
    • 사용자가 데이터를 필요로 하는 시점을 예상하여 prefatch가 가능하다.
    • 서버에서 데이터 변이(mutation)나 업데이트를 관리할 수 있다.
    • 쿼리는 stale time 동안 키로 식별되기 때문에, 페이지의 여러 구성 요소가 동일한 데이터를 요청하는 경우 쿼리를 한 번에 보낼 수 있다. 기존 쿼리가 나가는 동안 다른 구성요소가 같은 데이터를 요청하는 경우, 중복 요청을 제거할 수 있다.
    • 서버에서 오류가 발생하는 경우 재 요청을 보내거나 핸들링 할 수 있는 콜백을 전달할 수 있다.
  • 용어 설명
    - query client: 쿼리와 캐시를 관리하는 클라이언트. 캐시와 툴을 포함한다.

    • query provider: 자식 컴포넌트에 캐시와 클라이언트 설정을 제공, 쿼리 클라이언트 prop으로 사용한다.
    • useQuery hook: 서버에서 데이터를 가져오는 훅

useQuery

const { data } = useQuery({
    queryKey: ["posts"],
    queryFn: fetchPosts,
  });
  // 이렇게만 하면 에러 발생 왜냐면 비동기 함수라 data가 undefined이기 때문에 에러 발생
	if(!data){
      return <div>undefined data</div>
    }
	// 이렇게 작성해 두면 데이터가 없는 동안은 div를 반환하다가 data가 falsy하지 않으면, 다시 렌더링한다.

isFetching, isLoading의 차이

isLoading

  • isLoading은 캐시된 데이터가 없는 최초의 async query 요청을 해 데이터를 가져오는 경우 isLoading은 true가 된다.
  • 쿼리가 성공적으로 데이터를 가져오거나 에러를 발생시키면 false가 된다.
  • 캐시되어 있는 경우는 isLoading이 true.

isFetching

  • 쿼리가 데이터를 가져오고 있는 경우는 항상 true이다.
  • 백드라운드 재요청(캐시에 데이터가 있는 경우에도 백그라운드에서 새 데이터를 가져오는 것) 동안 isFetching은 true가 될 수 있습니다.

isLoading은 isFetching의 하위집합으로 isLoading이 true이면 항상 isFetching이 true이다.

isError, error

  • 디폴트하게 react query는 요청에 에러가 발생 시, 세번의 요청을 보내고 최종적으로 isError를 결정한다.
  • isError 프로퍼티를 이용해 에러가 발생했는지 여부를 파악할 수 있고, error 프로퍼로 그 에러의 내용을 알 수 있다.

// replace with useQuery
  const { data, isLoading, isError, error } = useQuery({
    queryKey: ["posts"],
    queryFn: fetchPosts,
  });
  // 이렇게만 하면 에러 발생 왜냐면 비동기 함수라 data가 undefined이기 때문에 에러 발생

  if (isLoading) {
    return <h2>로딩중이지롱!</h2>;
  }

  if (isError) {
    return (
      <>
        <h2>에러 발생!!</h2>
        <p>{error.toString()}</p>
      </>
    );
  }

stale의 의미

  • 데이터가 expired 된 것을 의미한다. 그리고 refetch되는 것을 기다리는 것이다.

    stale time

  • 캐시에 아직 존재하지만 재검증(revalidate)이 필요함을 의미한다.

  • staleTime -> max age

  • 기본적으로 리액트 쿼리의 default stale time은 0ms이다. 이게 stale한 데이터가 없이 항상 fresh한 데이터를 유지하는 의미로 stale time을 생각하면 좋다.

  • stale time 동안은 fresh하다.

    gcTime

  • 데이터를 캐시에 유지할 시간을 결정한다.

  • 데이터가 구독되지 않으면 지정된 시간 후에 캐시에서 삭제된다. 즉, 데이터와 연관된 활성 useQuery가 없고 화면에 데이터가 표시되지 않는 순간부터 시간이 측정된다.

    staleTime vs gcTime

profile
자신을 개발하는 개발자!

0개의 댓글