← 전체 글로 돌아가기

Next.js

Next.js에서 canonical URL이 소셜 미리보기를 망칠 때

Next.js의 canonical URL 설정이 잘못돼서 SNS 공유 시 미리보기가 깨지는 경우와 디버깅 과정을 다룬다.

블로그 글이나 상품 페이지를 카카오톡이나 페이스북에 공유할 때 미리보기가 제목, 이미지, 설명 대신 빈 화면이나 이전 페이지의 정보를 보여주는 일이 있다. 대부분은 canonical URL이 잘못 설정되거나 메타데이터가 제대로 렌더링되지 않았기 때문이다.

현재 상황 파악: 소셜 미리보기 검사

먼저 SNS에서 실제로 뭘 보는지 확인해야 한다:

# 네이버 SNS 정보 조회
curl -i 'https://yoursite.com/post/some-post-id'

# 응답 헤더에서 OpenGraph 메타 태그를 확인
curl -s 'https://yoursite.com/post/some-post-id' | grep -E 'og:|twitter:|canonical'

또는 Facebook의 공유 디버거(https://developers.facebook.com/tools/debug/)나 카카오톡의 메타 태그 검사 도구에 URL을 넣어서 어떤 정보를 읽는지 본다.

canonical URL의 역할과 주의사항

Canonical URL은 "이 페이지의 정식 주소는 이것이다"라고 검색 엔진과 SNS에 알려준다:

// pages/post/[id].js
import Head from 'next/head';

export default function Post({ post }) {
  return (
    <>
      <Head>
        <link rel="canonical" href={`https://yoursite.com/post/${post.id}`} />
        <meta property="og:url" content={`https://yoursite.com/post/${post.id}`} />
        <meta property="og:title" content={post.title} />
        <meta property="og:description" content={post.excerpt} />
        <meta property="og:image" content={post.image} />
      </Head>
      <article>{post.content}</article>
    </>
  );
}

Canonical URL과 og:url이 다르면 SNS가 혼란스러워한다.

로컬과 운영의 도메인 차이 확인

로컬에서는 http://localhost:3000이고 운영에서는 https://yoursite.com이면, 로컬 테스트할 때 미리보기가 제대로 나올 수 없다. 환경 변수로 도메인을 관리하자:

# .env.local
NEXT_PUBLIC_BASE_URL=http://localhost:3000

# .env.production
NEXT_PUBLIC_BASE_URL=https://yoursite.com

그리고 코드에서 사용:

const baseUrl = process.env.NEXT_PUBLIC_BASE_URL;

<link rel="canonical" href={`${baseUrl}/post/${post.id}`} />

동적 경로에서 URL 생성 실수

동적 라우트를 쓸 때 URL을 잘못 만드는 경우가 많다:

// ❌ 잘못된 예
const url = `/post/${id}`; // 상대 경로

// ✓ 올바른 예
const url = `${process.env.NEXT_PUBLIC_BASE_URL}/post/${id}`; // 절대 URL

SNS 플랫폼은 절대 URL을 기대한다.

빌드 후 실제 HTML 확인

Next.js의 정적 생성(Static Generation)을 쓰면, 빌드 시점에 HTML이 생성된다. 빌드 후 생성된 파일을 직접 확인해보자:

npm run build
cat .next/server/pages/post/[id].html | head -100

OG 메타 태그가 제대로 있는지 보자. 없다면 Next.js가 렌더링하지 못한 것이다.

getStaticProps와 메타데이터

SSG(정적 생성)를 쓰는 경우, getStaticProps에서 데이터를 가져온 후에야 메타데이터를 만들 수 있다:

export async function getStaticProps({ params }) {
  const post = await fetchPost(params.id);
  return {
    props: { post },
    revalidate: 60 // ISR: 60초마다 재검증
  };
}

export default function Post({ post }) {
  return (
    <Head>
      <meta property="og:title" content={post.title} />
      <meta property="og:description" content={post.excerpt} />
      <meta property="og:image" content={post.image} />
      <meta property="og:url" content={`https://yoursite.com/post/${post.id}`} />
    </Head>
  );
}

최종 검증: 배포 후 확인

배포 후 실제 URL을 검사 도구에 넣어서 확인하자:

# 1. 메타 태그 직접 확인
curl -s 'https://yoursite.com/post/abc123' | grep -A 5 'og:'

# 2. OpenGraph 이미지가 실제로 접근 가능한지
curl -i 'https://yoursite.com/images/post-image.jpg'

# 3. SNS 공유 디버거로 재크롤링
# Facebook: https://developers.facebook.com/tools/debug/
# 네이버: https://searchadvisor.naver.com/tools/sitecheck

Canonical URL이 정확하고 모든 메타 태그가 잘 렌더링되면, SNS 미리보기도 자동으로 개선된다. 특히 이미지 URL은 절대 경로여야 SNS가 인식할 수 있다.