인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

Inflearn Community Q&A

busbug38250's profile image
busbug38250

asked

Next + Create a SNS service with React Query

두개의 차이점

Resolved

Written on

·

125

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을 하면서 데이터를 동기화할 필요가 있나 싶어서 어떻게 사용해야할지 감이 안잡히네여

reactnext.jsreact-querynext-authmsw

Answer 1

0

zerocho님의 프로필 이미지
zerocho
Instructor

2번 방법으로 하면 페이지는 10초마다 리밸리데이트하더라도 fetch의 데이터는 영구적으로 캐싱일 것 같습니다. 프로덕트 목록이 업데이트 되는 것이라면 1번 방식을 해야할 것 같네요.

busbug38250님의 프로필 이미지
busbug38250
Questioner

2번 방법으로해도 fetch Data가 변경되고 10초 이후에는 새로고침할때 변경된 데이터로 그려져서요ㅠㅠ

zerocho님의 프로필 이미지
zerocho
Instructor

다시 문서 읽어보니까 const revalidate는 default value가 Infinity인데 fetch revalidate는 기본값이 없네요. 그러면 지금 상황에서는 둘이 똑같은 게 맞습니다. 1번에서는 fetch revalidate가 const revalidate를 낮추고, 2번에서는 const revalidate 값을 fetch revalidate가 따라가네요.

참고로 개발모드에서는 페이지 캐시가 작동하지 않으니 테스트할 때 유의하셔야 합니다.

busbug38250님의 프로필 이미지
busbug38250
Questioner

답변 감사합니다!

busbug38250's profile image
busbug38250

asked

Ask a question