bgyoonsContact

queryClient

FrontEnd | | 5분 읽기

서버 컴포넌트의 좋은 점은 중첩될 수 있고 React 트리의 여러 레벨에 존재할 수 있기 때문에 애플리케이션의 최상단이 아닌 실제로 사용되는 위치에 더 가깝게 데이터를 프리페치할 수 있다는 점입니다.

프리패치 하는 곳에서 쿼리 클라이언트 선언권장되지만(왜?)

모든 서버 컴포넌트에서 재사용되는 단일 컴포넌트를 만들 수도 있습니다 → queryClient를 재사용하므로 중복된 인스턴스 생성을 방지

cache()는 Next.js의 서버 컴포넌트 내에서 요청(Request) 범위로 제한된 캐싱 메커니즘입니다.

새 요청이 들어오면 cache() 내부의 함수가 다시 실행되어 새로운 인스턴스를 생성합니다.

데이터 요청이 중복될 가능성이 있거나 효율적인 메모리 관리가 중요한 경우, cache()를 사용하여 queryClient를 공유하는 것이 좋습니다.

반면, 최소 직렬화 데이터가 필요한 경우나, 데이터 간의 의존성이 거의 없는 경우에는 독립적인 queryClient를 생성하는 방식이 더 적합합니다.

단점은 dehydrate(getQueryClient())를 호출할 때마다 이전에 이미 직렬화된 적이 있고 현재 서버 컴포넌트와 관련이 없는 쿼리를 포함하여 전체 쿼리 클라이언트를 직렬화하므로 불필요한 오버헤드가 발생한다는 것입니다. → 근데 지금은 하나만 쓰니까 상관 없음


cache란

  • 서버 컴포넌트에서만 사용
  • 캐싱 단위가 서버 요청
    • HydrationBoundary로 감싸진 범위가 요청 범위
    • 같은 HTTP 요청 내에서는 같은 queryClient 인스턴스
    • cache를 호출할 때마다 새 인스턴스가 생성됩니다. 새 요청이 들어오면 내부 함수가 다시 실행되어 새로운 queryClient 인스턴스를 생성 → 요청 범위 내에서 queryClient 재사용 가능 (데이터 요청이 중복되는 경우 캐싱하는게 좋음)

queryClient는 데이터를 미리 가져오고 관리함 → cache()로 생성된 queryClient는 같은 범위에서 한 번만 생성됨 → 캐싱된 결과를 재사용 할 수 있게 해줌

HTTP 요청 범위인지, 서버 컴포넌트가 요청 범위인지?

React Query Provider: 클라이언트에서 데이터를 캐싱하고 관리합니다. 서버에서 직렬화된(dehydrated) 데이터를 받아 초기 상태로 설정합니다.

cache()의 queryClient: 서버에서만 존재하며, 데이터를 prefetch하고 직렬화(dehydrate)하여 클라이언트로 전달하는 데 사용됩니다.

  1. 서버에서 cache()를 사용해 queryClient를 생성하고 데이터를 prefetch합니다.
  2. dehydrate()를 통해 데이터를 직렬화하여 HTML과 함께 클라이언트로 전달합니다.
  3. 클라이언트의 React Query Provider가 이 직렬화된 데이터를 초기 상태로 사용하여 새로운 QueryClient를 생성합니다.

따라서, 서버의 queryClient는 클라이언트의 React Query Provider와 직접적으로 덮어쓰는 관계가 아닙니다.

  • 서버 측 queryClient:
    • 서버에서 queryClient를 생성하면 해당 요청(Request) 범위 내에서만 유효하며, 새 요청이 들어오면 새로 생성됩니다.
    • 이 인스턴스는 서버에서 데이터 패칭 및 캐싱을 관리하고, 클라이언트로 전달되는 초기 상태로 사용될 수 있습니다.
  • 클라이언트 측 React Query Provider:
    • 클라이언트에서 React Query Provider를 사용하면 클라이언트의 상태를 관리합니다. 일반적으로 클라이언트 애플리케이션에서 한 번 생성되고, 애플리케이션의 전반적인 상태를 관리합니다.

QueryClientProvider ⇒ createContext로 전역으로 queryClient 관리

dehydrate ⇒ prefetch 할 때 생성한 queryClient를 이용하여 이 때의 queryClient를 넘겨주어 쿼리 캐시들을 가져와주는(flatMap으로 직렬화) 역할만 함 ⇒ 그냥 정말 queryClient에 캐싱된 것들만 꺼내서(역할 끝) ⇒ HydrationBoundary state에 쏙 넣어줌

HydrationBoundary ⇒ client 옵션이 있는데 ⇒ client가 props로 오면 그걸 쓰고 아니면 context의 queryClient를 씀 ⇒ 넘겨주는게 없으니 context queryClient를 쓸 거고