VORA는 한국어와 영어 두 언어 사용자를 모두 지원하며, 두 언어 버전 간에 완벽한 동등성을 유지합니다. 모든 페이지가 두 언어로 존재하고, 모든 기능이 두 언어에서 작동하며, 블로그에도 두 언어 버전이 있고, 심지어 이용약관까지도 두 가지 버전으로 제공됩니다. 우리는 로컬라이제이션 프레임워크를 사용하지 않고 이를 구현했으며, 대신 이중 HTML 파일 구조와 JavaScript의 runtime i18n 객체를 사용했습니다. 이 글에서는 이 접근 방식, 그것이 만든 구체적인 문제들, 그리고 뒤돌아보면서 다르게 할 점들을 설명합니다.
초기 아키텍처 결정: 이중 HTML 파일
정적 사이트를 위한 가장 단순한 i18n 접근 방식: 각 페이지에 대해 별도의 두 개 HTML 파일을 유지합니다. index.html (영어) 및 index_ko.html (한국어). 동일한 CSS, 동일한 JavaScript, 다른 HTML 콘텐츠입니다. 언어 전환은 상응하는 파일로의 링크입니다.
이것이 우리가 선택한 접근 방식이며, 정적 사이트에 대한 실제의 장점이 있습니다:
- JavaScript i18n 라이브러리가 필요하지 않습니다.
- 검색 엔진은 각 언어에 대해 완전히 별도의 페이지를 보므로, 이는 hreflang를 사용한 SEO에 대해 올바릅니다.
- 각 언어 버전을 완전히 독립적으로 최적화할 수 있습니다 — 다른 이미지, 다른 마케팅 카피, 다른 콘텐츠 강조.
- 유지 관리하거나 디버그할 언어 감지 논리가 없습니다.
단점은 사이트가 커질수록 명확해집니다.
절대 사라지지 않는 동기화 문제
index.html에 대해 UI 변경을 할 때, index_ko.html에도 동등한 변경을 해야 합니다. app.html에 새 기능을 추가할 때, app_ko.html에도 추가해야 합니다. HTML에 대한 모든 구조적 변경은 이중 작업입니다. 한 파일의 CSS 클래스를 수정할 때마다, 상대 파일에서도 수정해야 한다는 것을 기억해야 합니다.
이 동기화가 얼마나 자주 깨지는지를 보여주는 git 히스토리가 있습니다. "언어 일관성 수정: 영어 페이지의 한국어 링크 수정" 커밋은 일부 페이지의 한국어 버전에 한국어 페이지를 가리키는 링크가 있었지만(올바름) 동일한 페이지의 영어 버전이 한국어 페이지를 가리키는 링크로도 연결되어 있었음을 드러냅니다. 영어 FAQ에서 영어 블로그로 이동하는 사용자는 한국어 블로그에 착륙할 것입니다.
이러한 유형의 오류는 이중 파일 아키텍처의 예측 가능한 실패 모드입니다: 한 파일에서 변경을 한 후, 상대 파일로 전파하는 것을 잊고, 특정 탐색 경로를 따르는 경우에만 불일치가 표면화됩니다.
hreflang 구현
Google Search Console 및 국제 SEO를 위해 hreflang 태그를 올바르게 구현해야 했습니다. 모든 페이지는 <head>에 세 개의 메타 태그가 필요합니다:
<link rel="alternate" hreflang="en" href="https://...pages.dev/blog.html" />
<link rel="alternate" hreflang="ko" href="https://...pages.dev/blog_ko.html" />
<link rel="alternate" hreflang="x-default" href="https://...pages.dev/blog.html" />
x-default 태그는 더 나은 언어 일치가 없을 때 어느 버전을 제공할지를 Google에 알립니다 — 우리는 영어를 기본값으로 사용합니다. 모든 영어 페이지는 한국어 상대방으로 링크되고, 모든 한국어 페이지는 영어 상대방으로 링크됩니다. 구현은 지루하지만 국제 검색 가시성에 중요합니다.
hreflang 구현을 감사한 후 일부 한국어 페이지가 한국어 검색에서 나타나지 않음을 발견했습니다. 감사에서 발견한 것: 세 개의 한국어 페이지에는 hreflang URL이 잘못된 영어 상대방을 가리키고 있었습니다 (다른 페이지의 코드에서 복사-붙여넣기 오류). 두 페이지는 완전히 x-default 태그가 누락되어 있었습니다. 한 페이지에는 영어와 한국어 hreflang URL이 바뀌어 있었습니다. 이 모든 것이 조용했습니다 — 브라우저 오류가 없고, 배포 실패가 없었으며, 단지 Google의 크롤러에 잘못된 정보가 전송되었을 뿐입니다.
JavaScript i18n 객체: 실용적인 타협안
앱 페이지(app.html 및 app_ko.html)의 경우, 동적 UI 요소는 언어에 적절한 문자열을 표시해야 했습니다. JavaScript를 완전히 복제하는 대신, 앱 클래스 내에 간단한 i18n 객체를 구현했습니다:
this.i18n = {
ko: {
recording: '녹음 중',
waiting: '대기 중',
apiKeyNotSet: 'API 키 미설정',
startRecording: '녹음 시작',
// ... ~20개 더 많은 문자열
},
en: {
recording: 'Recording',
waiting: 'Waiting',
apiKeyNotSet: 'API Key Not Set',
startRecording: 'Start Recording',
// ...
}
};
// HTML lang 속성에서 언어 감지
this.currentLang = document.documentElement.lang === 'en' ? 'en' : 'ko';
앱 자체는 app.html 및 app_ko.html에서 동일합니다 — 유일한 차이는 <html> 태그의 lang 속성입니다 (lang="ko" vs lang="en"). JavaScript는 이 속성을 감지하고 적절한 문자열 사전을 선택합니다. 이는 우리가 하나의 JavaScript 파일(enhanced-app-v2.js)을 유지 관리한다는 의미입니다 — 코드베이스의 가장 복잡한 부분에 대한 유지 관리 부담의 의미 있는 감소입니다.
이용약관 분할: 로컬라이제이션 범위의 사례 연구
흥미로운 결정 지점은 이용약관이었습니다. 처음에는 한국어 약관 페이지만 있었습니다. 영어 지원을 추가하기로 결정했을 때 옵션은 다음과 같았습니다:
- 한국어 약관을 영어로 직접 번역합니다.
- 영어 사용자에게 적합한 새로운 영어 약관을 처음부터 작성합니다.
- 두 언어를 모두 제공하는 하나의 약관 문서를 보유합니다 (이중 언어 문서).
우리는 옵션 1 (별도의 영어 및 한국어 버전)을 선택했습니다 — 법적 명확성을 위해: 한국어 버전은 한국법을 따르는 한국 사용자를 위한 구속력 있는 버전이고, 영어 버전은 국제 사용자를 위한 구속력 있는 버전입니다. 분쟁 시 어느 버전이 통제하는지에 대한 모호성이 있는 이중 언어 문서는 우리가 필요로 하지 않은 법적 문제입니다.
"이용약관을 영어 및 한국어 버전으로 분리" 커밋은 예상보다 큰 리팩터링이었습니다: 원래 한국어 약관을 terms_ko.html로 이름 변경, 영어를 위한 새 terms.html 작성, 약관에 링크하는 모든 페이지 업데이트 (모든 페이지), 그리고 사이트맵 업데이트. 이중 파일 변경은 모든 링크 업데이트를 고려할 때 12파일 변경이 되었습니다.
언어 일관성 감사
개발 후반에 우리는 사이트 전체에서 언어 일관성에 대한 체계적인 감사를 실시했습니다. 발견 사항은 이중 파일 아키텍처가 어디서 깨지는지에 대해 교육적이었습니다:
- 탐색 링크: 3개의 영어 페이지가 한국어 상대방으로 링크되어 있었습니다 (grep 및 바꾸기로 수정됨).
- 바닥글 콘텐츠: 일부 한국어 페이지에는 영어 바닥글 텍스트가 있었습니다 (영어 템플릿을 복사했으나 바닥글을 번역하지 않음).
- 메타 설명: 두 개의 한국어 페이지에는 영어 메타 설명이 있었습니다 (SEO 영향: Google이 검색 결과에서 설명을 표시하므로 한국어 검색 사용자는 영어 미리보기를 봤습니다).
- 이미지 alt 텍스트: 여러 페이지에는 페이지 언어와 관계없이 이미지에 영어 alt 텍스트가 있었습니다. 시력 있는 사용자에게는 영향이 낮지만 한국어 사용자의 화면 판독기에 영향을 미칩니다.
- 날짜: 일부 한국어 페이지에서는
Feb 2026형식 대신2026년 2월형식으로 날짜를 표시하고 있었습니다.
이 중 어느 것도 자동화된 테스트로 포착되지 않았습니다 — 수동 검토가 필요했습니다. VORA의 현재 규모 (2개 언어의 20개 이상 페이지)에서는 관리 가능합니다. 더 큰 규모에서 이중 파일 아키텍처는 자동화 (링크 일관성, 언어 태그 존재를 확인하는 스크립트) 또는 적절한 i18n 시스템 중 하나를 요구합니다.
현대 도구가 있으면 대신 무엇을 구축할지
뒤돌아보면서 빌드 시스템으로 새로 시작할 경우, 우리는 다음 접근 방식 중 하나를 사용할 것입니다:
- i18n 지원을 갖춘 정적 사이트 생성기: Eleventy, Hugo 또는 Astro 모두 1급 국제화 기능을 가지고 있습니다. 템플릿을 한 번 작성하고 번역 파일 (YAML 또는 JSON)을 제공합니다. 콘텐츠 변형이 자동으로 생성됩니다. 링크 일관성이 템플릿 엔진으로 보장됩니다.
- 빌드 스크립트를 사용한 JSON 기반 번역: 전체 SSG 없이도 template HTML 파일을 취하고 JSON 번역 파일에서 언어 변형을 생성하는 Node.js 빌드 스크립트가 동기화 문제를 제거할 것입니다. 템플릿에 대한 변경이 자동으로 모든 언어 변형으로 전파됩니다.
이 접근 방식을 원래 사용하지 않은 이유: 우리는 빌드 도구 없음, npm 의존성 없음, 그리고 복잡성 오버헤드가 없음을 원했습니다. 텍스트 편집기에서 편집하고 직접 커밋할 수 있는 정적 사이트는 빌드 파이프라인이 있는 사이트보다 유지 관리하기가 진정으로 더 간단합니다. 이중 파일 접근 방식은 프로젝트가 시작될 때 규모에 맞는 올바른 호출이었습니다. VORA가 성장함에 따라 이중 파일 접근 방식의 유지 관리 고통이 마이그레이션 비용을 초과할 때 Eleventy 또는 유사한 도구로 마이그레이션할 가능성이 높습니다 — 그리고 우리는 아직 그 지점에 도달하지 않았습니다.
이중 언어 아키텍처는 또한 제품 진실을 반영합니다: VORA의 한국어 및 영어 사용자는 다소 다른 맥락과 필요를 가지고 있습니다. 한국어 사용자는 특정 회의 문화 규칙 (우리가 논의한 개조식 의사록 형식, 특정 기술 어휘 패턴)이 있는 시장에 있습니다. 영어 사용자는 다른 회의 문화와 다른 규칙이 있는 곳에 있을 수 있습니다. 이중 파일 접근 방식은 유지 관리 비용에도 불구하고 각 버전을 독립적으로 최적화할 수 있는 유연성을 제공합니다. 그 유연성은 순수한 번역 기반 i18n 시스템이 부분적으로 희생할 실제 가치를 가집니다.