| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455 |
- 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<string, string>;
- };
- // 익명 공개 데이터 전용 서버 fetch — 요청자 쿠키/토큰을 붙이지 않으므로 응답이 모든 사용자 공통이고,
- // 따라서 Next Data Cache(revalidate/tags)로 요청 간 캐시가 안전하다. 라우트가 cookies()/headers() 로
- // 동적이어도 개별 fetch 는 Data Cache 에서 서빙된다.
- // ⚠️ 사용자별 데이터·인증 필요 호출은 반드시 기존 fetchJson 사용(그쪽은 쿠키/Authorization 주입 → 캐시 금지).
- export async function fetchPublicJson<T>(url: string, options: PublicFetchOptions = {}): Promise<ResultDto<T>>
- {
- 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<T>;
- }
- 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<T>;
- }
- return await res.json() as ResultDto<T>;
- } 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<T>;
- }
- }
|