Next.js 15에서 fetch API 활용하는 최신 방법

Next.js 15에서 fetch API 활용하는 최신 방법
TILPosted On Apr 22, 202510 min read

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부터는 fetchnext 옵션도 함께 쓸 수 있는데요, 굉장히 강력합니다. 예를 들어 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-cacheNext.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 옵션을 설정하지 않아도 돼요.
  • revalidatecache 옵션이 모순되는 설정(예: 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-cachecache: 'no-store'를 사용해도 HMR 중에는 캐시가 유지되어서 최신 데이터가 바로바로 안 보일 수 있습니다.

하지만 실제로 페이지를 새로고침하거나 다른 경로로 이동할 때는 캐시가 깨져서 다시 최신 데이터를 가져오게 돼요.

이게 개발할 때 가끔 데이터를 바로바로 바꿔서 테스트하는 과정에서 헷갈리게 할 수 있으니 주의해야 합니다.

추가로 궁금하다면 serverComponentsHmrCache 문서도 확인해보세요!


참고로 알아두면 좋은 점

  • cache: 'no-store' 옵션은 프로덕션 환경에선 실제로 캐시를 안 해서 무조건 최신 데이터를 가져오지만,
  • 개발 모드에서만 HMR 캐시가 이를 덮어씌웁니다.
  • 이 때문에 개발 중에는 fetch 요청이 예상과 다르게 동작할 수 있으니 주의해야 해요.
  • 만약 진짜 최신 데이터를 계속 보고 싶다면, 페이지를 새로고침하거나 다른 경로로 이동하는 방법을 쓰는 게 좋습니다.

이런 Next.js 내부 동작 방식을 살펴보는 건 개발 생산성을 높이고, 예상치 못한 버그를 막는 데 큰 도움이 됩니다!

버전 히스토리

버전변경 사항
v13.0.0fetch 기능 추가됨

여기서 fetch는 데이터를 서버에서 가져올 때 자주 사용하는 기능인데, 이 버전부터 공식적으로 도입됐다는 뜻이에요. 개발할 때 API 호출이 필요하면 이 기능을 활용해보세요. 예전에는 XMLHttpRequest나 다른 라이브러리를 많이 썼는데, fetch는 Promise 기반이라 비동기 처리가 훨씬 깔끔해져서 요즘은 표준처럼 쓰이고 있답니다.