joooii

[Next.js] 메타데이터 적용이 안되는 문제 해결 (ft. Streaming Metadata, Lighthouse) 본문

트러블슈팅

[Next.js] 메타데이터 적용이 안되는 문제 해결 (ft. Streaming Metadata, Lighthouse)

joooii 2025. 12. 4. 00:55

🚧 문제 상황

⚙️ 발생한 환경 및 프로그램

`Next ^15.4.4`

 

 

🎯 문제 상황 정의

CERT-IS 프로젝트의 Lighthouse 성능을 개선하기 위해 리팩토링을 진행하는데, SEO 항목의 점수가 계속 90점이 나왔다.

그러나 이미 우리 프로젝트에서 `layout.tsx`, `page.tsx`에 이미 메타데이터를 구현한 상태였다.

개발자도구 - [Elements] 탭에서 meta 태그가 정상적으로 보였다. 

그럼에도 불구하고 Lighthouse는 meta description이 없다고 판단하고 있었다.

 

 

🔥 발생한 문제 및 에러

`Document does not have a meta description`

 


🧭 해결방안 및 과정

💼 해결하기 위한 노력 및 시행착오

1️⃣ `/app/layout.tsx` , `/app/domain/layout.tsx`에서 metadata 제거 후 테스트

→ 변화 없음

 

2️⃣ `/app/domain/page.tsx`의 metadata 주입 방식(generateMetadata) 점검

→ 변화 없음

 

3️⃣ view-source 점검

→ meta가 head 태그가 아닌 body 태그 중간에 삽입되는 것을 발견

head 태그 내 메타데이터

 

body 태그 내 메타데이터

 

4️⃣ `/domain/page.tsx` 및 동적 라우트(`/[id]`)에서만 현상 발생

→ 정적 페이지에서는 문제 없음

 

⇒ 이 지점에서 문제의 원인이 동적 페이지 렌더링 방식이라고 추정하였다.

 

 

💡 근본 원인 파악

이런 문제가 발생한 블로그나 자료가 있는지 확인하고자 GPT에게 구글링하기 위한 단어를 추출하여 streaming metadata로 검색해보니 이와 동일한 문제가 발생한 블로그를 찾을 수 있었다.

 

이 문제의 원인은 Next.js v15.2+ 버전에서 도입된 Streaming metadata 였다.

 

 

✔ Streaming Metadata란?

Streaming Metadata는 Next.js가 `generateMetadata()`가 async 또는 Promise를 반환하는 경우, generateMetadata를 기다리지 않고 초기 UI를 먼저 브라우저로 전달하고 메타데이터는 `<body>` 내부에 스트리밍 패치로 나중에 삽입하는 기능이다.

 

JS 실행이 가능한 봇(ex. Googlebot, 브라우저)최종적으로 DOM을 읽기 때문에 body 패치로 들어간 metadata도 문제 없이 해석이 가능하다. 그렇기에 [Elements] 탭에서는 meta 태그가 보인 것이었다.

 

반면, JS를 실행할 수 없는 HTML-limited bot(ex. 페이스북/카카오/트위터 미리보기용 크롤러)은 기존 방식대로 메타데이터가 렌더링을 블로킹하며, 기존처럼 `<head>`에 정상적으로 포함되어 제공한다.

 

그러나 Lighthouse는 JS 실행 이전의 "초기 HTML(view-source)" 기준으로 검사하기 때문에 meta description 없음으로 잘못 판단한 것이다.

 

즉, Next.js의 Streaming Metadata와 Lighthouse의 초기 HTML 검사 방식이 충돌한 것하여 문제가 발생한 것이다.

 

 

💫 최종 해결 방법

Next 공식 문서에 따라 Streaming Metadata를 비활성화하여 모든 metadata를 `<head>`에 정적으로 삽입하도록 강제하였다.

// next.config.ts 설정

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  // 모든 User-Agent를 HTML-limited bot으로 간주하여
  // streaming metadata를 비활성화함
  htmlLimitedBots: /.*/,
};

export default nextConfig;

 

결과적으로 `<head>` 에 metadata가 즉시 렌더링되면서 Lighthouse - SEO 점수가 100점으로 개선되었다.


👾 결론

역시 문제의 본질은 공식 문서에 있다는 것을 또 뼈저리게 깨달았다. 이 문제를 해결하기 위해 이틀 반동안 메타데이터 코드(만..)를 들여다보면서 여러 시도를 해봤는데도 해결 방법을 찾을 수가 없었다. 그런데 단 1줄의 코드만으로 문제를 해결해버리니 .. 사실 이번에도 공식문서를 봤었는데, 공식문서 한글 번역본만 봤기에 해당 문제를 해결할 수가 없던 것이었다.

 

공식문서가 괜히 공식문서가 아닌데 영어가 두려워 미련한 방법을 선택해 시간을 허비한 것 같아 아쉬운 마음이 크다. 이번 트러블슈팅을 계기로 공식문서를 습관화하는 버릇을 확실하게 들여놔야겠다는 생각이 들었다.


📚 참고자료

 

Functions: generateMetadata | Next.js

Learn how to add Metadata to your Next.js application for improved search engine optimization (SEO) and web shareability.

nextjs.org

 

메타데이터 적용 안되는 문제 분석 (feat. streaming metadata)

Next.js 15 에서 메타데이터가 제대로 적용되지 않는 문제가 발생했다. 아무래도 15.2 에서 추가된 streaming metadata 가 원인인 것 같은데, 정확한 원인을 찾아보고, 실수로라도 발생하지 않도록 해결해

monognuisy.vercel.app