본문 바로가기
✨FRONTEND/📍Next.js

Next.js App Router에서 React Query 쓰면서 metadata 쓰기

by 짱돌보리 2025. 9. 6.
728x90

Next.js App Router에서 React Query 쓰면서 metadata 쓰기

🚨 문제 상황

QueryClientProvider는 클라이언트 컴포넌트에서만 사용할 수 있다. 그런데 layout.tsx는 기본적으로 서버 컴포넌트임!

 

그래서 layout 최상단에 use client를 붙이면… 서버 전용 기능인 metadata가 에러 나면서 작동 안 함 😅

🧐 왜 metadata는 서버에서만 되냐?

Next.js에서 metadata는 서버 컴포넌트에서만 평가되는 정적 정보다.
HTML <head>에 들어가는 title, description, og:image 같은 정보!!

 

서버에서 미리 렌더링되어 SEO, SSR, SSG 등에 활용된다.

 

즉, 클라이언트에서 평가하면 안 되는 값이기 때문에
use client를 붙이면 서버 컴포넌트로 취급되지 않아서 metadata를 못 쓴다!!

🛠️ 해결 방법: 컴포넌트 분리

1️⃣ React Query Provider만 클라이언트로 분리

  'use client'

import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { useState } from 'react'

export default function Providers({ children }: { children: React.ReactNode }) {
  const [queryClient] = useState(() => new QueryClient())
  return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
}

 

2️⃣ layout.tsx는 서버 컴포넌트 그대로 유지

  import type { Metadata } from 'next'
import '@/app/_styles/globals.css'
import Providers from './providers'
import Toast from './_components/Toast'

export const metadata: Metadata = {
  title: 'Clovie',
  description: '글 작성과 활동을 통해 ‘네잎클로버 등급’을 올리는 블로그 서비스',
}

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="ko">
      <body>
        <Providers>
          <main>{children}</main>
        </Providers>
        <Toast />
      </body>
    </html>
  )
}
  • layout은 서버 컴포넌트라 metadata 문제 없음 ✅
  • React Query Provider는 클라이언트 컴포넌트라 상태 관리, 캐싱 문제 없음 ✅
  • App Router의 서버/클라이언트 분리 철학을 지킬 수 있음 ✨