본문 바로가기
배움 기록/ETC

React-Query 를 사용하는 이유(+ 개념, 컨셉, SSR Hydration, Redux ...)

by dygreen 2023. 10. 9.

📌 React Query 를 사용하는 이유 ?

" 비동기 데이터 관리를 위해 사용한다. "

공식 홈페이지

여기서 비동기 데이터Server state (= 서버의 상태) 를 의미한다.

즉, API 로 클라이언트에게 제공될 수 있는 서버의 데이터API 로 추가/수정/삭제가 될 수 있는 서버의 데이터를 의미한다.

 

나의 경우 Redux 를 사용하여 비동기 데이터를 관리하곤 했다.

그러나 Redux 는 API 통신 및 비동기 데이터 관리를 위한 라이브러리가 아니기 때문에, (*Redux 는 전역 상태 관리를 위한 라이브러리)

API 요청을 통해 받아온 데이터를 관리하는 코드나 API 상태를 관리하는 코드 등을 직접 작성해야 했다.

 

반면 React Query 는 서버의 상태를 불러오고, 캐싱하며, 지속적으로 동기화하고 업데이트하는 작업을 도와주는 라이브러리이다.

따라서 API 요청 및 상태 관리를 위한 규격화된 방식을 제공한다. (ex. isLoading, error, isRefetchError ...)

이러한 기능들은 (Redux 를 사용하며 직접 코드를 작성해야 하는 것에 비해) 리소스를 경감시켜 중요한 비즈니스 로직에 집중할 수 있게끔 도와준다.

 

 

 

📌 React Query 주요 개념

• StaleTime

staleTime데이터가 신선한 상태로 남아 있는 시간을 말한다.

기본적으로 모든 쿼리의 staleTime0초로 설정되어 있다.

즉, 서버에서 데이터를 가지고 오자마자 신선하지 않다고 간주하는 것이다.

 

staleTime서버에서 데이터를 가져온 시점부터 시작한다.

설정된 시간이 지나면 해당 데이터는 stale(= 신선하지 않은) 데이터로 간주되며 새로운 업데이트가 필요하게 된다.

 

❓staleTime: Infinity 란
: Infinity 단어 뜻대로 데이터가 계속 신선한 데이터라고 설정하는 것을 의미한다.
해당 데이터는 자동으로 refetch 되지 않기 때문에, 데이터의 변경이 자주 일어나지 않는 경우 설정하면 좋다.
❓다른 창에 있다가 브라우저를 다시 focus 했을 때, 기존 staleTime 을 리셋하고 다시 카운트 하는 것일까
: staleTime 은 서버에서 데이터를 가져온 시점부터 시작되며, 브라우저의 focus 상태와는 관계 없이 독립적으로 카운트된다.
즉, 기존 브라우저에 다시 focus 했을 때 staleTime 은 리셋되지 않는다.
그러나! React Query 는 브라우저의 focus 상태에 따라 자동으로 데이터를 리프레시 하는 기능(= refetchOnWindowFocus)을 true 로 설정해 놓았다.
이 경우 브라우저에 다시 focus 하면 해당 쿼리의 데이터는 자동으로 refetch 되기 때문에 staleTime 이 리셋되는 것처럼 보일 수 있는데, 이것은 staleTime 이 리셋되는 것과는 별개의 동작이다.

 

• CacheTime

cacheTime데이터가 얼마나 오랫동안 메모리에 저장될 것인지를 말한다.

기본적으로 모든 쿼리의 cacheTime 은 5분으로 설정되어 있다.

 

cacheTime쿼리를 사용하는 모든 컴포넌트가 unmount 된 후 카운트가 시작된다.

설정된 시간이 지나면 해당 데이터는 가비지 컬렉터로 수집되어 사라진다.

 

• invalidateQueries()

invalidateQueries 는 queryClient 의 메서드 중 하나이다. 캐시 안의 모든 쿼리를 무효화 한다.

const queryClient = useQueryClient();

queryClient.invalidateQueries();
queryClient.invalidateQueries({ queryKey : ['list'] });

이 기능은 자주 변경되는 데이터가 없는 페이지에서 staleTimeInfinity 로 설정하고,

POST/PUT/DELETE 등의 이벤트가 발생했을 경우에만 쿼리 무효화를 통해 새로운 데이터를 갱신하여

불필요한 HTTP Request 요청을 줄이고 효과적으로 서버 데이터를 관리하기 위해 사용할 수 있다.

 

 

 

📌 React Query 에서 SSR 구현하기 (feat. hydration)

React Query 에서 SSR 을 구현하는 2가지 방식은 다음과 같다.

1. initialData : getServerSideProps 같은 SSR 메서드로 불러온 응답을 React Query 의 initialData 에 넣어주는 방식

2. hydration : SSR 내에서 prefetch 를 통해 쿼리를 불러온 뒤, queryClient 에서 dehydrate 한 상태값으로 페이지에 전달하는 방식

 

 

이 중 2번째 방식에 대해서 자세히 정리해보자면...

처음 1회는 SSR 메서드에서 prefetch 를 통해 데이터를 요청함 → 해당 캐시를 dehydrate → 클라이언트에 그것을 rehydrate

// pages/_app.tsx

import { QueryClient, QueryClientProvider, Hydrate } from '@tanstack/react-query';

export default function App({ Component, pageProps }: AppProps) {
  const queryClient = new QueryClient();

  return (
    <QueryClientProvider client={queryClient}>
      <Hydrate state={pageProps.dehydratedProps}>
        <Component {...pageProps} />
        <ReactQueryDevtools />
      </Hydrate>
    </QueryClientProvider>
  );
}
export default function Home() {
  const { data } = useQuery(['todos'], queryFn, { staleTime: 10 * 1000 });

  return (
    <div>
      {data?.map(({ title, completed }) => (
        <p key={title}>
          <strong>{title}</strong>
          {completed && <span>완료</span>}
        </p>
      ))}
    </div>
  );
}

export const getServerSideProps: GetServerSideProps = async () => {
  const queryClient = new QueryClient();
  await queryClient.prefetchQuery(['todos'], queryFn);
  return {
    props: {
      dehydratedProps: dehydrate(queryClient),
      hi: 'hello',
    },
  };
};

 

SSR 에서 hydrate 작업이 필요한 이유 ?

일단 hydrate'수분을 유지시키다' 라는 뜻으로,

정적인(= 메마른) HTML 을 동적인(= 수분을 보충) 상태로 변화시키는 과정으로 보면 된다.

 

[자세히]

SSR 은 서버에서 HTML 을 생성하고 클라이언트로 보내주게 된다. 그런데 이렇게 생성된 HTML 에는 데이터가 이미 포함되어 있지만,
클라이언트의 리액트 애플리케이션은 이러한 초기 상태에 대해 알지 못한다.

따라서 여기서 hydrate 작업으로 서버에서 렌더링된 결과물 클라이언트의 리액트 애플리케이션 상태 동기화하는 것이 필요하다.

 

➡️ hydrate 는 SSR 에서 생성된 정적인 HTML 에 클라이언트 측 JS 를 연결하여 동적으로 만드는 과정을 의미한다.

➡️ dehydrate 는 Server Side 에서 초기 상태를 추출하여 클라이언트에게 전달하는 과정, (re)hydrate 는 그 상태를 Client Side 애플리케이션에 복원하는 과정을 의미한다.

 

 

 

 

 

출처 :
https://tanstack.com/query/v3/
https://tech.kakaopay.com/post/react-query-1/
https://simsimjae.tistory.com/389
https://tesseractjh.tistory.com/269

 

728x90

댓글