해결된 질문
작성
·
64
0
안녕하세요, 아래 ISR에 대해서 질문드렸었는데, nextjs 에서 2가지 구현 방법이있다고 해서
두가지가 어떤 차이점이 있고 어떻게 활용하는게 좋을지 궁금해서 질문드립니다!
1번 방법 = fetch API 의 revlidate를 활용하여 ISR 구현
import ProductList from "@/component/ProductList";
import { getQueryClient } from "@/component/TanstackQueryOption";
import { getProducts } from "@/fetch/getProducts";
import { dehydrate, HydrationBoundary, QueryClient } from "@tanstack/react-query";
import Image from "next/image";
export default async function ProductPage () {
const queryClient = getQueryClient();
await queryClient.prefetchQuery({
queryKey:['products'],
queryFn: getProducts,
})
return (
<>
<section className='visual-sec'>
<Image src="/visual.png" alt="visual" width={1920} height={300}/>
</section>
<section className="product-sec">
<h2>상품 리스트</h2>
<HydrationBoundary state={dehydrate(queryClient)}>
<ProductList />
</HydrationBoundary>
</section>
</>
)
}
import {
isServer,
QueryClient,
defaultShouldDehydrateQuery,
} from '@tanstack/react-query'
function makeQueryClient() {
return new QueryClient({
defaultOptions: {
queries: {
staleTime: 10 * 1000,
},
dehydrate: {
shouldDehydrateQuery: (query) =>
defaultShouldDehydrateQuery(query) ||
query.state.status === 'pending',
},
},
})
}
let browserQueryClient: QueryClient | undefined = undefined
export function getQueryClient() {
if (isServer) {
return makeQueryClient()
} else {
if (!browserQueryClient) browserQueryClient = makeQueryClient()
return browserQueryClient
}
}
'use client'
import { getQueryClient } from '@/component/TanstackQueryOption';
import {
QueryClientProvider,
} from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { ReactNode } from 'react'
export default function TanstackQueryProvider({ children }: { children: ReactNode }) {
const queryClient = getQueryClient()
return (
<QueryClientProvider client={queryClient}>
{children}
<ReactQueryDevtools
initialIsOpen={true}
/>
</QueryClientProvider>
)
}
export const getProducts = async () => {
const res = await fetch(`http://localhost:9090/api/products`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
next: {
revalidate: 10,
}
});
const data = await res.json();
const currentTime = new Date().toLocaleTimeString('ko-KR', {
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
fractionalSecondDigits: 3,
hour12: false,
});
if (typeof window === "undefined") {
console.log('fetch products', 'server', currentTime);
console.table(data);
} else {
console.log('fetch products', 'client', currentTime);
console.table(data);
}
if(!res.ok) {
throw new Error("Failed to fetch products");
}
return data;
}
2번 방법 = export const revalidate 로 시간 설정 후 fetch로 받은 data 값을 바로 렌더링 시키기
import Product from "@/component/Product";
import styles from '@/component/ProductList.module.css';
import Image from "next/image";
export const revalidate = 10;
export default async function Product2Page() {
const data = await fetch('/api/products');
const products = await data.json();
console.log(revalidate, 'Product2Page');
return (
<>
<section className='visual-sec'>
<Image src="/visual.png" alt="visual" width={1920} height={300}/>
</section>
<section className="product-sec">
<h2>상품 리스트</h2>
<div className={styles.productList}>
{products.map((product: any) => (
<Product key={product.item_no} product={product} />
))}
</div>
</section>
</>
)
}
2개다 ISR로 구현되며, 1번 방법은 Data Cache 캐싱 매커니즘을 활용하고,
2번 방법은 Full Router Cache 캐싱 매커니즘을 활용한다의 차이점으로 생각이 드는데,
이 외에 다른 차이점과 실제 개발을 하면서 선호되는 방식이 따로 있을까요? 해당 페이지만 보았을때는 2번 방법으로 해도 어차피 주기적으로 다시 생성해서 최신 데이터를 반영하면 복잡하게 react-query를 사용하고, Hydration을 하면서 데이터를 동기화할 필요가 있나 싶어서 어떻게 사용해야할지 감이 안잡히네여
답변 1
0
2번 방법으로 하면 페이지는 10초마다 리밸리데이트하더라도 fetch의 데이터는 영구적으로 캐싱일 것 같습니다. 프로덕트 목록이 업데이트 되는 것이라면 1번 방식을 해야할 것 같네요.
2번 방법으로해도 fetch Data가 변경되고 10초 이후에는 새로고침할때 변경된 데이터로 그려져서요ㅠㅠ