Space
article thumbnail
반응형

Before you learn

🔗 [NextJS] Cache (캐시)

반응형

[NextJS] Cache Strategy (캐시 전략)

캐시 전략

각 홈페이지마다 cache 전략을 잘 세워서 작성해야 한다.

 

유저수가 많은 페이지일수록 더욱 중요하다.

 

Product에 관련된 Cache 전략을 작성해 보겠다.

(캐시 전략에 대해서만 작성하겠다.)

 

Home page : `home-product-list`를 60초마다 캐시 재검증한다.

// app/(tabs)/home/page.tsx

import { unstable_cache as nextCache } from "next/cache";

const getCacheProductList = nextCache(getInitialPostList, ["home-product-list"], {
  tags: ["home-product-list"],
  revalidate: 60,
});

 

Product detail page : `product-detail-${productId}`, `product-title-${productId}`를 60초마다 캐시를 재검증한다.

// app/product/[id]/page.tsx

import { unstable_cache as nextCache } from "next/cache";

function getCachedProductDetail(productId: number) {
  const cachedOperation = nextCache(getProductDetail, [`product-detail-${productId}`], {
    revalidate: 60,
    tags: [`product-detail-${productId}`],
  });
  return cachedOperation(productId);
}  

function getCachedProductTitle(productId: number) {
  const cachedOperation = nextCache(getProductTitle, [`product-title-${productId}`], {
    revalidate: 60,
    tags: [`product-title-${productId}`],
  });
  return cachedOperation(productId);
}

 

 

Product add page

: product 추가 후 product detail page로 이동하므로, `product-detail-${producttId}`, `product-title-${productId}`를 재검증하고,

  만약 유저가 detail page에서 home page로 이동할 수 도 있기에, "home-product-list"도 재검증한다.

// app/add/product/actions.ts

import { redirect } from "next/navigation";
import { revalidateTag } from "next/cache";

export async function uploadProduct(_: any, formData: FormData) {
      
      // db에 product upload 하는 코드...
      
      revalidateTag(`home-product-list`);
      revalidateTag(`product-detail-${product.id}`);
      revalidateTag(`product-title-${product.id}`);
      redirect(`/product/${product.id}`);
    }
  }
}

 

Product edit page

: edit page에서 편집 완료 후 product detail page로 이동하므로, `product-detail-${productId}`, `product-title-${productId}`를 재검증하고,

만약 유저가 detail page에서 home page로 이동할 수 도 있기에, "home-product-list"도 재검증한다.

// app/edit/product/[id]/page.tsx

import { unstable_cache as nextCache } from "next/cache";

function getCacheProductDetail(productId: number) {
  const cachedOperation = nextCache(getProductDetail, [`product-detail-${productId}`], {
    revalidate: 60,
  });
  return cachedOperation(productId);
}
// app/edit/product/[id]/actions.ts

import { redirect } from "next/navigation";
import { revalidateTag } from "next/cache";

export async function editProductUpload(_: any, formData: FormData) {

      // db에 수정된 product 데이터 업로드 하는 코드 ...

      revalidateTag(`home-product-list`);
      revalidateTag(`product-detail-${product.id}`);
      revalidateTag(`product-title-${product.id}`);
      redirect(`/product/${product.id}`);
    }
  }
}

 

Product delete

: product detail page에서 삭제버튼을 누르면 product가 삭제되고, home page로 이동하므로, "home-product-list"를 재검증하고,

  DB에서 삭제는 되었지만 아직 캐시가 남아있고, 해당 페이지에 접근을 차단하는 코드가 없을 경우,

  삭제된 product의 detail page로 접속이 될 수도 있기에, `product-detail-${productId}`, `product-title-${productId}`를 모두 재검증한다.

// app/product/[id]/actions.ts

import { revalidateTag } from "next/cache";

export async function onClickDeleteProduct(id: number) {

  // db에서 해당 product 삭제하는 코드 ...

  revalidateTag("home-product-list");
  revalidateTag(`product-detail-${product.id}`);
  revalidateTag(`product-title-${product.id}`);
  // redirect는 deleteBtn 마지막에 동작하도록 되어있어서 생략함
}

 

 

다른 유저가 CRUD를 한 경우에도 최신화된 product를 보여줘야 하기에, 60초마다 전부  재검증하도록 설정해 두었다.

만약 캐시 재검증 전에 다른 유저가 해당 product를 삭제했더라도 404 처리되어 해당 페이지에 접속하지 못하게 설정해 두었다.

revalidate: 60

의문점

Q1. Why Use?

간단히 적자면,
DB의 휴식시간을 주기 위해서이고, 효율적으로 데이터를 사용하고, 더욱 빠르게 보여주기 위함이다.

 

Q2. Tag를 product-title, product-detail처럼 하지 않고, 뒤에 id값을 넣는 이유?

product-title만 하게 되면 모든 product-title Tag를 가진 캐시가 재검증한다.
그렇기에 유저에게 보여주는 하나의 데이터만 재검증하기 위해 product-title-${productId}처럼 사용하였다.
(굳이 보여주지 않는 부분까지 재검증할 필요는 없고, 보여줄 때 해당부분만 재검증하면 된다.)

Reference

🔗 NextJS 공식 사이트 (unstable_cache)

반응형
profile

Space

@Space_zero

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!