fetch
Next.js에서는 기본 웹 fetch() API를 확장해서, 서버에서 각 요청마다 고유한 지속 캐싱(persistent caching)과 재검증(revalidation) 규칙을 설정할 수 있도록 했어요.
브라우저에서는 fetch 요청 시 cache 옵션이 브라우저 HTTP 캐시와 어떻게 상호작용할지를 지정하잖아요? 그런데 Next.js의 확장된 fetch에서는 서버 사이드에서 할 때 이 cache 옵션이 프레임워크가 관리하는 지속 데이터 캐시(persistent Data Cache)와 어떻게 상호작용할지를 결정해줘요.
즉, 서버 컴포넌트 안에서 async/await와 함께 그냥 fetch를 호출해도, 이 캐시 전략들이 작동하면서 성능 향상 및 데이터 최신성을 관리해준다는 뜻이에요.
추가 설명
-
지속 데이터 캐시란?
서버에서 한 번 가져온 데이터를 일정 시간 동안 저장해서, 같은 데이터를 재요청할 때 네트워크 호출을 줄여주는 역할을 해요. 그래서 유저 입장에선 페이지가 더 빨리 로드되고, 서버 부담도 줄어들죠. -
재검증(revalidation)이 뭐예요?
캐시된 데이터가 오래되었는지 주기적으로 체크해서, 최신 데이터가 필요하면 다시 fetch를 하는 거예요. -
서버 컴포넌트에서 fetch를 쓴다?
Next.js 13부터 도입된 서버 컴포넌트 덕분에, 서버에서 비동기적으로 데이터를 패칭하고 바로 렌더링할 수 있어요. 클라이언트에서 데이터 로딩 처리하는 걸 줄일 수 있죠.
예시 코드
// 서버 컴포넌트 내에서 fetch 사용
export default async function Page() {
const res = await fetch('https://api.example.com/data', {
cache: 'force-cache' // 고정된 캐시 전략 적용
});
const data = await res.json();
return (
<div>
<h1>서버에서 가져온 데이터</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
)
}
Next.js의 fetch API 확장 덕분에 서버 쪽 데이터 요청을 더 똑똑하게 관리할 수 있으니, 다음 프로젝트에 꼭 활용해보세요!
여러분, Next.js에서 데이터를 불러오는 방법에 대해 이야기해볼게요. 위에 있는 코드를 보시면, fetch
함수로 외부 API에서 데이터를 받아와서 화면에 포스트 리스트를 렌더링하는 아주 기본적인 예제입니다.
export default async function Page() {
let data = await fetch('https://api.vercel.app/blog')
let posts = await data.json()
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
)
}
Next.js의 fetch() API 활용
Next.js는 기본적으로 웹의 fetch()
API를 확장해서 제공하는데요, 그래서 우리가 익숙한 fetch
옵션들을 그대로 사용할 수 있다는 점이 편리해요. 이번에 살펴볼 옵션 중 하나가 cache
옵션입니다.
options.cache
cache
옵션은 데이터를 어떻게 캐싱할지를 결정하는 역할을 해요. 예를 들어, 기본적으로는 서버 컴포넌트에서 데이터를 패칭할 때 cache
가 적용되어, 다음에 같은 요청이 오면 캐시된 데이터를 바로 사용할 수 있도록 돼 있죠. 이걸 조절하면, 실시간 데이터가 중요하거나, 너무 자주 데이터를 갱신할 필요가 있을 때 유용해요.
"default"
: 기본 캐싱 정책을 따릅니다."no-cache"
: 매번 네트워크에서 새 데이터를 받아옵니다."force-cache"
: 캐시된 데이터만 사용하고 네트워크 요청은 안 합니다."only-if-cached"
: 캐시된 데이터가 없으면 실패합니다.
예를 들어, 이렇게 쓸 수 있어요:
let data = await fetch('https://api.vercel.app/blog', { cache: 'no-cache' })
이렇게 하면 무조건 최신 데이터를 받아오기 때문에, 실시간 뉴스나 가격 정보처럼 자주 업데이트되는 데이터에 적합합니다.
한 가지 꿀팁!
Next.js 13부터는 fetch
에 next
옵션도 함께 쓸 수 있는데요, 굉장히 강력합니다. 예를 들어 next: { revalidate: 10 }
옵션을 넣으면, 데이터를 받아와서 10초마다 캐시를 리프레시하도록 할 수 있어요. 이렇게 하면 서버 부하도 줄이고, 사용자는 어느 정도 최신 데이터를 볼 수 있죠.
let data = await fetch('https://api.vercel.app/blog', {
next: { revalidate: 10 }
})
한마디로, 여러분 프로젝트 상황에 맞게 캐시 전략을 유연하게 조절해 보세요. 그럼 데이터 패칭도 똑똑하게 할 수 있답니다!
Next.js에서 요청이 데이터 캐시와 어떻게 상호작용할지 설정하는 방법에 대해 설명해드릴게요.
fetch(`https://...`, { cache: 'force-cache' | 'no-store' })
여기서 cache 옵션은 세 가지 주요 상태가 있어요:
옵션 | 동작 설명 |
---|---|
auto (기본값) | 개발 환경에서는 매 요청마다 원격 서버에서 데이터를 가져와요. 하지만 빌드 시점에 페이지가 정적으로 사전 렌더링되면 그때 한 번만 가져와요. 그리고 동적 API가 감지되면 매 요청마다 데이터를 가져오죠. |
no-store | 동적 API 여부와 상관없이 항상 매 요청마다 원격 서버에서 데이터를 가져와요. 캐시를 사용하지 않는 느낌이에요. |
force-cache | Next.js의 데이터 캐시에서 일치하는 요청이 있는지 찾아요. ‘신선한’ 캐시가 있으면 캐시에서 바로 반환하고, 없거나 오래된 캐시라면 원격 서버에서 새로 데이터를 받아와 캐시를 업데이트해요. |
추가 꿀팁!
- 캐시가 ‘신선한(fresh)’하다는 말은 캐시된 데이터가 아직 유효하다는 뜻이에요. 이를 판단하는 기준은 Next.js 내부 정책이나
revalidate
옵션에 따라 달라집니다. force-cache
를 사용하면 빌드 시점의 데이터를 최대한 활용하면서도, 변경사항이 있을 때만 서버에서 최신 데이터를 받을 수 있어서 효율적이에요.- 개발 중에는 기본
auto
모드가 편리하지만, 프로덕션 환경에서는 상황에 맞게no-store
(실시간 업데이트 필요 시)나force-cache
(최소한의 요청으로 성능 최적화 시)를 선택하는 게 좋아요.
options.next.revalidate
이 옵션은 캐시를 갱신하는 주기를 설정할 때 쓰입니다. 예를 들어,
fetch('https://...', { next: { revalidate: 60 } })
이렇게 설정하면, 캐시된 데이터가 60초가 지나면 다음 요청 때 새로 갱신해요. 다시 말해, 1분마다 데이터를 새로고침하는 것과 같죠.
이걸 적절히 활용하면 새로 고침의 빈도와 SEO 최적화를 균형 있게 맞출 수 있습니다.
Next.js의 데이터 캐시는 페이지 성능과 사용자 경험에 큰 영향을 주니, 개발 환경과 서비스 특성에 맞게 잘 설정해 보세요!
fetch 함수에 next: { revalidate: ... }
옵션을 주면 리소스의 캐시 수명을 초 단위로 설정할 수 있어요. 쉽게 말해, 캐시가 얼마 동안 유지될지 정하는 거죠. 이 옵션에 따라 캐싱 동작이 달라집니다.
revalidate 값 | 의미 |
---|---|
false | 리소스를 무한정 캐시해요. (사실상 revalidate: Infinity와 같아요.) HTTP 캐시는 오랫동안 쓰다가 오래된 캐시를 지울 순 있지만, 기본적으로 무제한으로 저장합니다. |
0 | 캐시를 절대 하지 않아요. 항상 리소스를 새롭게 받아옵니다. |
number | 숫자(초)만큼 캐시 생명주기를 정해요. 예를 들어 60이면 60초간 캐시 유지. |
좀 더 알아두면 좋은 점
- 특정 fetch 요청에서 설정한
revalidate
값이 라우트(route) 기본 값보다 작으면, 라우트 전체의 리밸리데이트 간격도 그만큼 줄어듭니다. - 같은 URL을 가진 두 개의 fetch 요청이 각각 다른
revalidate
값을 가지고 있다면, 더 짧은 시간(낮은 값)이 적용됩니다. revalidate
를 숫자로 주면 따로cache
옵션을 설정하지 않아도 돼요.revalidate
와cache
옵션이 모순되는 설정(예:revalidate: 3600
인데cache: 'no-store'
)을 하면 에러가 발생해요.
참고로,
이 옵션은 Next.js에서 제공하는 기능으로, 서버 측 데이터 패칭 시 자동으로 ISR(Incremental Static Regeneration)을 조절하는데 유용합니다. 개발할 때 캐시 정책을 유연하게 조절하면, 페이지 성능과 최신성 사이에서 좋은 균형을 맞출 수 있어요.
혹시 어떻게 쓰는지 구체적인 예시가 궁금하다면 알려주세요!
options.next.tags
fetch(`https://...`, { next: { tags: ['collection'] } })
options.next.tags
는 요청에 캐시 태그(cache tags)를 설정하는 옵션이에요. 캐시 태그를 지정해두면, 나중에 revalidateTag
API를 사용해서 해당 태그가 붙은 데이터만 선택적으로 갱신할 수 있답니다. 이렇게 하면 불필요하게 전체 데이터를 다시 받아오지 않아도 되니까 성능 최적화에 큰 도움이 되죠.
- 태그 길이 제한: 각 태그는 최대 256자까지만 작성할 수 있어요.
- 태그 개수 제한: 한 요청당 최대 128개의 태그를 설정할 수 있어요.
추가 팁!
revalidateTag
를 사용하면 페이지나 일부 컴포넌트에서 특정 태그를 기반으로 데이터를 갱신할 수 있어서 리얼타임 데이터 반영이나, 변경이 잦은 부분만 업데이트할 때 매우 유용해요.
예를 들어, 쇼핑몰에서 ‘상품 컬렉션(collection)’ 태그를 붙인 데이터만 따로 갱신하고 싶을 때 편리하겠죠? 커스텀 태그를 잘 활용해서 앱 성능과 사용자 경험을 한층 개선해 보세요!
문제 해결 (Troubleshooting)
문제 상황 | 해결 방법 |
---|---|
태그가 너무 길 때 | 태그 길이를 256자 이내로 줄이세요. |
태그 개수가 128개를 초과할 때 | 필요 없는 태그를 제거하거나 그룹화하세요. |
데이터가 갱신되지 않을 때 | revalidateTag 가 올바르게 호출되었는지 확인하세요. |
캐시가 정상 동작하지 않을 때 | fetch 옵션과 캐시 정책을 다시 점검해보세요. |
혹시 캐시 관련해서 더 궁금한 점이나, 특정 상황에서 어떻게 활용하면 좋은지 알고 싶다면 언제든 질문해 주세요!
Fetch 기본 자동 no-store와 캐시: no-store
가 개발 환경에서 최신 데이터를 보여주지 않는 이유
Next.js에서 개발할 때, 특히 Server Components를 사용할 때 조금 특이한 캐싱 동작이 있어요. 바로 HMR(Hot Module Replacement) 과정에서 fetch 응답을 캐시에 저장한다는 점입니다. 이 덕분에 빠른 응답 속도와 함께, API 호출 비용도 아낄 수 있죠.
그런데 여기서 중요한 점! HMR 캐시는 기본적으로 모든 fetch 요청에 적용되는데, 심지어 cache: 'no-store'
옵션을 넣어도 마찬가지라는 거예요. 즉, 기본값인 no-cache
나 cache: 'no-store'
를 사용해도 HMR 중에는 캐시가 유지되어서 최신 데이터가 바로바로 안 보일 수 있습니다.
하지만 실제로 페이지를 새로고침하거나 다른 경로로 이동할 때는 캐시가 깨져서 다시 최신 데이터를 가져오게 돼요.
이게 개발할 때 가끔 데이터를 바로바로 바꿔서 테스트하는 과정에서 헷갈리게 할 수 있으니 주의해야 합니다.
추가로 궁금하다면 serverComponentsHmrCache 문서도 확인해보세요!
참고로 알아두면 좋은 점
cache: 'no-store'
옵션은 프로덕션 환경에선 실제로 캐시를 안 해서 무조건 최신 데이터를 가져오지만,- 개발 모드에서만 HMR 캐시가 이를 덮어씌웁니다.
- 이 때문에 개발 중에는 fetch 요청이 예상과 다르게 동작할 수 있으니 주의해야 해요.
- 만약 진짜 최신 데이터를 계속 보고 싶다면, 페이지를 새로고침하거나 다른 경로로 이동하는 방법을 쓰는 게 좋습니다.
이런 Next.js 내부 동작 방식을 살펴보는 건 개발 생산성을 높이고, 예상치 못한 버그를 막는 데 큰 도움이 됩니다!
버전 히스토리
버전 | 변경 사항 |
---|---|
v13.0.0 | fetch 기능 추가됨 |
여기서 fetch
는 데이터를 서버에서 가져올 때 자주 사용하는 기능인데, 이 버전부터 공식적으로 도입됐다는 뜻이에요. 개발할 때 API 호출이 필요하면 이 기능을 활용해보세요. 예전에는 XMLHttpRequest나 다른 라이브러리를 많이 썼는데, fetch
는 Promise 기반이라 비동기 처리가 훨씬 깔끔해져서 요즘은 표준처럼 쓰이고 있답니다.