next.js app router 에서의 tanstack-query (3)
Lesson 3: 서버 프리페칭(Prefetching)
우리는 next.js에서 서버 컴포넌트(page.tsx)를 사용해 서버 액션을 미리 호출해서, 클라이언트가 로딩 없이 바로 데이터를 보게할 수 있다.
목표: "깜빡임 없는 상품 목록 만들기"
1. 상황 (Scenario)
* 사용자(User)는 우리 앱의 상품 목록 페이지 (`/prefetch`)에 들어옵니다.
* Lesson 2에서 만든 페이지는 처음에 "⏳ 로딩 중..."이 떴다가 1초 뒤에 목록이 나옴.
* 우리의 목표: 사용자가 페이지에 들어오자마자 로딩 없이 즉시 1초 뒤의 데이터가 꽉 찬
상태를 보여주는 것
2. 전략 (Strategy)
* (서버 컴포넌트): 사용자가 요청을 보내면, 페이지를 그리기 전에 미리 데이터를
가져와서(Prefetch) Cache에 담음.
* (클라이언트 컴포넌트): 페이지가 로드되면, Cache된 데이터를
열어서(Dehydrate) 바로 꺼내씀(Hydrate). 새로 데이터를 요청하지 않는다
1. 개념 정의
* 서버 프리페칭(Server Prefetching): 사용자가 브라우저에 접속하기 전, 서버(Next.js)가
데이터를 미리 가져와서 React Query 캐시에 담아두는 기술입니다.
* 하이드레이션(Hydration): 서버에서 말려놓은(Dehydrated) 캐시 데이터를 클라이언트
브라우저가 받아서 다시 물을 주듯(Hydrate) 실제 메모리 상의 캐시로 복구하는
과정입니다.
2. 왜 사용하나요? (UX의 혁신)
* 로딩 스피너 제거: 사용자가 페이지에 진입하자마자 완성된 데이터를 보게 됩니다.
(isLoading이 필요 없음)
* SEO 최적화: 검색 엔진 봇이 데이터를 포함한 완성된 HTML을 읽을 수 있습니다.
* 폭포수(Waterfall) 방지: 여러 데이터를 가져올 때 서버에서 병렬로 미리 처리하여
클라이언트의 부담을 줄입니다.
3. 구현 공식 (5단계)
1. 서버 컴포넌트(`page.tsx`)에서 getQueryClient()를 호출하여 서버용 클라이언트를
생성합니다.
2. queryClient.prefetchQuery({...})를 실행하여 캐시를 미리 채웁니다. 이때 비동기
함수(Server Action 등)를 사용합니다.
3. dehydrate(queryClient)를 통해 캐시된 데이터를 직렬화 가능한 객체로 만듭니다.
4. 클라이언트 사이드에서 사용할 HydrationBoundary 컴포넌트로 UI를 감싸고, state로
dehydrated 데이터를 넘겨줍니다.
5. 클라이언트 컴포넌트(`ProductList`) 내부의 useQuery는 서버에서 사용한 것과 동일한
queryKey를 사용하여 데이터를 즉시 꺼내 씁니다.