From 7cbde80466b5b4752dc92adb265f3bbda7a7e016 Mon Sep 17 00:00:00 2001 From: ljpark Date: Fri, 22 May 2026 14:56:58 +0900 Subject: [PATCH] =?UTF-8?q?dm:=20=EC=BD=98=ED=85=90=EC=B8=A0=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20refresh?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/dm/app/(with-layout)/contents/page.tsx | 27 +++++++++++++++---- .../dm/components/ui/contents/contents-api.ts | 18 +++++++++++-- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/apps/dm/app/(with-layout)/contents/page.tsx b/apps/dm/app/(with-layout)/contents/page.tsx index 27d0974be..02b97af14 100644 --- a/apps/dm/app/(with-layout)/contents/page.tsx +++ b/apps/dm/app/(with-layout)/contents/page.tsx @@ -1,9 +1,26 @@ -export const dynamic = "force-dynamic"; -import { ContentsPage } from "@/components/ui/contents"; +import { revalidateTag } from "next/cache"; +import { Button } from "@common/components/ui/button"; export default async function Contents() { - const contsSn = 28; - const menuCd = "24"; + /** + * 'dm-content-detail' 태그를 가진 캐시 데이터를 즉시 무효화하는 서버 액션입니다. + * 버튼 클릭 시 실행되며, 이후 이 태그를 사용하는 모든 페이지는 최신 데이터를 다시 가져옵니다. + */ + async function revalidateAction() { + "use server"; + revalidateTag("dm-content-detail"); + console.log("Cache revalidated for tag: dm-content-detail"); + } - return ; + return ( +
+
+

콘텐츠 관리 도구

+

변경된 콘텐츠 내용을 즉시 반영하려면 아래 버튼을 클릭하세요.

+
+ +
+
+
+ ); } diff --git a/apps/dm/components/ui/contents/contents-api.ts b/apps/dm/components/ui/contents/contents-api.ts index 3a7c64639..0472b438b 100644 --- a/apps/dm/components/ui/contents/contents-api.ts +++ b/apps/dm/components/ui/contents/contents-api.ts @@ -4,14 +4,24 @@ import { unstable_cache } from "next/cache"; import { ENDPOINT } from "@/src/shared/config"; +function getServerBaseUrl() { + const port = process.env.PORT ?? process.env.NEXT_PUBLIC_PORT ?? "3000"; + const proxyHost = process.env.NEXT_PUBLIC_PROXY_HOST; + + if (process.env.NODE_ENV === "production" && process.env.HOSTNAME) { + return `http://${process.env.HOSTNAME}:${port}`; + } + + return proxyHost || `http://localhost:${port}`; +} export const getCachedContentDetail = unstable_cache( async (contsSn: number, menuCd: string) => { - const baseUrl = process.env.NEXT_PUBLIC_PROXY_HOST || "http://localhost:3015"; + const baseUrl = getServerBaseUrl(); const res = await fetch( `${baseUrl}${ENDPOINT.CMS_SERVICE.CONTENTS}/${contsSn}?menuCd=${menuCd}`, { - next: { revalidate: 3600, tags: [`content:${contsSn}`] }, + next: { revalidate: 0, tags: [`content:${contsSn}`] }, } ); @@ -23,4 +33,8 @@ export const getCachedContentDetail = unstable_cache( return res.json(); }, ["dm-content-detail"], + { + revalidate: 86400, // 1시간마다 자동 갱신 (선택 사항) + tags: ["dm-content-detail"], // 여기에 태그를 명시해야 revalidateTag가 작동합니다. + } );