Metadata Resolution
layout·page가 각각 export한 metadata는 루트부터 아래로 평가되어 얕은 방식으로 병합됩니다. openGraph처럼 중첩 객체를 가진 키는 한 필드만 덮어써도 객체 전체가 교체되어 앞 세그먼트의 값이 사라집니다.
- 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로 캐시하거나, 동적임을 의도적으로 표시해야 한다.
같은 그룹의 다른 시각화
RSC Streaming Waterfall
Next.js · Streaming서버 청크의 도착 시점과 브라우저 화면이 채워지는 과정을 연결합니다.
ISR Cache Lifecycle
Next.js · Caching요청 시점에 따른 HIT·STALE 응답과 백그라운드 재생성을 확인합니다.
App Router Render Tree
Next.js · RoutingURL 세그먼트와 중첩 레이아웃, 렌더 순서를 연결합니다.
Render Strategy Boundary
Next.js 16 · RenderingSSG·SSR·CSR과 정적 셸·동적 영역의 실행 위치를 비교합니다.