avatar
Ganymedian

NextJS 15 ‘use cache’

2 months ago
·
4 min read

NextJS 15 ‘use cache’

NextJS 15 에서, fetch 를 이전 버전처럼 사용하면 에러가 발생하는데요..

NextJS 15 버전 부터는 fetch 의 캐시 정책을 명시적으로 표현해줘야만 합니다.

이 때 ‘use cache’ 가 사용됩니다.

.

fetch 모듈에 대해서, 데이터를 캐싱 할 것인가 아닌가에 따라 두가지 구현 방식으로 갈라집니다.

  1. fresh data for every request : <Suspense>

  2. cached data : 'use cache'

.

.

Fresh Data for every request

모든 요청에서 fresh data 를 받아와야 할 때는, 해당 컴포넌트를 Suspense 로 감싸줍니다.

// fresh data for EVERY requests..
// 이제 Next 가 자체적으로 캐시를 오버라이드하지 않는다. fetch 는 캐시되지 않는다.
export function Notice() {
  const data = fetch(...)
  return (...data)
}

// 이제는 Suspense 가 없으면 에러를 뱉는다.
export default function Page() {
  return(
    <Suspense fallback={...loading}>
      <Notice />
        {... some other Data}
    </Suspense>
  )
}

.

.

Cached Data

Cache 와 Static Yuji 가 필요할 때, 'use cache' 를 선언주고 Suspense 를 제거합니다.

// Cache 해야 할 때
'use cache'

// 'use cache' 디렉티브에 따라 cache 는 캐싱된다. 
export function Notice() {
  const data = fetch(...)
  return (...)
}

// Notice 컴포넌트가 SSG 가 되는지는 아직 확인하지 못했다. 
export default function Page() {
  return(
    <Notice />
    (...other Data)
  )
}

SSG 같은 컴포넌트 단위의 Static-Component-Generation 과 'use cache' 의 관계와 차이를 아직 분명히 확인하지 못했습니다.

사이트 내에서 100만개의 캐시가 발생할 수도 있기 때문에, 관리를 위해선 Static Component 가 될 것 같지만, 펑션 단위의 ‘use cache’ 도 허용되는 것을 봐선 그렇지 않을 것 같기도 합니다. 때가 되면 저절로 알게 되겠죠.

.

.

Cache Handling for Route Segments

Route Segment 들은, use cache 와 Suspense 가 믹스되는 방식으로 중첩구조를 이루게 되는데, 특히 layout.tsx 에서는 use cache - Static 이 유용합니다.

// 이제 layout 은 캐싱 되고, children 에 대해 각각의 cache segment 가 할당된다.
// ContextProvider 들과 NavBar, Footer 는 Static 고정되고, 
// Navigation 은 children 내에서만 각각의 Route Segment 정책에 따라 이동하고 캐싱된다.
'use cache'
export default function RootLayout({
  children
}: Readonly<{
  children: React.ReactNode
}>) {
  return (
    <html
      lang="en"
      suppressHydrationWarning={true}>
      <body
        className={inter.className}
        suppressHydrationWarning={true}
        suppressContentEditableWarning={true}>
        <AuthProvider>
          <NavigationGuardContextProvider>
            <ThemeProvider
              defaultTheme="dark"
              storageKey="ganymedian-ui-theme">
              <RootFrame>
                <NavBar />
                <MainFrame>{children}</MainFrame>
                <Footer />
              </RootFrame>
              <Toaster />
            </ThemeProvider>
          </NavigationGuardContextProvider>
        </AuthProvider>
      </body>
    </html>
  )
}**

.

.

Cache Stale & Revalidate

이건 아직 unstable 버전이라고 합니다… Next Conf 에 납품 기일을 못 맞춘 팀이 있었나본데.. 감정이입이 되는군요.

// cacheTag : Cache Id 
// cacheLife: Cache Life for Cache Id
import { unstable_cacheTag as cacheTag, unstable-cacheLife as cacheLife } from 'next/cache'

async function getNotice() {
  'use cache'
  const data = fetch(...)

  cacheTag('cache-control-' + data.id)
  cacheLife({
    revalidate: 60,
    expire: 3600,
  stale: 10,
  })

  return ({...data})
}

export default function Page() {
  return(
    <div>
      {await getNotice()}
      (...other Data)
    </div>
  )
}

.

.

세줄 요약

  1. NextJS.15 에서 fetch 가 사용될 때, ‘use cache’ 를 명시적으로 표현해줘야 한다.

  2. Cache 하지 않을 때 : <Suspense>

  3. Cache 할 때 : 'use cache'

'use client' , 'use server' 못지 않게 'use cache' 도, 중요한 디렉티브 키워드가 되었습니다.

.

-끗-

.







....