Next.js 다국어 SEO 가이드: App Router에서 글로벌 랜딩·SaaS 화면을 안전하게 운영하는 구조

요약: Next.js 다국어 SEO는 번역이 아니라 URL·검색·운영 구조다
결론부터 말하면, Next.js App Router에서 다국어 SEO를 안전하게 운영하려면 ‘한국어 문구를 영어로 바꾸는 작업’보다 먼저 세 가지를 고정해야 한다. 첫째, 언어별 URL 정책을 정한다. 둘째, 같은 라우팅 표에서 canonical, hreflang, sitemap, language switcher를 생성한다. 셋째, 번역 파일과 CMS 콘텐츠의 책임 범위를 분리한다. 이 세 가지가 없으면 초기에는 빨리 출시되는 것처럼 보여도, 몇 달 뒤 URL 변경, 중복 콘텐츠, 누락된 메타데이터, 번역 누락, 캐시 무효화 오류가 동시에 발생한다.
Google은 언어별 콘텐츠가 있다면 쿠키나 브라우저 설정만으로 페이지 내용을 바꾸기보다 언어별로 다른 URL을 제공하고, hreflang이나 sitemap으로 변형 페이지를 명시하는 방식을 권장한다. Next.js App Router 문서도 app/[lang] 또는 app/[locale] 같은 동적 세그먼트를 통해 locale 값을 layout과 page에 전달하는 구조를 안내한다. ([developers.google.com](https://developers.google.com/search/docs/advanced/crawling/managing-multi-regional-sites))
실무 원칙은 간단하다. 검색으로 들어오는 공개 랜딩과 로그인 후 사용하는 SaaS 화면을 같은 다국어 SEO 정책으로 묶지 않는다. 랜딩은 URL·메타데이터·사이트맵이 우선이고, SaaS 화면은 사용자 언어 설정·권한·검수 가능한 번역 범위가 우선이다.
1. 먼저 정해야 할 것: 언어, 국가, 시장은 서로 다르다
다국어 프로젝트에서 첫 회의 때 가장 자주 생기는 오해는 ‘영어 페이지 하나 만들면 글로벌 대응이 끝난다’는 생각이다. SEO 관점에서는 영어라는 언어와 미국, 영국, 싱가포르 같은 시장이 다르다. 가격, 통화, 법무 문구, 고객 사례, 배송 가능 지역이 달라지면 단순 언어 번역이 아니라 지역별 페이지 운영이 된다.
| 구분 | 예시 | URL 설계 | 운영 포인트 |
|---|---|---|---|
| 언어 중심 | ko, en, ja | /ko, /en, /ja | 초기 글로벌 랜딩, B2B SaaS 소개 페이지에 적합하다. |
| 언어+국가 중심 | en-US, en-GB, ja-JP | /en-us, /en-gb | 가격, 법무, 고객 사례가 지역별로 달라질 때 검토한다. |
| 시장 중심 | 미국 사이트, 일본 사이트 | 서브도메인 또는 별도 도메인 | 현지 마케팅·운영 조직이 분리될 때 의미가 있다. |
hreflang 값은 언어 코드가 먼저 오고, 필요할 때 지역 코드를 붙인다. 국가 코드만 단독으로 쓰는 방식은 피해야 한다. 예를 들어 일본어 전체를 대상으로 하면 ja, 일본 지역의 일본어를 명시하려면 ja-JP가 자연스럽다. ([developers.google.com](https://developers.google.com/search/docs/advanced/crawling/localized-versions?hl=en&rd=1&visit_id=638854164708922959-2595562323))
2. URL 구조: /en, 루트 기본 언어, 서브도메인 중 무엇을 선택할까
URL은 다국어 SEO에서 가장 되돌리기 비싼 결정이다. 번역 품질은 나중에 개선할 수 있지만, 색인된 URL을 바꾸면 redirect, canonical, sitemap, 광고 랜딩, 백링크, 내부 링크를 모두 손봐야 한다.
| 구조 | 예시 | 장점 | 주의점 | 추천 상황 |
|---|---|---|---|---|
| 모든 언어 prefix | /ko/pricing, /en/pricing, /ja/pricing | 정책이 단순하고 hreflang, sitemap 생성이 쉽다. | 기본 언어도 prefix가 붙어 기존 루트 URL과 redirect 설계가 필요하다. | 신규 글로벌 랜딩, 새 SaaS 사이트 |
| 기본 언어는 루트 | /pricing, /en/pricing | 기존 한국어 사이트의 색인 자산을 유지하기 쉽다. | /와 /ko를 중복으로 열어두면 canonical 신호가 흔들릴 수 있다. | 이미 한국어 루트 URL이 운영 중인 팀 |
| 도메인·서브도메인 | jp.example.com, example.jp | 시장별 브랜딩, 법무, 운영 분리가 명확하다. | 인프라, 분석, 링크 자산, Search Console 관리가 늘어난다. | 현지 법인·현지 마케팅 조직이 있는 경우 |
| 쿠키·IP 기반 전환 | URL은 같고 내용만 변경 | 사용자에게는 짧아 보인다. | 검색엔진이 모든 언어 변형을 안정적으로 발견하기 어렵다. | 로그인 후 제품 UI 언어 설정 |
Google 문서는 자동 리다이렉트만으로 언어를 바꾸면 검색엔진과 사용자가 모든 언어 버전을 보지 못할 수 있다고 경고한다. 특히 Googlebot은 일반적으로 특정 Accept-Language 헤더를 보내지 않는 방식으로 크롤링하므로, 검색 유입을 기대하는 페이지는 URL로 언어가 드러나야 한다. ([developers.google.com](https://developers.google.com/search/docs/advanced/crawling/managing-multi-regional-sites))
next-intl을 쓰는 팀이라면 localePrefix: 'always', localePrefix: 'as-needed', localePrefix: 'never' 중 하나를 선택하게 된다. 기본 언어를 루트에 두는 as-needed는 마케팅 관점에서 매력적이지만, unprefixed pathname을 matcher가 감지하는지와 불필요한 기본 언어 prefix가 redirect되는지를 반드시 확인해야 한다. never는 URL이 locale별로 고유하지 않을 수 있어 alternate link를 직접 처리해야 하는 경우가 생긴다. ([next-intl.dev](https://next-intl.dev/docs/routing/configuration))

3. App Router 기본 구조: locale을 라우팅의 축으로 둔다
App Router 프로젝트에서는 언어를 화면 내부 상태로 숨기지 말고 route segment로 끌어올리는 편이 운영하기 쉽다. 예를 들어 공개 랜딩은 src/app/[locale]/(marketing), 제품 앱은 src/app/[locale]/(app), 관리자 화면은 src/app/[locale]/admin처럼 나눌 수 있다. 이때 [locale]은 SEO만을 위한 값이 아니라 서버 컴포넌트, 메타데이터, CMS 조회, 오류 메시지, 날짜·숫자 포맷의 공통 입력값이 된다.
src/i18n/routing.ts: 지원 locale, 기본 locale, URL prefix, localized pathname을 정의한다.src/app/[locale]/layout.tsx: locale 유효성을 검사하고, html lang 또는 provider를 설정한다.src/app/[locale]/(marketing)/pricing/page.tsx: 공개 색인 대상 페이지를 둔다.src/app/[locale]/(app)/dashboard/page.tsx: 로그인 후 제품 화면을 둔다.src/app/sitemap.ts: 공개 페이지와 locale별 alternate URL을 생성한다.
Next.js 문서는 locale 라우팅을 위해 특수 파일을 app/[lang] 아래에 둘 수 있고, generateStaticParams로 특정 locale 경로를 정적으로 생성할 수 있다고 설명한다. next-intl 역시 top-level [locale] 세그먼트, routing 설정, navigation wrapper, request config를 중심으로 App Router와 통합한다. ([nextjs.org](https://nextjs.org/docs/app/guides/internationalization))
Next.js 16 이후 공식 문서에서는 예전 middleware.ts 파일 관습이 proxy.ts로 변경되었다. 기존 Next.js 13~15 자료를 참고하는 팀은 문서와 저장소의 파일명이 다를 수 있으므로, 다국어 redirect와 locale negotiation 코드가 실제 실행되는 위치를 먼저 확인해야 한다. ([nextjs.org](https://nextjs.org/docs/pages/api-reference/file-conventions/proxy?utm_source=openai))
4. hreflang·canonical: 서로 다른 신호를 보내지 않는 것이 핵심이다
다국어 SEO에서 흔한 사고는 hreflang 자체를 빠뜨리는 것이 아니라, canonical, sitemap, language switcher, 내부 링크가 서로 다른 URL을 가리키는 것이다. 예를 들어 영어 가격 페이지의 canonical은 /en/pricing인데 사이트맵은 /pricing?lang=en을 제출하고, 언어 전환 버튼은 /en 홈으로만 보내면 검색엔진과 사용자 모두 같은 콘텐츠 그룹을 이해하기 어렵다.
| 항목 | 안전한 기준 | 자주 나는 실수 |
|---|---|---|
| canonical | 완전히 번역된 언어별 페이지는 대체로 자기 자신을 canonical로 둔다. | 모든 언어 페이지가 한국어 루트만 canonical로 가리킨다. |
| hreflang | 각 언어 페이지가 자기 자신과 다른 언어 버전을 모두 나열한다. | 영어 페이지는 한국어를 가리키지만 한국어 페이지는 영어를 되돌려 가리키지 않는다. |
| x-default | 언어 선택 페이지나 기본 fallback 페이지를 명확히 지정한다. | x-default를 canonical처럼 오해해 모든 URL의 대표 페이지로 사용한다. |
| sitemap | 색인 가능한 공개 URL만 넣고 alternates를 함께 생성한다. | 미번역 초안, noindex 페이지, 로그인 필요 페이지까지 포함한다. |
| 언어 전환 | 같은 콘텐츠의 다른 언어 URL로 이동한다. | 어느 페이지에서든 언어를 바꾸면 각 언어의 홈으로 이동한다. |
Google의 hreflang 가이드는 각 언어 버전이 자기 자신과 다른 모든 언어 버전을 나열해야 하며, alternate URL은 프로토콜을 포함한 완전한 URL이어야 한다고 설명한다. 또한 서로 되돌려 가리키지 않는 hreflang은 무시되거나 올바르게 해석되지 않을 수 있다. ([developers.google.com](https://developers.google.com/search/docs/advanced/crawling/localized-versions?hl=en&rd=1&visit_id=638854164708922959-2595562323))
canonical도 절대 URL 기준으로 관리하는 편이 안전하다. Google은 rel='canonical'에 상대 경로보다 절대 경로를 권장하며, sitemap과 redirect 역시 canonical 신호로 활용될 수 있다고 설명한다. Next.js의 metadataBase와 alternates.languages를 사용하면 상대 경로를 설정하더라도 최종 head에는 완전한 canonical과 hreflang URL을 출력할 수 있다. ([developers.google.com](https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls))
운영 코드에서는 다음과 같은 단일 정책이 필요하다. routing.ts에 등록된 locale과 pathname을 기준으로 Link, generateMetadata, sitemap.ts, CMS preview URL이 모두 같은 helper를 사용해야 한다. 다국어 SEO는 메타 태그를 한 번 넣는 작업이 아니라 URL 생성 규칙을 제품 전반에 공유하는 작업이다.
5. 메타데이터: generateMetadata를 페이지 데이터와 같은 소스에서 가져온다
App Router에서는 정적 메타데이터와 generateMetadata를 함께 쓸 수 있다. 페이지 제목과 설명이 locale, CMS 문서, 가격 플랜, 블로그 slug에 따라 달라진다면 generateMetadata에서 같은 데이터를 읽어오는 구조가 자연스럽다. Next.js 문서는 generateMetadata가 route params, searchParams, parent metadata를 받을 수 있고, fetch 요청은 관련 렌더링 경로에서 memoize될 수 있다고 설명한다. ([nextjs.org](https://nextjs.org/docs/app/api-reference/functions/generate-metadata))
여기서 중요한 것은 ‘본문은 CMS에서 가져오고 title은 코드에 하드코딩’하는 식의 분리 운영을 피하는 것이다. 콘텐츠 담당자가 영어 랜딩 제목을 수정했는데 본문만 바뀌고 SEO title은 그대로라면 검색 결과와 페이지 내용이 어긋난다. 반대로 모든 메타데이터를 CMS에 맡기면 미입력, 길이 초과, 중복 title을 검수하는 프로세스가 필요하다.
- 브랜드 공통 title template은 layout metadata로 둔다.
- 페이지별 title, description, OG title, OG description은 locale별 콘텐츠와 함께 관리한다.
- canonical과 hreflang은 CMS 담당자가 직접 입력하지 않고 라우팅 정책에서 생성한다.
- 미번역 페이지는 자동 fallback으로 영어를 노출할지, 404 처리할지, noindex로 둘지 미리 정한다.
- production, staging, preview의
metadataBase가 섞이지 않도록 환경 변수를 분리한다.
SEO 전반의 기본 구조를 아직 정리하지 않았다면 다국어 작업 전에 Next.js App Router SEO 기본 구조부터 점검하는 편이 좋다. 단일 언어 SEO가 불안정한 상태에서 locale만 늘리면 문제도 언어 수만큼 늘어난다.

6. 번역 파일과 CMS: 무엇을 어디에 둘까
다국어 운영 비용은 ‘몇 개 언어를 지원하느냐’보다 ‘어떤 콘텐츠를 누가 얼마나 자주 바꾸느냐’에 의해 결정된다. 버튼, 메뉴, 폼 오류는 개발 배포와 함께 움직여도 되지만, 랜딩 카피와 블로그는 마케팅팀이 독립적으로 수정해야 할 가능성이 높다. 가격, 약관, 개인정보 문구는 번역 품질보다 승인권자가 더 중요하다.
| 콘텐츠 유형 | 권장 저장 위치 | 관리자 | 주의점 |
|---|---|---|---|
| 버튼, 메뉴, 폼 오류 | 코드 저장소의 JSON 또는 TS 메시지 파일 | 개발팀, PM | 키 누락을 빌드나 테스트에서 잡아야 한다. |
| 랜딩 본문, 고객 사례 | CMS locale별 문서 | 마케팅팀 | slug, seoTitle, seoDescription, published 상태가 필요하다. |
| 블로그, 도움말 문서 | CMS 또는 문서 플랫폼 | 콘텐츠 담당자 | 원문과 번역본을 canonicalGroupId로 묶어야 한다. |
| 가격, 법무, 약관 | CMS+승인 워크플로우 또는 별도 DB | 대표, 법무, 운영 | 단순 번역이 아니라 시장별 정책 검수가 필요하다. |
| SaaS 사용자 데이터 | 서비스 DB | 고객사, 사용자 | 검색 색인 대상이 아니므로 SEO보다 권한과 언어 표시가 우선이다. |
next-intl은 정적 pathname을 locale별로 다르게 보여주고 내부적으로 같은 App Router 파일에 매핑하는 구성을 제공한다. 다만 CMS에서 동적 slug를 locale별로 관리한다면 language switcher와 alternate link도 CMS의 localized slug를 알아야 한다. 도구가 자동으로 해결해주는 범위와 서비스가 직접 책임져야 하는 범위를 구분해야 한다. ([next-intl.dev](https://next-intl.dev/docs/routing/configuration))
CMS 모델은 최소한 locale, slug, canonicalGroupId, status, seoTitle, seoDescription, publishedAt, updatedAt를 가져야 한다. 이 구조가 있으면 한국어 원문은 공개, 영어 번역은 검수 중, 일본어는 미작성 같은 상태를 sitemap과 hreflang에서 제외할 수 있다.
CMS 발행 후 Next.js 캐시를 무효화하는 기준도 locale을 포함해야 한다. 한국어 가격 페이지를 수정했는데 영어 가격 페이지까지 재검증할 필요는 없지만, 공통 가격 데이터가 바뀌었다면 여러 locale의 메타데이터와 본문이 함께 바뀔 수 있다. 캐시 운영은 Next.js ISR·온디맨드 재검증 전략과 함께 설계하면 배포 없이 콘텐츠를 바꾸는 구조를 잡기 쉽다.
7. SaaS 화면은 다국어 SEO와 분리해서 설계한다
해외 유입을 준비하는 팀이 자주 묻는 질문은 ‘관리자 화면까지 hreflang을 넣어야 하느냐’다. 대부분의 답은 아니다. 로그인 후 대시보드, 관리자 화면, 결제 관리, 내부 운영 화면은 검색 색인 대상이 아니다. 이 영역에서는 hreflang보다 인증, 권한, 테넌시, 사용자별 언어 선호, 날짜·통화 포맷, 오류 메시지 번역이 중요하다.
| 영역 | 검색 색인 | 다국어 우선순위 | 운영 기준 |
|---|---|---|---|
| 홈, 기능 소개, 가격 랜딩 | 색인 대상 | URL, hreflang, canonical, sitemap | 마케팅팀이 CMS로 관리할 수 있어야 한다. |
| 문서, 도움말, API 가이드 | 조건부 색인 | localized slug, 검색 의도별 번역 | 원문과 번역본의 버전 차이를 추적한다. |
| 회원가입, 로그인 | 대개 제한적 | 폼 문구, 약관 링크, 오류 메시지 | 국가별 약관과 개인정보 동의가 다를 수 있다. |
| 대시보드, 관리자 | 색인 제외 | 사용자 언어 설정, 권한별 메뉴 번역 | noindex, 인증, 접근 제어가 우선이다. |
| 테넌트 공개 페이지 | 서비스 정책에 따라 다름 | 테넌트별 SEO 허용 여부 | 고객사 콘텐츠가 검색 노출되어도 되는지 계약과 설정이 필요하다. |
BizMit 같은 SaaS·업무 자동화 프로젝트에서도 공개 랜딩과 관리자 화면은 같은 Next.js 앱 안에 있을 수 있지만 운영 기준은 다르다. 공개 랜딩은 검색 노출과 전환을 기준으로, 관리자 화면은 권한과 업무 효율을 기준으로 설계해야 한다. 관리자 보안 구조가 함께 필요하다면 Next.js App Router 인증 권한 설계 가이드를 먼저 정리하는 것이 좋다.

8. 출시 전 체크리스트: 페이지 수보다 신호 일관성을 확인한다
다국어 출시 전에는 ‘영어 페이지가 몇 개 완성됐는가’보다 ‘검색엔진과 사용자가 같은 URL 체계를 보게 되는가’를 먼저 확인해야 한다. 아래 체크리스트는 개발팀, 마케팅팀, PM이 함께 봐야 한다.
URL·라우팅
- 지원하지 않는 locale URL은 404 또는 정해진 redirect로 처리된다.
- 기본 언어를 루트에 둘지 prefix에 둘지 문서화되어 있다.
- 언어 전환 버튼은 같은 콘텐츠의 다른 언어 URL로 이동한다.
- staging, preview URL이 production sitemap이나 canonical에 섞이지 않는다.
메타데이터·검색 신호
- 각 공개 페이지에 locale별 title과 description이 있다.
- canonical, hreflang, sitemap이 같은 URL helper를 사용한다.
- hreflang은 자기 자신을 포함하고, reciprocal link가 맞는다.
hreflang='x-default'를 사용할 경우 fallback 페이지의 역할이 명확하다.- noindex 페이지나 로그인 필요 페이지가 sitemap에 들어가지 않는다.
콘텐츠·CMS
- 미번역 페이지가 자동으로 기본 언어 본문을 노출하지 않는다.
- CMS 문서에 locale, slug, canonicalGroupId, status가 있다.
- 가격, 약관, 개인정보 문구는 번역이 아니라 승인 절차로 관리된다.
- 검색 의도가 다른 시장은 직역이 아니라 별도 카피로 작성한다.
빌드·캐시·검수
generateStaticParams또는 동적 렌더링 범위가 locale별로 결정되어 있다.- CMS 발행 시 해당 locale과 관련 route만 재검증한다.
- 번역 키 누락, 잘못된 locale 코드, 깨진 내부 링크를 테스트에서 잡는다.
- Search Console, 로그, 크롤러 테스트로 대표 locale URL을 샘플 검증한다.
Google은 sitemap 방식으로도 hreflang 변형을 전달할 수 있고, Next.js App Router는 sitemap.ts에서 alternates.languages를 생성하는 방식을 제공한다. 페이지 수가 늘어나면 head 태그만 수동으로 관리하기보다 sitemap과 라우팅 helper를 함께 생성하는 편이 실수에 강하다. ([developers.google.com](https://developers.google.com/search/docs/advanced/crawling/localized-versions?hl=en&rd=1&visit_id=638854164708922959-2595562323))
9. 단계별 도입 로드맵
초기 스타트업이나 정부지원 MVP에서는 처음부터 한국어, 영어, 일본어 랜딩과 전체 SaaS 화면을 동시에 완성하려고 하면 일정이 빠르게 흔들린다. 권장 순서는 다음과 같다.
- 0단계: URL 인벤토리 — 현재 색인된 URL, 광고 랜딩, 주요 백링크, 기존 sitemap을 정리한다.
- 1단계: 라우팅 정책 확정 — default locale, prefix, localized pathname, redirect 규칙을 문서화한다.
- 2단계: 핵심 랜딩 3~5개만 다국어화 — 홈, 기능, 가격, 문의, 대표 고객사례부터 시작한다.
- 3단계: CMS와 SEO 메타데이터 연결 — 콘텐츠 담당자가 locale별 title, description, slug, 발행 상태를 관리하게 한다.
- 4단계: SaaS UI 번역 범위 확장 — 가입, 결제, 대시보드, 관리자 화면을 업무 우선순위에 따라 번역한다.
- 5단계: 관측과 리팩터링 — Search Console, 전환율, 문의 품질, 고객 언어 분포를 보고 다음 locale 투자를 결정한다.
AgentMit은 다국어 Next.js 프로젝트를 단순 번역 기능으로 보지 않는다. 특히 기존 App Router 프로젝트를 다국어 구조로 전환하거나, CMS·번역 워크플로우·관리자 화면까지 함께 설계해야 하는 경우에는 처음부터 route map, 콘텐츠 모델, SEO 신호, 캐시 무효화 기준을 한 장의 운영표로 맞추는 것이 중요하다. 구현 상담이 필요하다면 프로덕션 문의에서 현재 URL 구조, 지원하려는 locale, CMS 사용 여부, 색인 대상 페이지 목록을 먼저 공유하면 논의가 빨라진다.
참고한 공식 문서와 적용 범위
- Google Search Central의 다국어·다지역 사이트 문서는 언어별 URL, 자동 리다이렉트 주의, 사용자가 언어를 선택할 수 있는 링크 제공 기준을 확인하는 데 사용했다. ([developers.google.com](https://developers.google.com/search/docs/advanced/crawling/managing-multi-regional-sites))
- Google의 localized versions 문서는 hreflang, HTTP header, sitemap, reciprocal link, x-default, language code 기준을 확인하는 데 사용했다. ([developers.google.com](https://developers.google.com/search/docs/advanced/crawling/localized-versions?hl=en&rd=1&visit_id=638854164708922959-2595562323))
- Google canonical 문서는 절대 canonical URL과 sitemap, redirect가 canonical 신호로 작동하는 방식을 확인하는 데 사용했다. ([developers.google.com](https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls))
- Next.js 공식 문서는 App Router의 internationalization, generateMetadata, metadataBase, alternates.languages, localized sitemap 구현 기준을 확인하는 데 사용했다. ([nextjs.org](https://nextjs.org/docs/app/guides/internationalization))
- next-intl 문서는 App Router 기반 locale routing, proxy, localePrefix, localized pathname, alternateLinks 설정의 실무 판단 기준을 확인하는 데 사용했다. ([next-intl.dev](https://next-intl.dev/docs/routing/setup))

