Docker
Next.js에서 metadataBase를 빼먹고 공유 이미지 URL이 깨진 기록
배포 후 OG 이미지가 상대 경로로 만들어진 원인과 확인 기준을 짧게 정리했다.
이상했던 지점
게시글 상세 페이지에는 opengraph-image.png가 있었고 브라우저에서 직접 열면 이미지도 보였다. 그런데 메신저 미리보기에서는 이미지가 빠졌다. HTML을 열어 보니 og:image가 절대 URL이 아니라 상대 경로처럼 만들어져 있었다.
<meta property="og:image" content="/posts/example/opengraph-image.png">
로컬에서는 대충 넘어갔지만, 외부 크롤러는 이 주소를 어떤 도메인 기준으로 해석해야 하는지 분명하지 않았다. 특히 배포 주소와 프리뷰 주소가 섞이는 환경에서는 더 헷갈렸다.
설정을 어디에 둘지 정했다
App Router에서 메타데이터를 만들 때 기준 URL을 한 곳에 두기로 했다. 나는 루트 레이아웃 쪽에 metadataBase를 넣고, 환경 변수로 운영 도메인을 받게 했다.
import type { Metadata } from 'next'
export const metadata: Metadata = {
metadataBase: new URL(process.env.NEXT_PUBLIC_SITE_URL ?? 'https://example.com'),
title: {
default: 'My Blog',
template: '%s | My Blog',
},
}
그리고 페이지별 메타데이터에서는 경로만 넘겼다.
export async function generateMetadata(): Promise<Metadata> {
return {
openGraph: {
images: ['/og/default.png'],
},
}
}
이렇게 하면 최종 HTML에는 기준 URL이 붙은 주소가 만들어진다.
내가 한 번 더 확인한 것
이미지를 고친 뒤 바로 메신저에서 확인했는데 계속 예전 결과가 나왔다. 이때 코드가 틀린 줄 알고 다시 뒤집을 뻔했다. 실제로는 미리보기 캐시가 남아 있었다. 그래서 먼저 HTML 원문을 확인하고, 그 다음 각 서비스의 캐시 갱신 도구나 새 URL로 확인했다.
curl -s https://example.com/posts/sample | grep -i 'og:image'
브라우저 화면보다 HTML의 메타 태그를 먼저 보는 편이 빠르다. 화면에서 이미지가 보이는 것과 크롤러가 읽는 URL이 올바른 것은 다른 문제였다.
짧은 점검표
- 운영 환경의
NEXT_PUBLIC_SITE_URL값이 실제 공개 도메인인지 본다. metadataBase가 루트 또는 공통 설정에 있는지 확인한다.og:image결과가https://로 시작하는지 HTML에서 직접 본다.- 이미지 응답이 200이고 로그인 없이 접근되는지 확인한다.
- 메신저 캐시 때문에 수정 결과가 늦게 보일 수 있음을 따로 기록한다.
남은 메모
SEO나 공유 이미지는 코드가 맞아도 바로 체감되지 않을 때가 많다. 그래서 이제는 “화면에서 보인다” 대신 “크롤러가 읽을 HTML에 절대 URL로 들어갔다”를 완료 기준으로 잡는다.