요약
GEO/SEO를 위하여 한 페이지 안에 섞여 있던 한국어·영어 콘텐츠를 언어별 URL로 분리하였습니다.
이 과정에서 리서치 및 고민한 내용, Codex에 실제 요청한 프롬프트를 정리하였습니다.
발생한 문제
웹 도구 모음 사이트인 Weplet을 만들면서 한국어와 영어를 함께 지원하도록 만들었습니다.
처음에는 weplet.com이라는 하나의 URL에서 언어 전환 버튼을 누르면 한국어와 영어 콘텐츠가 바뀌도록 구현했습니다.
사용자 입장에서는 버튼을 누르면 언어가 정상적으로 변경되기 때문에 큰 문제가 없어 보였습니다.
하지만 ko/en을 눌러도 주소창에는 변화가 없고 같은 주소를 공유하고 있습니다. 코드를 살펴보니 실제 구조는 하나의 페이지 안에 한국어와 영어 콘텐츠가 모두 들어 있고, 화면에서 보여주는 내용만 전환하는 방식이었습니다.
탐색 도구라는 단어가 표시된 화면
이렇게 한국어 페이지와 영어 페이지가 동일한 URL을 사용하면 구조는 사용성 측면에서는 동작하지만, 검색 노출까지 고려하면 문제가 있었습니다.
한 페이지 내에 한국어 페이지와 영어 페이지가 혼재되어 있음.
특정 언어 페이지를 링크로 공유하기 어렵다.
검색 결과에서도 사용자의 언어에 맞는 URL을 연결하기 어렵다.
Google은 다국어 사이트를 만들 때 쿠키나 브라우저 설정만으 로 같은 URL의 콘텐츠를 바꾸는 것보다, 각 언어 버전에 서로 다른 URL을 사용하는 방식을 권장합니다.
그래서 이번에는 단순히 언어 전환 버튼을 고치는 것이 아니라, Weplet의 다국어 URL 구조 전체를 다시 설계해보기로 했습니다.
진행 방법
1. 다국어 URL을 처리하는 세 가지 방법 조사
다국어 사이트에서 언어별 페이지를 구분하는 방법은 크게 세 가지로 정리할 수 있었습니다.
다른 이름을 가진 한국 웹사이트 목록
방법 1. 언어별 서브도메인 사용
각 언어를 별도의 서브도메인으로 분리하는 방식입니다.
ko.weplet.com
en.weplet.com언어별 사이트를 독립적으로 운영하거나, 국가별 서비스와 인프라가 크게 다른 경우에는 유용합니다. 하지만 Weplet은 한국어와 영어가 같은 기능과 페이지 구조를 공유하기 때문에 서브도메인까지 나누면 배포와 관리 구조가 불필요하게 복잡해질 수 있다고 판단했습니다.
방법 2. 하위 경로 사용(채택안)
하나의 도메인 안에서 언어를 경로로 구분하는 방식입니다.
weplet.com/ko
weplet.com/en기존 도메인의 구조와 권위를 함께 활용할 수 있고, 프론트엔드 라우팅과 Sitemap도 한 프로젝트 안에서 관리할 수 있습니다. Weplet처럼 언어별 기능과 페이지 구성이 거의 동일한 서비스에 가장 적합하다고 판단했습니다.
방법 3. 쿼리 파라미터 사용
weplet.com?lang=ko
weplet.com?lang=en구현은 비교적 간단하지만, 페이지의 언어가 URL 경로에 명확하게 드러나지 않습니다.
파라미터 누락이나 중복 URL 관리 문제도 생길 수 있어 대표 URL을 관리하기가 상대적으로 까다로웠습니다.
최종 선정
Weplet에는 다음과 같은 하위 경로 방식이 가장 적합하다고 결론 내렸습니다.
weplet.com/ko
weplet.com/enGoogle 역시 언어별로 서로 다른 URL을 제공하고, 각 URL을 hreflang으로 연결하는 방식을 안내하고 있습니다.
리다이렉트 문제
언어별 URL을 나누려고 하니 실제로 처리하는 과정에서 새로운 문제가 떠올랐습니다.
사용자가 언어가 없는 루트 주소로 들어오면 어떤 언어를 보여줘야 할까요?
https://weplet.com이럴 때, 접속자의 브라우저 언어나 위치를 확인해 자동으로 한국어 또는 영어 페이지로 보내는 구조를 생각할 수 있습니다.
예를 들면 다음과 같습니다.
한국어 브라우저 → /ko
그 외 브라우저 → /en하지만 모든 요청을 브라우저 언어나 접속 지역만으로 강제 이동(리다이렉트) 시키면 문제가 생길 수 있습니다.
예를 들어 사용자가 영어 페이지인 /en을 직접 열었는데, 한국어 브라우저를 사용한다는 이유로 /ko로 다시 이동시키면 사용자가 명시적으로 선택한 언어를 무시하게 됩니다.
검색엔진 크롤러도 항상 일반 사용자와 같은 언어 헤더나 지역 정보를 제공하는 것은 아닙니다. Googlebot은 기본적으로 Accept-Language 헤더 없이 요청할 수 있기 때문에, 같은 URL에서 접속 조건에 따라 콘텐츠를 바꾸면 일부 언어 버전을 충분히 발견하지 못할 가능성이 있습니다.
최종 리다이렉트 기준
리다이렉트 규칙은 다음과 같이 정했습니다.
1. URL에 언어가 지정돼 있다면 그대로 유지
weplet.com/ko → 한국어 페이지 표시 (리다이렉트 안함)
weplet.com/en → 영어 페이지 표시 (리다이렉트 안함)사용자가 /ko 또는 /en으로 직접 접근했다면 브라우저 언어나 접속 지역과 관계없이 요청한 언어를 그대로 보여줍니다.
2. 언어가 없는 루트로 접근한 경우에만 언어 판단
weplet.com → (리다이렉트) → weplet.com/en어떤 언어로 보여줄지 판단하는 우선순위는 다음과 같습니다.
사용자가 이전에 직접 선택한 언어
브라우저의 설정 언어(
Accept-Language로 확인)서비스의 기본 언어(영어)
사용자가 직접 선택한 언어가 있다면, 다음에 들어왔을 때 기억할 수 있도록 다음과 같이 쿠키에 명시적으로 저장합니다.
preferred_locale=ko또는
preferred_locale=en단순히 마지막으로 방문한 URL을 추측하는 것이 아니라, 사용자가 직접 선택한 언어라는 의미를 가진 값으로 저장했습니다.
3. 언어 전환 시 현재 페이지의 맥락 유지
사용자가 상세 페이지를 보고 있다면 언어를 변경해도 홈으로 이동하지 않고 보던 페이지를 유지도록 했습니다.
/ko/tools/json-formatter
→ /en/tools/json-formatter언어 경로만 변경하고 나머지 페이지 경로는 유지하는 방식입니다.
대응되는 번역 페이지가 없는 경우에는 해당 언어의 홈이나 목록 페이지로 보내는 대신, 어떤 동작을 할지 별도의 정책을 정해야 합니다. Weplet에서는 우선 동일한 페이지 구조를 한국어와 영어에 모두 제공하는 것을 기준으로 잡았습니다.
Codex 에게 전달한 구현 요청 프롬프트
조사한 내용과 결정한 기준을 정리해 다음과 같이 Codex에 구현을 요청했습니다.
단순히 “다국어 처리를 해주세요”라고 요청하지 않고, URL 구조와 리다이렉트 우선순위, 검색 최적화 조건을 체크리스트로 구체화했습니다.
사이트 다국어 처리 개선을 요청합니다.
weplet.com/ko, weplet.com/en처럼 하위 경로를 사용하여 URL을 분리해주세요.
리다이렉트 기준:
사용자가 /ko 또는 /en처럼 언어가 지정된 주소에 직접 접근했다면
요청한 언어를 그대로 보여주세요.
언어가 지정되지 않은 주소로 접근했을 때에는 저장된 사용자 선택과
브라우저 언어를 확인해 적절한 경로로 이동해주세요.
언어 판단 우선순위는 다음과 같습니다.
1. 사용자가 과거에 직접 선택한 언어
2. 브라우저의 Accept-Language에서 확인한 지원 언어
3. 서비스의 기본 언어인 영어
사용자가 선택했던 언어는 preferred_locale=en처럼
명시적인 언어 설정값을 쿠키에 저장해주세요.
언어를 변경할 때는 현재 보고 있던 페이지 경로를 유지해주세요.
예:
/ko/tools/json-formatter
→ /en/tools/json-formatter
최종적으로 다음 체크리스트를 모두 만족하게 해주세요.
- [ ] 모든 언어 페이지에 고유한 URL이 있다.
- [ ] URL 경로와 실제 콘텐츠 언어가 일치한다.
- [ ] html lang 값이 실제 콘텐츠 언어와 일치한다.
- [ ] 대응되는 상세 페이지끼리 hreflang으로 상호 연결된다.
- [ ] 각 언어 페이지의 canonical이 자기 자신을 가리킨다.
- [ ] 검색에 공개할 언어 URL이 Sitemap에 포함된다.
- [ ] 사용자가 직접 선택한 언어 URL을 강제로 변경하지 않는다.
- [ ] 루트 URL의 언어 판단 순서와 서비스 기본 언어가 정해져 있다.
- [ ] 언어 변경 시 URL이 바뀌고 현재 페이지의 맥락이 유지된다.
체크리스트 - 검색엔진을 위한 추가 설정
최종 적용하면서 요청한 체크리스트 내용 중 몇가지를 소개합니다. 이것들은 페이지의 html태그 안에 메타 데이터로 입력되는 정보들입니다.
1. HTML lang
각 페이지의 실제 언어에 맞게 html lang을 설정했습니다.
<!-- 한국어 페이지 -->
<html lang="ko"><!-- 영어 페이지 -->
<html lang="en">다만 Google은 페이지 언어를 판별할 때 lang 속성만을 직접적인 판단 기준으로 사용하지 않고, 실제 페이지 콘텐츠를 분석한다고 설명합니다. 따라서 lang 값뿐만 아니라 화면에 표시되는 본문도 해당 언어로 일관되게 구성해야 합니다.
2. hreflang
한국어 페이지와 영어 페이지가 서로 대응되는 번역본이라는 것을 알리기 위해 hreflang을 연결했습니다.
<link
rel="alternate"
hreflang="ko"
href="https://weplet.com/ko/tools/json-formatter"
/>
<link
rel="alternate"
hreflang="en"
href="https://weplet.com/en/tools/json-formatter"
/>
<link
rel="alternate"
hreflang="x-default"
href="https://weplet.com/tools/json-formatter"
/>
hreflang은 각 페이지가 동일한 콘텐츠의 언어별 버전이라는 점을 검색엔진에 전달하는 역할을 합니다. 각 언어 페이지는 자기 자신을 포함한 대응 페이지를 서로 참조하도록 구성해야 합니다.
3. Canonical URL
canonical은 페이지의 표준 주소를 나타냅니다. 동일한 페이지를 여러가지 url을 통해 표시할 수 있는 경우가 많기 때문에, 어떤 주소가 표준인지 크롤러(검색봇)가 알 수 있도록 합니다.
Google 역시 hreflang을 사용하는 경우 가능한 한 같은 언어의 URL을 canonical로 지정하도록 안내합니다.
각 언어 페이지는 자기 자신(각 언어 페이지)의 URL을 canonical로 지정했습니다.
<!-- 한국어 페이지 -->
<link
rel="canonical"
href="https://weplet.com/ko/tools/json-formatter"
/>
<!-- 영어 페이지 -->
<link
rel="canonical"
href="https://weplet.com/en/tools/json-formatter"
/>
한국어와 영어 콘텐츠는 서로 대응되는 번역 페이지이지만, 한쪽을 다른 쪽의 중복 페이지로 처리하면 안 됩니다.
사이트맵(Sitemap)
Sitemap은 검색엔진에 중요 URL과 언어별 대체 페이지 정보를 전달하는 데 사용할 수 있습니다. 다만 Sitemap 제출 자체가 색인 생성을 보장하는 것은 아니며, 검색엔진이 URL을 발견하도록 돕는 힌트에 가깝습니다.
검색에 노출하고 싶은 한국어와 영어 URL이 Sitemap에 모두 포함되도록 만들어야 합니다.
<url>
<loc>https://weplet.com/ko/tools/json-formatter</loc>
</url>
<url>
<loc>https://weplet.com/en/tools/json-formatter</loc>
</url>
저는 여기에서 더 나아가 Sitemap을 각 언어별로 독립적으로 만들어서 연결시켰습니다. sitemap-ko.xml 과 sitemap-en.xml 를 별도로 만들고 두 Sitemap을 하나의 Sitemap Index에서 연결했습니다.
<!-- sitemap.xml -->
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://weplet.com/sitemap-ko.xml</loc>
</sitemap>
<sitemap>
<loc>https://weplet.com/sitemap-en.xml</loc>
</sitemap>
</sitemapindex>robots.txt에서도 Sitemap Index의 위치를 안내했습니다.
Sitemap: https://weplet.com/sitemap.xml적용 확인
다국어 URL 구조를 적용한 뒤에는 다음 항목을 추가로 확인이 가능합니다.
Google Search Console에서
/ko,/enURL 색인 상태 확인URL 검사 도구로 canonical 인식 결과 확인
hreflang상호 연결 누락 여부 검사Sitemap에 잘못된 URL이나 리다이렉트 URL이 포함되지 않았는지 확인
언어 변경 후 기존 상세 페이지 경로가 유지되는지 테스트
쿠키가 없거나 잘못된 언어 값이 저장된 경우 테스트
번역되지 않은 페이지의 fallback 정책 정리
한국어와 영어 검색 결과에서 각각 적절한 제목과 설명이 표시되는지 확인
검색 노출은 설정 직후 바로 확인하기 어렵기 때문에, 이후 실제 색인 결과와 검색 유입 변화를 관찰해 후속 사례로 정리해보려고 합니다.
결과와 배운 점
이번 작업을 통해 다국어 처리는 단순히 번역 문구를 보여주는 기능이 아니라는 점을 배웠습니다.
사용자 화면에서 언어가 정상적으로 바뀌더라도 다음 조건이 함께 충족돼야 검색엔진과 사용자가 언어별 페이지를 명확하게 구분할 수 있었습니다.
언어마다 고유한 URL이 있어야 한다.
URL과 실제 콘텐츠 언어가 일치해야 한다.
직접 선택한 언어는 자동 판단보다 우선해야 한다.
대응되는 번역 페이지를
hreflang으로 연결해야 한다.언어별 페이지가 자기 자신을 canonical로 지정해야 한다.
Sitemap에 실제 검색 노출 대상 URL을 포함해야 한다.
참고 자료 Reference
Google Search Central — 다국어·다지역 사이트 관리 가이드
언어별 고유 URL 사용, 자동 리다이렉트 주의사항, 다국어 사이트의 URL 구조를 정하는 데 참고했습니다.Google Search Central — 언어별 페이지와 hreflang 설정 가이드
한국어와 영어 페이지를hreflang으로 상호 연결하고,x-default를 설정하는 방법을 참고했습니다.Google Search Central — 지역 및 언어 적응형 페이지 크롤링 가이드
Accept-Language, 접속 위치 등에 따라 콘텐츠를 동적으로 변경하거나 리다이렉트할 때 발생할 수 있는 크롤링 문제를 확인했습니다.Google Search Central — canonical URL 설정 가이드
각 언어 페이지가 같은 언어의 자기 URL을 canonical로 지정해야 한다는 기준을 확인했습니다.Google Search Central — Sitemap 생성 및 제출 가이드
언어별 Sitemap 생성, Sitemap Index 연결,robots.txt와 Search Console을 통한 제출 방법을 참고했습니다.