summaryrefslogtreecommitdiff
path: root/app/api/revalidate/approval/route.ts
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-11-05 19:28:49 +0900
committerjoonhoekim <26rote@gmail.com>2025-11-05 19:28:49 +0900
commite890fbae0c9c273b825ac808aa516de1f87fb218 (patch)
treec2b7bdacd22043a8b4781e9b4c6ea682468abd0f /app/api/revalidate/approval/route.ts
parent35e373fe29a4145d0692ee35ff9e6b0c887df0eb (diff)
(김준회) 실사의뢰 결재 오류 수정, 결재 캐시 백그라운드 컨텍스트에서 패스로 무효화 처리, pm2 ecosystem 설정 변경 (npm 레이어 로그 문제), git 줄바꿈 문제 2건 커밋으로 처리
Diffstat (limited to 'app/api/revalidate/approval/route.ts')
-rw-r--r--app/api/revalidate/approval/route.ts101
1 files changed, 101 insertions, 0 deletions
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 }
+ );
+ }
+}
+