Next.js fetch & App Router 캐싱 완벽 가이드
Next.js의 fetch 캐싱 동작을 이해하고, 실무에서의 적용 방법을 단계별로 배워보세요. 초보자도 따라하기 쉬운 체크리스트 제공합니다.
핵심: Next.js는 서버 렌더링과 클라이언트 요청 사이의 데이터 페칭을 통합해 성능을 높이고 비용을 절감하는 전략을 제공합니다. App Router의 fetch는 기본적으로 서버 쪽에서 응답을 캐시하고 필요 시 재검증하는 메커니즘을 통해 일관된 사용자 경험을 만듭니다.
도입: Next.js fetch와 App Router 캐싱이란
Next.js App Router의 App Router에서 제공하는 fetch는 서버 컴포넌트와 클라이언트 컴포넌트 간의 데이터 요청을 조정합니다. 서버 쪽에서는 기본적으로 응답을 캐시하여 반복 요청에 대한 레이턴시를 줄이고, 클라이언트 쪽에서는 브라우저 표준 fetch 동작을 따릅니다. 이 구조는 페이지 로드 시간 단축과 백엔드 호출 횟수 감소라는 실질적 이점을 제공합니다.
App Router 캐싱은 캐시 지속 시간과 재검증 정책을 개발자가 제어할 수 있도록 옵션을 제공합니다. 예를 들어 revalidate를 60으로 설정하면 서버에서 최대 60초 동안 동일한 결과를 재사용하고 그 이후에 다시 검증을 시도합니다. 이러한 제어는 API 비용을 줄이면서도 신선도를 보장할 때 유용합니다.
이 글은 fetch의 기본 동작을 실무적으로 이해하고, 언제 어떤 옵션을 사용해야 하는지 명확히 하는 것을 목적으로 합니다. 구체적으로는 캐시 기본값, revalidate 숫자 예시, 서버와 클라이언트의 차이점을 실제 시나리오로 비교합니다. 궁극적으로는 성능과 일관성을 고려한 권장 패턴을 제시합니다.
핵심 질문
이 글을 통해 독자는 첫째로 서버 컴포넌트에서 fetch가 기본적으로 어떻게 캐시되는지 알게 됩니다. 예를 들어 revalidate를 60으로 설정했을 때의 동작과 동일 요청이 30초 간격으로 들어올 때의 응답 흐름을 이해할 수 있습니다. 둘째로 클라이언트 환경에서의 fetch가 기본적으로 캐시를 적용하지 않는 이유와 이를 보완하는 패턴을 학습합니다.
셋째로 fetch 옵션(cache, next.revalidate, no-store 등)을 실제 코드와 함께 적용해 볼 수 있습니다. 예시로 cache: 'no-store'를 사용하면 매 요청마다 네트워크 호출이 발생하므로 실시간성이 중요한 데이터(예: 결제 상태)에 적합합니다. 넷째로 캐시 정책 선택이 트래픽 비용과 사용자 응답성에 어떤 수치적 영향을 주는지 비교할 수 있습니다.
기본 원리: Next.js에서 fetch가 동작하는 방식
Next.js fetch 캐싱 동작 이해하기에서의 fetch는 호출되는 위치(서버 컴포넌트 vs 클라이언트 컴포넌트)에 따라 기본 동작과 캐시 전략이 달라집니다. 서버 컴포넌트에서 호출되는 fetch는 기본적으로 서버 레벨의 캐시를 사용해 여러 요청 간에 응답을 공유할 수 있습니다. 반면 클라이언트 컴포넌트의 fetch는 브라우저의 네트워킹과 캐시 규칙을 따릅니다.
서버 vs 클라이언트에서의 fetch 차이
서버에서의 fetch는 기본값으로 force-cache 유사 동작을 하며 동일한 URL과 옵션으로 들어오는 요청을 재사용합니다. 예를 들어 동일 API에 초당 10회의 요청이 들어오고 revalidate가 설정되어 있지 않다면 첫 요청 결과가 일정 기간(무기한 또는 헤더 기반) 재사용될 수 있습니다. 클라이언트 측 fetch는 기본적으로 매 요청마다 네트워크가 발생하거나 브라우저 캐시 정책을 따르므로, 동일한 패턴에서 서버보다 더 자주 네트워크 호출이 발생합니다.
서버 쪽 캐시는 여러 사용자가 동일한 리소스를 요청할 때 큰 이점을 제공합니다. 예를 들어 인기 뉴스 페이지가 분당 1,200회 요청을 받을 때 서버 캐시를 사용하면 실제 백엔드 호출은 초당 1~2회로 줄어들 수 있습니다. 반면 실시간성이 중요한 대시보드 같은 경우에는 cache: 'no-store'를 사용해 항상 최신 데이터를 가져오도록 구성해야 합니다.
fetch 옵션과 기본값 정리
주요 옵션으로는 cache, next.revalidate(또는 next: { revalidate }), 그리고 cache: 'no-store'가 있습니다. 예를 들어 next: { revalidate: 60 }을 설정하면 응답은 최대 60초 동안 캐시되고, 그 기간 이후의 첫 요청에서 백그라운드 재검증이 트리거됩니다. cache: 'no-store'는 캐시를 완전히 비활성화해 매번 네트워크 요청을 보냅니다.
예시:
await fetch('https://api.example.com/data', {
next: { revalidate: 60 } // 60초 동안 캐시 후 재검증
});
await fetch('/api/live', { cache: 'no-store' }); // 항상 최신 데이터 강제
기본값은 서버에서 요청될 때 캐시를 활용하는 쪽으로 동작하는 경우가 많습니다. 이 때문에 개발 중에는 예상치 못한 오래된 응답을 볼 수 있으므로 revalidate 값을 명시하거나 no-store로 테스트 환경을 구성하는 것이 안전합니다. 또한 Cache-Control 헤더가 설정된 외부 API의 경우 Next.js가 해당 헤더를 존중해 동작합니다.
권장 사용 사례
정적에 가까운 데이터(예: 블로그 목록)는 revalidate를 길게 설정해(예: 3600초) 백엔드 호출을 크게 줄이는 것이 효과적입니다. 예를 들어 하루 평균 10,000 PV를 가진 블로그에서 revalidate를 3600으로 설정하면 백엔드 호출 수는 초당 평균 2~3회 수준으로 감소합니다. 사용자별 실시간 데이터는 cache: 'no-store'를 사용해 항상 최신 상태를 유지해야 합니다.
클라이언트 측에서 자주 갱신되는 UI(예: 실시간 알림)에는 React Query나 SWR 같은 클라이언트 캐시 라이브러리를 사용해 폴링이나 소켓과 결합하는 것을 권장합니다. 서버 컴포넌트에서는 가능한 한 서버 캐시와 revalidate를 조합해 비용과 응답성 사이의 균형을 맞추는 것이 좋습니다. 마지막으로 배포 환경에서 Edge 런타임을 사용할 경우 인스턴스별 캐시 특성을 고려해 설정을 검증해야 합니다.
캐싱 메커니즘 상세: revalidate, cache 옵션과 내부 동작
revalidate의 작동 시점
Next.js에서 fetch의 next.revalidate는 특정 리소스에 대해 "생존 시간(TTL)"을 지정하는 방식으로 작동합니다. 예를 들어 revalidate: 60으로 설정하면 최초 응답은 캐시에 저장되고 이후 60초 동안은 캐시된 응답을 그대로 반환합니다. TTL이 만료된 다음 들어온 첫 요청에서 백그라운드 재검증(background revalidation)이 시작되며, 이때 기존의 만료된 응답을 즉시 반환할 수 있습니다.
이 동작은 전통적인 stale-while-revalidate 개념과 유사하지만 구현 세부가 다릅니다. stale-while-revalidate는 만료 후에도 일정 기간 동안 오래된 응답을 제공하는 규칙을 말하는 반면, Next.js의 revalidate는 TTL 만료 시점의 첫 요청에서 재생성을 트리거하고 기본적으로 오래된 응답을 계속 제공하면서 새로운 응답을 비동기적으로 생성하는 패턴을 따릅니다. 결과적으로 사용자 지연(latency)을 최소화하면서도 백그라운드에서 최신화가 이루어집니다.
cache: 'force-cache' / 'no-store' / 'default' 비교
'force-cache'는 가능한 경우 캐시된 응답을 우선 반환하고 캐시에 항목이 없을 때만 네트워크 호출을 발생시킵니다. 반환 관점에서 보면 캐시가 존재하면 0ms에 응답이 가능하고, 저장 관점에서는 응답을 디스크나 인메모리에 저장해 이후 요청에 재사용합니다. 만료 규칙은 revalidate 설정이나 수동 무효화(예: 태그 인벨리데이션)에 의존합니다.
'no-store'는 어떠한 경우에도 캐시를 저장하지 않고 항상 최신 데이터를 요청합니다. 반환은 항상 네트워크 라운드트립을 포함하므로 평균 응답 시간이 늘어나며(예: 100ms→400ms 증가), 저장과 만료는 아예 존재하지 않아 보안상 민감한 데이터(fetching tokens 등)에 적합합니다. 서버 컴포넌트에서 SSR로 처리할 때 세션별 데이터에 주로 사용됩니다.
'default'는 표준 HTTP 캐시 정책과 서버 설정을 따르며 Cache-Control 헤더를 존중합니다. 예컨대 원격 서버가 Cache-Control: max-age=120, stale-while-revalidate=30를 반환하면 Next.js는 이를 준수해 120초 간 캐시하고 그 이후 30초는 stale-while-revalidate 행동을 따를 수 있습니다. 즉, 제어는 외부 응답의 헤더와 Next.js 재설정 옵션의 조합으로 결정됩니다.
동작 예시 타임라인
시나리오: revalidate: 60, cache: 'force-cache'로 설정한 리소스가 있고 초기 요청이 t=0에 들어왔다고 하겠습니다. t=0에는 네트워크 호출이 발생해 응답(예: size 12KB, latency 220ms)이 캐시에 저장되고 클라이언트에 전달됩니다.
t=30에서 들어온 요청은 캐시 유효기간(60초) 내이므로 즉시 캐시 응답을 반환합니다. 평균 응답 시간은 캐시 읽기 기준으로 5~10ms 수준으로 줄어듭니다. 이때 백그라운드 재검증은 발생하지 않습니다.
t=61에서 들어온 요청이 최초 만료 후의 첫 요청이므로 서버는 기존(만료된) 캐시를 즉시 반환하고 동시에 백그라운드에서 재검증을 시작합니다. 재검증이 완료되는 시간은 외부 API 응답 시간에 따라 달라지며(예: 300ms), 성공 시 캐시가 새 응답으로 교체됩니다.
타임라인 요약: t=0 -> 네트워크 호출, 캐시 저장, 응답 반환 (220ms) t=30 -> 캐시 반환 (10ms) t=61 -> 만료, 즉시 'stale' 반환 (10ms), 백그라운드 재검증 시작 t=61.3~61.8 -> 재검증 완료, 캐시 갱신 (외부 API 따라 300~800ms)
실무 예시: 서버 컴포넌트와 클라이언트 컴포넌트에서의 데이터 패칭
서버 컴포넌트 예시
서버 컴포넌트에서는 빌드/런타임에서 fetch를 직접 사용해 데이터를 가져오고 렌더링 타임에 HTML을 생성합니다. 예시로 뉴스 목록을 60초마다 재검증하도록 설정하면 서버는 revalidate: 60을 사용해 ISR을 구현합니다. 이 방식은 SEO에 유리하며 초기 페이지 로드에서 완전한 HTML을 반환하기 때문에 크롤러와 공유할 때 유리합니다.
// app/news/page.tsx (서버 컴포넌트 예시)
export default async function NewsPage() {
const res = await fetch('https://api.example.com/news?limit=10', {
next: { revalidate: 60, tags: ['news-list'] },
// cache: 'force-cache'가 기본 동작과 결합되어 캐시 우선 반환
});
const items = await res.json();
return (
{/* items를 순회해 서버에서 마크업 생성 */}
);
}
위 코드에서 60초 동안은 캐시 응답을 즉시 반환하고, 만료 후 첫 요청 시 백그라운드 재생성을 시작합니다. 만약 뉴스 속보 발생 시 즉각 반영해야 하면 revalidate를 더 짧게(예: 5초) 또는 수동으로 tags를 사용한 무효화로 처리할 수 있습니다. 서버 컴포넌트는 데이터가 페이지 HTML에 미리 포함되므로 렌더링 시점의 일관성이 확보됩니다.
단점으로는 매우 빈번한 실시간 업데이트(초당 수백 건 갱신)가 필요한 경우 revalidate 기반 캐싱이 과도한 백그라운드 재검증을 발생시킬 수 있다는 점입니다. 이런 상황에서는 no-store로 매번 새로 조회하거나, 외부 웹소켓/스트리밍을 결합하는 방식이 더 적합합니다.
클라이언트 컴포넌트 예시
클라이언트 컴포넌트는 브라우저에서 데이터를 패칭하고 상태로 관리하므로 사용자 상호작용이 많은 UI에 적합합니다. 예를 들어 SWR 스타일의 패턴을 사용하면 자동 재검증, 폴링, 포커스 복구 등을 손쉽게 구현할 수 있고 평균 응답 시간 최적화와 UX 개선에 유리합니다. 하지만 초기 로드에서 HTML에는 데이터가 포함되지 않으므로 SEO 민감한 페이지에는 부적합할 수 있습니다.
// 클라이언트 컴포넌트 예시 (간단한 SWR 유사 패턴)
'use client';
import { useEffect, useState } from 'react';
export default function ClientList() {
const [data, setData] = useState(null);
async function fetchData() {
const res = await fetch('/api/items', { cache: 'no-store' });
setData(await res.json());
}
useEffect(() => {
fetchData();
const id = setInterval(fetchData, 15000); // 15초 폴링
return () => clearInterval(id);
}, []);
return {data ? JSON.stringify(data) : '로딩 중...'};
}
위 코드는 cache: 'no-store'를 사용해 항상 최신 데이터를 가져오는 예로, 실시간성이 중요한 관리자 페이지나 사용자별 대시보드에 적합합니다. 폴링 주기를 15초로 설정하면 초당 트래픽이 높아질 때 백엔드 부하를 고려해 증가율과 비용을 계산해야 합니다. 예를 들어 동시 사용자 1,000명에 폴링 15초라면 초당 약 67 요청이 발생하므로 인프라 용량을 2배로 잡아야 할 수 있습니다.
- 체크리스트: 클라이언트 패칭 시 고려사항 — 폴링 주기(초), 캐시 전략(no-store vs force-cache), 실패 재시도 정책(지수 백오프), UX(로딩 스켈레톤)
- 권장 설정 예: 사용자 활동성이 높고 실시간성 필요 시 cache: 'no-store', 폴링 10~30초. 트래픽 비용 고려 시 revalidation 또는 서버 푸시 병행.
요약하면 서버 컴포넌트는 SEO와 초기 로드 퍼포먼스에 유리하고, 클라이언트 컴포넌트는 상호작용과 실시간 업데이트에 유리합니다. 아키텍처 결정 시에는 재검증 간격(예: 5s, 60s, 300s)과 예상 동시 접속자 수, 외부 API 지연(예: 100ms~800ms)을 기준으로 비용·성능 트레이드오프를 평가해야 합니다. 마지막으로 혼합 패턴(서버에서 기본 데이터 렌더링 + 클라이언트에서 실시간 보강)을 사용하면 두 접근의 장점을 함께 얻을 수 있습니다.
비교: 캐싱 전략별 장단점과 판단 기준
성능 우선 판단 기준
Next.js에서 성능을 최우선으로 삼을 때는 응답 시간(TTFB), 캐시 적중률, 비용 세 가지 지표를 동시에 고려해야 합니다. 예를 들어 CDN 캐시 적중률이 90%인 경우 TTFB가 50~100ms로 유지되지만 적중률이 50%로 떨어지면 백엔드 렌더링으로 인해 TTFB가 300ms 이상으로 늘어납니다. 통상적으로 95번째 백분위 응답시간(P95)을 500ms 이하로 유지하는 것을 목표로 삼으면 사용자 경험 개선과 비용 균형을 맞추기 쉽습니다.
전략별로 보면 클라이언트 사이드 캐시는 사용자 상호작용이 많은 SPA 내에서 네비게이션 응답을 20~50ms 수준으로 줄여줍니다. ISR(Incremental Static Regeneration)은 초당 수천 요청 처리 시 CDN 적중률 70~95%를 달성하면 인스턴스 호출을 크게 줄여 비용을 30~80% 절감할 수 있습니다. fetch revalidate(서버 측 재검증)는 데이터 정확도를 위해 중간 수준의 재검증 빈도를 설정할 때 응답 속도와 비용의 균형점으로 자주 선택됩니다.
데이터 민감도(실시간성) 판단
데이터 민감도가 높을수록 캐시 TTL을 짧게 잡아야 합니다. 예를 들어 금융 거래나 실시간 주문 수량은 1초 이하의 재검증 또는 웹소켓/폴링으로 처리해야 하고, 재고 수량은 5~30초, 제품 상세와 같은 변경이 적은 콘텐츠는 300~3600초(5분~1시간) 수준의 재검증을 권장합니다. 이렇게 구체적 TTL을 정하면 캐시 적중률과 실시간성의 트레이드오프를 명확히 관리할 수 있습니다.
실제 사례로 뉴스 헤드라인 페이지는 분당 1~5회의 콘텐츠 업데이트가 예상될 때 revalidate: 60초를 적용하면 대부분의 트래픽에서 CDN 캐시 적중률 80% 이상을 유지하면서 신선도도 확보할 수 있습니다. 반대로 개인화 대시보드나 장바구니처럼 사용자별로 빠르게 변하는 데이터는 서버 측 세션이나 클라이언트 캐시(SWR)로 처리해 revalidation을 최소화하는 편이 낫습니다. 각 페이지 유형별로 표준 TTL을 문서화해 팀 합의를 만드는 것이 운영 부담을 줄입니다.
운영 관점(모니터링/롤백) 고려사항
운영에서는 캐시 관련 메트릭을 실시간으로 모니터링하는 것이 중요합니다. 모니터링 항목으로는 캐시 적중률(%), 원본 호출수, revalidation 실패율, P95 응답시간, 캐시 만료율 등을 설정하고 경고 임계값을 예를 들어 적중률 70% 미만이나 revalidation 실패율 1% 초과 시 알람을 트리거합니다. 문제가 발생하면 즉시 CDN 무효화, revalidate 값 일시 조정(예: 3600s -> 5s), 코드 롤백 순으로 대응하며 먼저 완화 조치로 TTL을 짧게 해 신규 콘텐츠 유통을 막는 방법을 권장합니다.
롤백 절차는 사전 준비가 관건입니다. 배포 전 캐시 관련 Feature Flag를 통해 단계적 활성화를 설정하고, 장애 시 10% -> 50% -> 100% 방식의 점진 적용을 통해 영향 범위를 줄입니다. 또한 재현 가능한 로컬/스테이징 시나리오(예: 10분 동안 5k RPS 부하 테스트)를 마련해 캐시 미스 상황과 revalidation 병목을 사전에 검증해야 합니다.
| 전략 | 장점 | 단점 | 추천 상황 | 권장 재검증 예 |
|---|---|---|---|---|
| ISR (getStaticProps revalidate) | 정적 성능 + 필요시 최신화, CDN 적중률 상승 | 초기 미스 시 렌더 비용 발생, 빌드 복잡도 | 블로그, 상품 상세 페이지, 트래픽 많은 콘텐츠 | 60s ~ 3600s |
| fetch revalidate (서버 단에서 제어) | 데이터 정확도 향상, 서버에서 세밀한 제어 가능 | 서버 부하 증대, 지연시간 증가 가능 | 가격·재고 같이 변경 빈도 중간인 리소스 | 5s ~ 60s |
| Client-side 캐시 (SWR, React Query) | 사용자별 최신화 및 빠른 인터랙션, 낮은 서버 부하 | 초기 로드에서 서버 응답 필요, SEO 측면 제한 | 대시보드, 개인화 영역, 상세한 UI 상태 | 1s ~ 30s(폴링/재검증 기준) |
실무 적용 로드맵: 설정 체크리스트와 단계별 가이드
단계별 작업 상세
1단계는 페이지와 API 엔드포인트를 트래픽·변동성 기준으로 분류하는 것입니다. 예를 들어 상위 10% 트래픽 페이지는 CDN 기반 ISR 후보로, 개인화 페이지는 클라이언트 캐시 후보로 분류합니다. 이 단계에서 페이지별 예상 요청수(예: 일 50만 요청), 변경 빈도(분당 업데이트 수)를 수치로 문서화합니다.
2단계는 각 페이지에 맞는 구현을 적용하는 작업입니다. ISR이 필요한 페이지에는 getStaticProps에 revalidate 값을 설정하고, 실시간성이 필요한 API는 Cache-Control 헤더 또는 SWR을 도입합니다. 이때 권장 설정 예시는 블로그: revalidate: 300, 상품목록: revalidate: 60, 개인대시보드: SWR revalidate 5s 입니다.
3단계는 테스트 및 배포입니다. 로컬과 스테이징에서 부하 테스트를 수행해 캐시 적중률과 P95 응답시간을 측정합니다. 예를 들어 wrk로 30초간 1000 동시 연결을 시뮬레이션해 P95가 목표치(예: 500ms) 이내인지 확인합니다.
- 트래픽/변동성 분류 및 문서화
- 페이지별 전략 결정(ISR, SSR, Client-cache)
- 구현: getStaticProps/revalidate, Cache-Control, SWR 적용
- 스테이징 부하 테스트(예: 1k~5k RPS 시나리오)
- 점진 배포 및 모니터링 설정
점검 포인트 체크리스트
배포 전에 반드시 확인할 항목은 revalidate 설정의 누락 여부입니다. 모든 getStaticProps에 의도한 revalidate 값이 존재하는지, 숫자가 초 단위로 합리적 범위(예: 5s, 60s, 300s)인지 점검하세요. 잘못된 값은 의도치 않은 캐시 만료로 대량 원본 호출을 유발합니다.
또한 CDN과 애플리케이션 간 Cache-Control/Surrogate-Control 헤더 일치 여부를 점검해야 합니다. 헤더 불일치는 캐시 무효화 또는 중복 재검증을 초래하며, 예시로 브라우저 캐시 600s, CDN 캐시 60s로 설정된 경우 혼선이 발생할 수 있습니다. 마지막으로 모니터링 대시보드에 캐시 적중률, revalidation 실패, P95를 추가하고 임계값 알람을 설정합니다.
- getStaticProps revalidate 값 확인
- Cache-Control/Surrogate-Control 헤더 일관성 점검
- CDN 무효화(Invalidate) 스크립트 준비 여부
- SLO: P95 응답시간 목표 및 알람 설정
- 부하 테스트 시나리오 및 결과 저장
마무리: 핵심 요약과 다음 학습 로드맵
요약하면 캐싱 전략은 성능, 데이터 신선도, 운영 복잡도 사이의 균형 문제입니다. 각 페이지의 트래픽 특성과 데이터 민감도를 기반으로 ISR, 서버 재검증, 클라이언트 캐시를 조합하면 대부분의 요구사항을 충족할 수 있습니다. 실무에서는 우선순위를 정해 파일럿 적용 후 점진 확장하는 방식이 실패 위험을 낮춥니다.
핵심 체크포인트는 다음과 같습니다: 페이지 분류(트래픽·변동성), 명확한 revalidate/TTL 정책, CDN/애플리케이션 헤더 일관성, 모니터링 및 롤백 플레이북. 예시로 대형 e커머스는 제품 상세에는 ISR(60s), 카트/결제는 클라이언트 캐시 또는 SSR을 혼합해 사용합니다. 이러한 정책을 코드와 운영 문서로 남기면 팀 간 의사결정이 빨라집니다.
추가 학습 로드맵으로는 내부 렌더링 흐름 심화, CDN 무효화 전략, 캐시 관련 메트릭 해석법을 권장합니다. 구체적으로는 Next.js의 ISR 동작 원리, Cache-Control 헤더 종류와 우선순위, 실제 트래픽을 기반으로 한 부하 테스트 설계법을 단계적으로 학습하세요. 각 항목은 실무 적용 시 곧바로 유용한 지식입니다.
다음 단계로는 팀 내 가이드라인을 만들고 한 달 단위로 정책을 재검토하는 주기를 권합니다. 운영 초기에는 매주 캐시 적중률과 revalidation 실패를 점검하고, 안정화되면 월간 검토로 전환합니다. 이 과정을 통해 점진적으로 최적값을 찾을 수 있습니다.
추가 학습 항목(클릭하면 펼침)
1. ISR 내부 재검증 로직과 race condition 처리 방법 학습
2. CDN별 무효화 API 사용법 및 비용 최적화 전략
3. SWR/React Query를 이용한 클라이언트 캐시 패턴과 폴링 전략
4. 실제 트래픽 기반 부하 테스트 설계(시나리오별 RPS, 동시 접속자, 데이터셋)
자주 묻는 질문
Next.js에서 fetch와 전통적인 fetch API의 차이는 무엇인가요?
기본적으로 Next.js 환경에서는 fetch가 서버 측에서 실행될 수 있고, 프레임워크가 제공하는 cache/revalidate 옵션을 통해 추가 제어가 가능합니다. 전통적 fetch보다 서버·클라이언트 컨텍스트를 의식해야 합니다.
revalidate를 0으로 설정하면 어떤 결과가 나오나요?
revalidate: 0은 매 요청마다 재검증을 시도하는 동작과 유사해 최신성을 우선시하지만, 서버 부하가 증가할 수 있으니 주의해야 합니다.
SSR(서버 렌더링)에서도 클라이언트 캐시가 도움이 되나요?
초기 로드와 SEO엔 SSR이 유리하지만, 이후 사용자 상호작용에서 클라이언트 캐시를 병행하면 UX 개선에 도움이 됩니다.
Next.js에서 캐시 무효화(롤백)를 어떻게 관리하나요?
캐시 무효화는 revalidate 값 조정, 빌드 재배포 또는 CDN 무효화 API를 통해 관리할 수 있으며 운영 플로우에 맞춘 정책이 필요합니다.
작은 프로젝트에서는 어떤 전략을 권장하나요?
작은 서비스는 복잡한 분산 캐시 대신 간단한 revalidate 설정과 서버 중심의 fetch로 시작해, 필요 시 클라이언트 캐시를 도입하는 것이 유지보수에 유리합니다.
fetch 호출 오류 시 권장되는 처리 패턴은?
에러 핸들링을 일관되게 적용하고, 서버 컴포넌트에서는 안정적인 대체 UI를 렌더링하며 로그와 재시도 정책을 설정하는 것이 좋습니다.
App Router에서 데이터 패칭과 상태 관리를 함께 쓰려면?
데이터는 서버 컴포넌트에서 패칭하고, 클라이언트 상태(로컬 인터랙션)는 별도의 상태 관리 툴이나 React 상태로 처리해 역할을 분리하는 방식이 권장됩니다.
Next.js에서 TypeScript를 사용하는 방법은?
Next.js는 TypeScript를 기본적으로 지원하며, 프로젝트 생성 시 TypeScript 템플릿을 선택하면 자동으로 설정됩니다. 또한, tsconfig.json 파일을 통해 추가 설정이 가능합니다.