summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/api/pos/download-on-demand-partners/route.ts1
-rw-r--r--app/api/revalidate/approval/route.ts101
2 files changed, 102 insertions, 0 deletions
diff --git a/app/api/pos/download-on-demand-partners/route.ts b/app/api/pos/download-on-demand-partners/route.ts
index d2941537..0e146c80 100644
--- a/app/api/pos/download-on-demand-partners/route.ts
+++ b/app/api/pos/download-on-demand-partners/route.ts
@@ -241,3 +241,4 @@ export async function GET(request: NextRequest) {
}
}
+
diff --git a/app/api/revalidate/approval/route.ts b/app/api/revalidate/approval/route.ts
new file mode 100644
index 00000000..ed4da139
--- /dev/null
+++ b/app/api/revalidate/approval/route.ts
@@ -0,0 +1,101 @@
+import { revalidateTag } from 'next/cache';
+import { NextRequest, NextResponse } from 'next/server';
+
+/**
+ * 결재 시스템 캐시 무효화 API
+ *
+ * 백그라운드 프로세스(폴링 서비스)에서 request 컨텍스트 없이
+ * 캐시를 무효화하기 위한 API 라우트
+ *
+ * 사용법:
+ * await fetch('/api/revalidate/approval', {
+ * method: 'POST',
+ * headers: { 'Content-Type': 'application/json' },
+ * body: JSON.stringify({ tags: ['approval-logs'] })
+ * });
+ */
+export async function POST(request: NextRequest) {
+ try {
+ const body = await request.json();
+ const { tags, secret } = body;
+
+ // 선택적 보안: 환경 변수로 시크릿 키 검증
+ // 내부 서버에서만 호출되므로 필수는 아님
+ if (process.env.REVALIDATION_SECRET && secret !== process.env.REVALIDATION_SECRET) {
+ return NextResponse.json(
+ { success: false, message: 'Invalid secret' },
+ { status: 401 }
+ );
+ }
+
+ // 캐시 태그 무효화
+ if (Array.isArray(tags)) {
+ for (const tag of tags) {
+ revalidateTag(tag);
+ console.log(`[Cache Revalidation] Tag revalidated: ${tag}`);
+ }
+ } else if (typeof tags === 'string') {
+ revalidateTag(tags);
+ console.log(`[Cache Revalidation] Tag revalidated: ${tags}`);
+ }
+
+ return NextResponse.json({
+ success: true,
+ revalidated: true,
+ tags: Array.isArray(tags) ? tags : [tags],
+ timestamp: new Date().toISOString(),
+ });
+ } catch (error) {
+ console.error('[Cache Revalidation] Error:', error);
+ return NextResponse.json(
+ {
+ success: false,
+ message: error instanceof Error ? error.message : 'Revalidation failed',
+ },
+ { status: 500 }
+ );
+ }
+}
+
+// GET 요청으로도 사용 가능 (개발/테스트용)
+export async function GET(request: NextRequest) {
+ const { searchParams } = new URL(request.url);
+ const tag = searchParams.get('tag');
+ const secret = searchParams.get('secret');
+
+ if (process.env.REVALIDATION_SECRET && secret !== process.env.REVALIDATION_SECRET) {
+ return NextResponse.json(
+ { success: false, message: 'Invalid secret' },
+ { status: 401 }
+ );
+ }
+
+ if (!tag) {
+ return NextResponse.json(
+ { success: false, message: 'Tag parameter is required' },
+ { status: 400 }
+ );
+ }
+
+ try {
+ revalidateTag(tag);
+ console.log(`[Cache Revalidation] Tag revalidated: ${tag}`);
+
+ return NextResponse.json({
+ success: true,
+ revalidated: true,
+ tag,
+ timestamp: new Date().toISOString(),
+ });
+ } catch (error) {
+ console.error('[Cache Revalidation] Error:', error);
+ return NextResponse.json(
+ {
+ success: false,
+ message: error instanceof Error ? error.message : 'Revalidation failed',
+ },
+ { status: 500 }
+ );
+ }
+}
+