import 'server-only'; import { ResultDto } from '@/types/response/common'; const API_URL = process.env.API_URL; type PublicFetchOptions = { // Next Data Cache 재검증 주기(초). 기본 300초. revalidate?: number; // revalidateTag 로 무효화할 태그 tags?: string[]; headers?: Record; }; // 익명 공개 데이터 전용 서버 fetch — 요청자 쿠키/토큰을 붙이지 않으므로 응답이 모든 사용자 공통이고, // 따라서 Next Data Cache(revalidate/tags)로 요청 간 캐시가 안전하다. 라우트가 cookies()/headers() 로 // 동적이어도 개별 fetch 는 Data Cache 에서 서빙된다. // ⚠️ 사용자별 데이터·인증 필요 호출은 반드시 기존 fetchJson 사용(그쪽은 쿠키/Authorization 주입 → 캐시 금지). export async function fetchPublicJson(url: string, options: PublicFetchOptions = {}): Promise> { const { revalidate = 300, tags, headers } = options; try { const actionURL = `${API_URL}${url.startsWith('/') ? url : `/${url}`}`; const res = await fetch(actionURL, { method: 'GET', headers: { 'Accept': 'application/json', ...(headers ?? {}) }, next: { revalidate, ...(tags && tags.length > 0 ? { tags } : {}) } }); if (res.status === 204) { return { success: true, status: 204, message: null, data: null, errors: null } satisfies ResultDto; } const contentType = res.headers.get('content-type'); if (!contentType || !contentType.includes('application/json')) { return { success: false, status: res.status, message: null, data: null, errors: null } satisfies ResultDto; } return await res.json() as ResultDto; } catch (err) { const message = err instanceof Error ? err.message : '서버와 통신이 불가합니다.'; console.warn(`[500] ${message}`); return { success: false, status: 500, message, data: null, errors: null } satisfies ResultDto; } }