2025. 3. 5. 21:11ㆍ프론트엔드/Next JS
📌 On-Demand ISR (특정 페이지 즉시 다시 생성) 자세한 설명
✅ On-Demand ISR(Incremental Static Regeneration)이란?
기존 ISR(Incremental Static Regeneration)은 일정 시간(revalidate)마다 자동으로 페이지를 갱신하지만,
On-Demand ISR은 특정 API를 호출하면 즉시 해당 페이지를 다시 생성합니다.
📌 사용자가 특정 행동(예: 데이터 변경)을 하면, 해당 페이지를 강제로 다시 빌드하여 최신 데이터를 반영하는 방식입니다.
🔹 On-Demand ISR vs 기존 ISR 차이점
방식 기존 ISR On-Demand ISR
| 재생성 방식 | revalidate 시간이 지나면 다음 요청 시 백그라운드에서 갱신 | 특정 API 호출 시 즉시 갱신 |
| 데이터 반영 속도 | 일정 시간이 지나야 갱신됨 | 사용자의 특정 행동에 따라 즉시 반영 가능 |
| 서버 부하 | 일정한 간격으로만 실행됨 | 필요한 순간에만 실행되므로 더 효율적 |
| 적용 예시 | 뉴스, 블로그, 상품 리스트 | 게시글 수정 후 즉시 반영, 특정 페이지 강제 업데이트 |
✅ On-Demand ISR의 필요성
기본 ISR은 revalidate: 10과 같이 일정 시간이 지나야 갱신되므로, 데이터가 변경된 직후 바로 반영되지는 않습니다.
즉, 실시간성이 필요한 페이지에서는 ISR의 revalidate 설정만으로는 부족할 수 있습니다.
👉 On-Demand ISR을 사용하면, 관리자(운영자)가 데이터를 변경한 즉시 해당 페이지를 다시 생성하도록 트리거할 수 있습니다. 🚀
✅ On-Demand ISR API 코드 분석
import { NextApiRequest, NextApiResponse } from "next";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
try {
await res.revalidate("/"); // 루트 페이지 강제 재검증 ("/" 페이지 새로 생성)
return res.json({ revalidate: true }); // 성공 시 응답
} catch (err) {
res.status(500).send("Revalidation Failed"); // 실패 시 500 에러 반환
}
}
🔹 코드 설명
- req: NextApiRequest, res: NextApiResponse → Next.js API Route의 요청 & 응답 객체
- res.revalidate("/") → / 페이지를 즉시 다시 생성 (ISR 강제 실행)
- 성공하면 { revalidate: true } JSON 응답 반환
- 실패하면 500 (Revalidation Failed) 응답 반환
✅ On-Demand ISR을 호출하는 방법
On-Demand ISR은 API를 통해 호출되므로, 이를 프론트엔드에서 fetch()를 사용해 트리거할 수 있습니다.
📝 클라이언트에서 On-Demand ISR 실행하기
async function triggerRevalidate() {
const response = await fetch("/api/revalidate", {
method: "POST",
});
if (response.ok) {
alert("페이지가 성공적으로 다시 생성되었습니다!");
} else {
alert("재생성에 실패했습니다.");
}
}
📌 버튼을 만들어 클릭 시 해당 API를 호출하면 특정 페이지를 강제로 다시 생성할 수 있습니다.
✅ On-Demand ISR을 특정 페이지에 적용하기
기본적으로 res.revalidate("/")는 루트 페이지만 다시 생성하지만, 특정 페이지를 지정하여 부분 갱신도 가능합니다.
📝 특정 페이지만 다시 생성하는 API Route
import { NextApiRequest, NextApiResponse } from "next";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
try {
const { path } = req.query; // 요청 URL에서 path 추출
if (!path) return res.status(400).json({ error: "Path is required" });
await res.revalidate(path as string); // 특정 경로만 재생성
return res.json({ revalidate: true });
} catch (err) {
res.status(500).send("Revalidation Failed");
}
}
📝 프론트엔드에서 특정 페이지 강제 재생성 요청
async function triggerRevalidate(path: string) {
const response = await fetch(`/api/revalidate?path=${path}`, {
method: "POST",
});
if (response.ok) {
alert(`"${path}" 페이지가 성공적으로 다시 생성되었습니다!`);
} else {
alert(`"${path}" 페이지 재생성에 실패했습니다.`);
}
}
📌 triggerRevalidate("/products/123")처럼 특정 페이지를 지정하여 강제로 다시 생성 가능.
✅ On-Demand ISR을 활용하는 시나리오
🔹 1. 블로그 포스트 수정 후 즉시 반영
// 블로그 포스트 저장 후 특정 페이지 다시 생성 요청
await fetch(`/api/revalidate?path=/blog/${postId}`, { method: "POST" });
🔹 관리자가 새 글을 작성하거나 기존 글을 수정하면 해당 블로그 글 페이지를 즉시 다시 생성할 수 있습니다.
🔹 2. 쇼핑몰 상품 정보 수정 후 즉시 반영
// 상품 정보 수정 후 특정 상품 상세 페이지 다시 생성 요청
await fetch(`/api/revalidate?path=/products/${productId}`, { method: "POST" });
🔹 상품 정보(가격, 설명 등)가 수정되면 해당 상품 상세 페이지를 즉시 다시 생성하여 최신 정보를 제공할 수 있습니다.
🔹 3. 관리자 대시보드에서 모든 페이지 즉시 갱신
// 관리자 페이지에서 전체 사이트 강제 갱신 버튼
await fetch("/api/revalidate", { method: "POST" });
🔹 관리자가 운영하는 웹사이트에서 특정 페이지뿐만 아니라 모든 페이지를 한 번에 강제 갱신할 수도 있음.
✅ On-Demand ISR vs 기존 ISR 비교
방식 기존 ISR (revalidate) On-Demand ISR (res.revalidate())
| 갱신 방식 | 일정 시간이 지나야 자동 갱신 | API 요청을 통해 즉시 갱신 |
| 즉시 반영 여부 | 불가능 (대기 시간이 필요함) | 가능 (바로 갱신됨) |
| 사용 예시 | 정기적으로 업데이트되는 페이지 (예: 뉴스) | 게시글 수정, 상품 업데이트 후 즉시 반영 필요 |
✅ 결론
🚀 On-Demand ISR을 사용하면 데이터가 변경되었을 때 즉시 해당 페이지를 다시 생성할 수 있습니다.
💡 기존 ISR(정기적 재생성)과 SSR(매 요청마다 재생성)의 장점을 결합하여 최신 데이터를 반영하면서도 성능을 유지할 수 있습니다.
🎯 블로그, 쇼핑몰, 뉴스 사이트 등 데이터가 자주 변경되는 페이지에 최적화된 방식입니다.
'프론트엔드 > Next JS' 카테고리의 다른 글
| 📌 Next.js 페이지 라우터(페이지 기반 라우팅) 총정리 🚀 (2) | 2025.03.05 |
|---|---|
| Next.js에서 SEO 최적화하는 방법 (SSR, SSG, ISR, 동적 경로 포함) (2) | 2025.03.05 |
| 📌 Next.js의 ISR(Incremental Static Regeneration) 방식 자세한 설명 (0) | 2025.03.05 |
| 📌 Next.js에서 getStaticProps와 getStaticPaths를 활용한 SSG 정리 (0) | 2025.03.05 |
| Next.js의 SSG(Static Site Generation) 개념과 활용 (0) | 2025.03.02 |