hafuture

Next.js 다국어 SEO 구현 가이드

Next.js App Router에서 하드코딩 없이 next-intl 라이브러리를 활용해 SEO에 최적화된 다국어 웹사이트를 구축하는 가이드입니다.

Next.jsi18nnext-intlSEOTechnical

다국어 웹사이트를 운영할 때 가장 흔히 저지르는 실수가 있습니다. 바로 메타데이터를 영어로만 하드코딩하는 것입니다. 오늘은 이 문제를 next-intl 라이브러리로 어떻게 깔끔하게 해결할 수 있는지 공유합니다.

문제 상황: 영어로 고정된 메타데이터

hafuture는 한국어, 영어, 일본어를 지원하는 글로벌 서비스입니다. 그런데 어느 날 Google Search Console을 확인하던 중 이상한 점을 발견했습니다. 한국어 페이지(/ko)에 접속해도 HTML의 <title><meta description>이 영어로 표시되고 있었던 것입니다.

<!-

- /ko 페이지인데 영어? -->
<title>Free Online Tools for Text, PDF & Images | Hafuture</title>
<meta name="description" content="Fast, private, browser-based tools..." />

이는 분명히 SEO에 악영향을 미치며, 한국어 검색 결과에서 불이익을 받을 수 있습니다.

원인: generateMetadata에서 하드코딩

문제의 원인은 layout.tsxgenerateMetadata 함수에 있었습니다:

// ❌ 잘못된 방식: 하드코딩
export async function generateMetadata(): Promise<Metadata> {
  return {
    title: {
      default: "Free Online Tools for Text, PDF & Images | Hafuture",
      template: "%s | Hafuture",
    },
    description: "Fast, private, browser-based tools...",
  };
}

아무리 next-intl을 사용하고 있어도, 메타데이터 부분에서 번역 함수를 호출하지 않으면 정적인 영어 텍스트가 그대로 출력됩니다.

해결책: getTranslations 사용

next-intl은 서버 컴포넌트에서 사용할 수 있는 getTranslations 함수를 제공합니다. 이를 활용하면 generateMetadata에서도 동적으로 번역된 메타데이터를 생성할 수 있습니다.

1단계: 메시지 파일에 Metadata 섹션 추가

// messages/ko.json
{
  "Metadata": {
    "title": "텍스트, PDF, 이미지를 위한 무료 온라인 도구 | Hafuture",
    "description": "빠르고 안전한 브라우저 기반 도구입니다...",
    "ogTitle": "텍스트, PDF, 이미지를 위한 무료 온라인 도구 | Hafuture"
  }
}

2단계: generateMetadata에서 getTranslations 호출

// ✅ 올바른 방식: next-intl 사용
import { getTranslations } from "next-intl/server";

export async function generateMetadata(
  { params }: { params: Promise<{ locale: string }> }
): Promise<Metadata> {
  const { locale } = await params;
  const t = await getTranslations({ locale, namespace: "Metadata" });

  return {
    title: {
      default: t("title"),
      template: t("titleTemplate"),
    },
    description: t("description"),
    openGraph: {
      title: t("ogTitle"),
      description: t("ogDescription"),
    },
  };
}

하드코딩 vs next-intl 비교

비교 항목 하드코딩 (Custom) next-intl 라이브러리
최종 HTML 결과 구현 실력에 따라 다름 완벽한 결과 보장
구현 난이도 높음 (서버/클라이언트 동기화 필요) 낮음 (Next.js 전용 설계)
실수 가능성 높음 (메타데이터 누락 등) 낮음 (정해진 패턴)
SEO 영향 불안정 안정적으로 높은 점수
유지보수 어려움 쉬움 (JSON 파일만 수정)

결과 확인

수정 후 각 언어별 페이지의 HTML을 확인해보면:

한국어 (/ko):

<title>텍스트, PDF, 이미지를 위한 무료 온라인 도구 | Hafuture</title>
<meta property="og:locale" content="ko_KR" />

일본어 (/ja):

<title>テキスト、PDF、画像のための無料オンラインツール | Hafuture</title>
<meta property="og:locale" content="ja_JP" />

이제 검색 엔진이 각 언어에 맞는 메타데이터를 정확히 인식할 수 있습니다!

관련 도구 써보기

다국어 지원으로 더욱 똑똑해진 Hafuture의 도구들을 만나보세요:

결론

Next.js App Router를 사용하고 있다면, SEO 실수를 방지하고 유지보수를 편하게 하기 위해 next-intl 도입을 강력하게 추천합니다. 특히 generateMetadata에서 getTranslations를 사용하면 "제목/설명 번역 안 됨" 문제를 가장 깔끔하게 해결할 수 있습니다.

다국어 지원은 단순히 텍스트를 바꾸는 것이 아닙니다. 사용자의 언어와 문화를 존중하는 첫걸음이니까요!

감사합니다. 🌏