Next.js · SEO

Metadata Resolution

layout·page가 각각 export한 metadata는 루트부터 아래로 평가되어 얕은 방식으로 병합됩니다. openGraph처럼 중첩 객체를 가진 키는 한 필드만 덮어써도 객체 전체가 교체되어 앞 세그먼트의 값이 사라집니다.

평가 0%
스트리밍 켜짐—초기 UI를 먼저 보내고 generateMetadata 결과는 <body>에 추가됩니다. JS를 실행하지 못하는 봇은 여전히 기다린 뒤 <head>에서 받습니다.
  • Root Layoutapp/layout.tsx

    루트 레이아웃이 사이트 전역 기본값을 잡는다. openGraph에 title·description·siteName 세 필드를 모두 채워 두었다.

  • Blog Layoutapp/blog/layout.tsx

    여기가 함정이다. openGraph에 title 하나만 다시 썼는데 얕은 병합이라 객체가 통째로 교체되어, 루트가 넣어 둔 description·siteName이 사라진다. 공유하려면 그 필드를 여기서 다시 써야 한다.

  • Post Pageapp/blog/[slug]/page.tsx

    generateMetadata로 글 데이터를 fetch해 채운다. async 함수이므로 스트리밍 대상이 되며, 마지막 세그먼트라 title·description의 최종 값이 된다.

  • 얕은 병합generate-metadata.md:1328-1330

    세그먼트별 metadata는 root → 아래 순서로 평가되고 얕게 병합된다. 같은 키는 나중 것이 앞의 것을 교체한다. openGraph·robots처럼 중첩 필드를 가진 키는 부분 병합이 아니라 객체 전체가 바뀐다.

  • 스트리밍 메타데이터generate-metadata.md:1222-1232

    generateMetadata가 끝나기를 기다리지 않고 초기 UI를 먼저 보낸다. 준비된 태그는 <head>가 아니라 <body>에 추가된다. JS를 실행하는 봇(Googlebot)은 정상적으로 인식하지만, HTML-limited bots(facebookexternalhit 등)에서는 여전히 대기한 뒤 <head>에 넣는다. htmlLimitedBots로 조절한다.

  • Next 16 — Cache Components와 함께 쓸 때generate-metadata.md "With Cache Components"

    cacheComponents가 켜져 있으면 generateMetadata도 다른 컴포넌트와 같은 규칙을 따른다. 런타임 데이터(cookies, headers, params, searchParams)나 캐시되지 않은 fetch를 쓰면 요청 시로 미뤄진다. 페이지의 나머지가 완전히 프리렌더 가능한데 메타데이터만 런타임을 타면 Next.js가 명시적 선택을 요구하는 에러를 낸다 — 데이터를 use cache로 캐시하거나, 동적임을 의도적으로 표시해야 한다.