# 23. 국제화 가이드

## 0. 먼저 알고 가기 (30초 요약)

- 번역 키는 기능 요구보다 먼저 만들어져야 유지보수가 쉬워집니다.
- 숫자/날짜/문장 길이까지 언어별 차이를 먼저 반영하면 QA 비용이 줄어듭니다.
- 릴리즈마다 누락 키를 회귀 검사하도록 자동화하세요.

> **왜 중요한가**: 국제화는 "번역만 하면 끝"이 아닙니다. 문장 길이, 숫자/날짜 포맷, 방향성, SEO, 폰트, 캐시 키까지 영향을 받기 때문에, 나중에 추가하면 모든 화면을 재작업해야 하는 큰 부채가 됩니다.
>
> **일상 비유**: 옷 사이즈 표기와 같습니다. S/M/L만 적은 옷은 한국에서는 통해도, 유럽에서는 cm와 inch를 함께 표기해야 환불률이 줄어듭니다. "한 번 잘 설계하면 모든 시장에서 통하는" 영역입니다.

## 초심자용 한눈에 보기

국제화는 번역 품질뿐 아니라 운영까지 잡아야 하는 실무 주제입니다.

```mermaid
flowchart LR
  L[Locale 결정] --> M[메시지 키 + ICU]
  M --> F[Fallback 규칙]
  F --> P[Pseudo-loc/RTL smoke]
  P --> S[SEO/hreflang]
  S --> O[운영 모니터링]
```

### 핵심 용어 빠르게 정리

| 용어          | 쉬운 뜻                                 |
| ------------- | --------------------------------------- |
| `locale`      | 지역/언어 설정 값(ko-KR 등)             |
| `번역 키`     | 다국어 문자열을 찾는 고유 식별자        |
| `placeholder` | 변수 치환 부분 예: `{name}`             |
| `RTL`         | 오른쪽에서 왼쪽으로 쓰는 언어 정렬 방향 |
| `용어집`      | 품질을 맞추기 위해 통일한 번역 사전     |

| 분류            | 제품 품질 & 글로벌                                                                                                                                                    | 상태          | Stable    |
| :-------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------ | :-------- |
| **연관 가이드** | [02. React 19](./02_React19_실무_가이드.md), [08. 성능](./08_성능_최적화_가이드.md), [19. 접근성](./19_웹_접근성_가이드.md), [24. SEO](./24_SEO_메타데이터_가이드.md) | **도구 원칙** | 벤더 중립 |
| **핵심 테마**   | locale routing, ICU message, 번역 QA, pseudo-localization, RTL, fallback, SEO                                                                                         | **Update**    | 최신 기준 |

---

> 국제화 표준은 특정 번역 SaaS나 AI 모델 사용법이 아니라 **언어, 지역, 방향성, 포맷, 검색 노출, 번역 품질을 제품 구조 안에서 지속 가능하게 관리하는 방식**입니다.

---

## 추천 항목 (실무 우선순위)

- **시작 추천**: locale 우선순위(`URL`/`쿠키`/`헤더`)와 fallback 규칙을 먼저 정합니다.
- **안정 추천**: 번역 키 충돌/누락을 CI에서 잡고, 중요 문구는 번역 품질 샘플로 사전 검증하세요.
- **운영 추천**: RTL, 통화/날짜 포맷은 지역별 테스터 계정으로 주기 점검합니다.

## 추천 항목 고도화 체크

- `첫 적용` — locale routing, ICU message, fallback, RTL smoke 중 하나를 실제 PR이나 운영 이슈에 붙이고, 변경 전 기준을 먼저 적는다.
- `증거 정리` — message compile, placeholder diff, pseudo-loc screenshot, hreflang 검사를 같은 작업 기록에 남긴다.
- `재점검` — missing key, overflow defect, locale SEO mismatch가 나아졌는지 30일 안에 확인하고 기준을 유지, 수정, 폐기 중 하나로 판정한다.

## 추천 항목 실행 기록 템플릿

- `작업` : locale routing, ICU message, fallback, RTL smoke 적용 범위를 어느 화면, 패키지, 문서에 둘지 적는다.
- `증거` : message compile, placeholder diff, pseudo-loc screenshot, hreflang 검사 중 실제로 남긴 항목만 링크한다.
- `판정` : 유지/수정/폐기 중 하나와 이유를 한 문장으로 남긴다.
- `다음 점검` : missing key, overflow defect, locale SEO mismatch를 다시 볼 날짜와 담당자를 지정한다.

## 문서 책임 범위

| 이 문서가 결정하는 것                                      | 단일 출처로 따르는 문서                                                                      |
| :--------------------------------------------------------- | :------------------------------------------------------------------------------------------- |
| locale 결정, message format, fallback, pseudo-localization | [02. React 19](./02_React19_실무_가이드.md), [07. 테스팅](./07_테스팅_가이드.md)             |
| hreflang, canonical, localized metadata                    | [24. SEO 메타데이터](./24_SEO_메타데이터_가이드.md)                                          |
| RTL, accessible name, 번역 후 UI 접근성                    | [19. 웹 접근성](./19_웹_접근성_가이드.md), [20. 디자인 시스템](./20_디자인_시스템_가이드.md) |
| AI 번역 사용과 민감정보/검증 책임                          | [18. AI 개발 워크플로우](./18_AI_개발_워크플로우_종합.md)                                    |

---

## 0. 모든 프론트엔드 그룹 공통 Baseline

| 영역                    | 공통 기준                                                  | 검증 방법          |
| :---------------------- | :--------------------------------------------------------- | :----------------- |
| **Locale 전략**         | URL, 쿠키, 계정 설정, 브라우저 언어 우선순위 명시          | routing test       |
| **Message format**      | 변수, plural, select, date/number 포맷을 구조화            | compile check      |
| **Fallback**            | 누락 번역, 미지원 locale, 오래된 번역 fallback 정의        | missing key report |
| **Pseudo-localization** | UI overflow와 hard-coded text 검출                         | visual smoke       |
| **RTL**                 | layout, icon direction, focus order, motion direction 검증 | RTL test           |
| **SEO**                 | canonical, hreflang, localized metadata 관리               | SEO audit          |
| **QA**                  | placeholder 보존, 용어집, tone, 길이, 접근성 검수          | translation QA     |

### 0.0 국제화 처리 플로우

```mermaid
flowchart TD
  A[요청/라우트 진입] --> B[Locale 판별]
  B --> C[메시지 키 로드 및 ICU 컴파일]
  C --> D{누락 키 또는 변수 불일치}
  D -->|있음| E[빌드 실패 + 번역 보강]
  D -->|없음| F[출력 렌더 및 날짜/숫자 포맷 적용]
  F --> G[Pseudo-localization + RTL smoke]
  G --> H{문장 길이/문맥 이슈}
  H -->|있음| I[UI 반영/번역 수정]
  H -->|없음| J[SEO/Hreflang/canonical 반영]
  E --> C
  I --> F
  J --> K[릴리즈 증적 및 locale KPI 모니터링]
```

### 0.1 교차 검증 매트릭스

| 권고                                                     | 1차 출처                         | 실행 증거                                  | 운영 증거                          | 철회 조건                                 |
| :------------------------------------------------------- | :------------------------------- | :----------------------------------------- | :--------------------------------- | :---------------------------------------- |
| 메시지는 ICU/plural/select 같은 구조화 format을 사용한다 | Unicode CLDR/ICU MessageFormat   | compile check, placeholder diff            | 번역 오류, locale-specific bug     | 단일 언어 또는 극소수 정적 copy만 다룰 때 |
| URL locale, canonical, hreflang을 일관되게 관리한다      | 검색엔진/HTML link relation 문서 | route SEO test, sitemap validation         | indexed locale mismatch            | 검색 노출이 필요 없는 내부 도구일 때      |
| pseudo-localization을 release smoke에 포함한다           | i18n QA best practice            | visual overflow test, hard-coded text scan | overflow defect, missing key count | 번역 대상 UI가 아직 없을 때               |
| RTL은 logical property와 컴포넌트 테스트로 검증한다      | CSS logical properties, WAI/WCAG | RTL visual diff, keyboard navigation       | RTL-only defect, support ticket    | 지원 locale에 RTL 언어가 없을 때          |

### 0.2 운영 게이트

| Gate             | Evidence                                                     | Owner         | Rollback                               |
| :--------------- | :----------------------------------------------------------- | :------------ | :------------------------------------- |
| Locale 추가      | routing test, fallback rule, SEO metadata 확인               | I18n owner    | locale 비활성화 또는 제한 공개         |
| 메시지 변경      | ICU compile, placeholder diff, missing key report            | Content owner | 이전 번역 복구 또는 fallback 적용      |
| Pseudo/RTL smoke | overflow screenshot, hard-coded text scan, RTL keyboard test | QA owner      | release 차단 또는 affected locale 제외 |
| SEO 국제화       | canonical/hreflang/sitemap validation                        | SEO owner     | sitemap 제외 또는 canonical rollback   |

### 0.2.1 Locale 공개 전 증거 흐름

```mermaid
flowchart LR
  COPY["source copy 변경"] --> MSG["ICU message + placeholder"]
  MSG --> COMPILE{"compile/pass?"}
  COMPILE -->|"fail"| FIX_COPY["키/placeholder 수정"]
  FIX_COPY --> MSG
  COMPILE -->|"pass"| VISUAL["pseudo-loc screenshot"]
  VISUAL --> RTL{"RTL 또는 긴 문장<br/>영향 있음?"}
  RTL -->|"있음"| LAYOUT["logical property/focus/motion 점검"]
  RTL -->|"없음"| SEO
  LAYOUT --> SEO["localized metadata + hreflang"]
  SEO --> FLAG{"locale flag<br/>부분 공개 가능?"}
  FLAG -->|"예"| CANARY["locale canary + KPI 모니터링"]
  FLAG -->|"아니오"| HOLD["공개 보류"]
  CANARY --> RELEASE["정식 공개"]
```

---

## 1. Locale 결정 규칙

> **왜 중요한가**: locale 우선순위가 서버/클라이언트/SEO마다 다르면 한 사용자가 한 페이지에서 서로 다른 언어가 섞여 보입니다. hydration 불일치 버그의 가장 흔한 원인입니다.

| 우선순위 | 기준                              |
| :------- | :-------------------------------- |
| 1        | 사용자가 명시적으로 선택한 locale |
| 2        | 로그인 사용자의 저장된 preference |
| 3        | URL path/domain의 locale          |
| 4        | 브라우저 `Accept-Language`        |
| 5        | 제품 기본 locale                  |

locale 결정 규칙은 서버 렌더링, 클라이언트 라우팅, API 호출, SEO metadata에서 동일하게 적용되어야 합니다.

### 1.1 Locale 결정 의사결정 트리

```mermaid
flowchart TD
  START([요청 진입]) --> EXPLICIT{URL에<br/>locale switch?}
  EXPLICIT -->|예| USE_EXPLICIT[명시 선택 locale]
  EXPLICIT -->|아니오| LOGIN{로그인 사용자?}
  LOGIN -->|예| HAS_PREF{저장된<br/>preference 존재?}
  HAS_PREF -->|예| USE_PREF[저장된 preference]
  HAS_PREF -->|아니오| URL_CHECK
  LOGIN -->|아니오| URL_CHECK
  URL_CHECK{URL path<br/>또는 domain에<br/>locale 표시?}
  URL_CHECK -->|예| USE_URL[URL locale]
  URL_CHECK -->|아니오| ACCEPT{Accept-Language<br/>헤더에 지원 locale?}
  ACCEPT -->|예| USE_ACCEPT[브라우저 우선 locale]
  ACCEPT -->|아니오| USE_DEFAULT[제품 기본 locale]
  USE_EXPLICIT --> RENDER[렌더링]
  USE_PREF --> RENDER
  USE_URL --> RENDER
  USE_ACCEPT --> RENDER
  USE_DEFAULT --> RENDER
```

### 1.2 신규 언어/로케일 추가 시퀀스

```mermaid
sequenceDiagram
  participant PM as PM
  participant DEV as Frontend Dev
  participant TR as Translator
  participant CI as CI Pipeline
  participant SEO as SEO Owner
  participant OPS as Ops

  PM->>DEV: 신규 locale ko-KR 추가 요청
  DEV->>DEV: locales/ko-KR 디렉토리 생성
  DEV->>DEV: 메시지 키 골격 복제 (en 기준)
  DEV->>TR: 번역 요청 + screenshot/context
  TR->>DEV: 번역 파일 PR
  DEV->>CI: PR 푸시
  CI->>CI: ICU compile + placeholder diff
  CI->>CI: missing key 검사
  CI->>CI: pseudo-loc + RTL smoke
  CI-->>DEV: 모든 게이트 통과
  DEV->>SEO: hreflang/canonical/sitemap 추가
  SEO->>SEO: localized metadata 작성
  DEV->>OPS: locale 활성화 플래그 ON
  OPS->>OPS: locale별 KPI 대시보드 확인
  OPS-->>PM: 신규 locale 정식 공개
```

비유: 새 매장을 오픈하는 것과 같습니다. 메뉴판(번역) → 가격표(숫자/통화) → 간판(SEO) → POS 시스템(라우팅) 순서로 준비해야 첫 손님이 헤매지 않습니다.

---

## 2. 메시지 작성 원칙

> **왜 중요한가**: 문장 조각을 이어 붙이는 방식은 영어에서는 자연스러워도, 어순/조사/관사가 다른 언어에서는 문법이 깨집니다. ICU 같은 구조화 포맷을 처음부터 쓰는 것이 가장 저렴한 보험입니다.

| 원칙               | 기준                                       |
| :----------------- | :----------------------------------------- |
| 문장 단위          | 단어 조각을 이어 붙이지 않음               |
| 변수 명확화        | `{count}`, `{userName}`처럼 의미 있는 이름 |
| plural/select 사용 | 수량과 성별/상태 분기를 문법적으로 처리    |
| HTML 분리          | 번역 문자열에 임의 HTML 삽입 금지          |
| 문맥 제공          | 번역자에게 화면, 목적, 제한 길이 제공      |

```json
{
  "cart.items": "{count, plural, =0 {No items} one {# item} other {# items}}",
  "order.status": "{status, select, paid {Paid} failed {Failed} pending {Pending} other {Unknown}}"
}
```

### 2.1 ICU 메시지 처리 흐름

```mermaid
flowchart TD
  SRC[메시지 키 source] --> COMPILE[ICU 컴파일러]
  COMPILE -->|문법 오류| FAIL_COMPILE[빌드 실패<br/>리뷰 차단]
  COMPILE -->|성공| AST[AST 산출]
  AST --> EXTRACT[placeholder 목록 추출]
  EXTRACT --> DIFF{소스 vs 번역<br/>placeholder 일치?}
  DIFF -->|불일치| FAIL_DIFF[CI 실패<br/>번역 수정 요청]
  DIFF -->|일치| RUNTIME[런타임 메시지 빌더]
  RUNTIME --> VARS{입력 변수 모두 제공?}
  VARS -->|아니오| FALLBACK[fallback 적용<br/>+ 모니터링 경고]
  VARS -->|예| RENDER[최종 렌더 문자열]
  RENDER --> INTL[Intl.NumberFormat<br/>Intl.DateTimeFormat 적용]
  INTL --> OUT[화면 출력]
```

비유: 케이크 데코레이션 틀과 같습니다. 글자 한 줄을 직접 짜내는 게 아니라, "이 자리에 이름, 이 자리에 나이"라는 틀(ICU)에 맞춰 짜야 모든 케이크가 일관됩니다.

---

## 3. 번역 키 구조

| 방식           | 기준                       |
| :------------- | :------------------------- |
| Domain 기반    | `checkout.payment.submit`  |
| Component 기반 | 재사용 컴포넌트 내부 label |
| Error 기반     | `error.network.timeout`    |
| Metadata 기반  | `seo.product.title`        |

키 이름은 화면 위치보다 의미를 담아야 합니다. `button.submit`보다 `checkout.payment.submit`이 추적과 변경에 유리합니다.

---

## 4. 번역 QA

| 검사        | 기준                                 |
| :---------- | :----------------------------------- |
| 누락 키     | build 또는 CI에서 실패               |
| 미사용 키   | 주기적으로 정리                      |
| placeholder | 원문과 번역의 변수 목록 일치         |
| ICU syntax  | compile 단계에서 검증                |
| 길이        | 버튼, 탭, 카드, 표에서 overflow 확인 |
| 용어집      | 제품 용어와 금지어 검사              |
| 접근성      | 번역 후 accessible name 의미 유지    |

AI 번역을 사용하더라도 placeholder, plural, tone, legal copy는 자동 검증과 사람 검토가 필요합니다.

---

## 5. Pseudo-localization

Pseudo-localization은 실제 번역 전에 UI 구조 문제를 찾는 가장 저렴한 방법입니다.

| 검출 대상       | 예시                                 |
| :-------------- | :----------------------------------- |
| hard-coded text | 번역 파일을 거치지 않는 문자열       |
| overflow        | 긴 문자열에서 버튼/카드 깨짐         |
| concatenation   | 문법이 깨지는 문자열 조합            |
| missing key     | fallback text 노출                   |
| bidi 문제       | RTL에서 punctuation/number 방향 문제 |

release 전 핵심 flow는 pseudo locale에서 한 번 이상 확인합니다.

---

## 6. RTL 지원

> **왜 중요한가**: 아랍어/히브리어 등 RTL 언어는 단순 텍스트 방향뿐 아니라 메뉴 위치, 아이콘 화살표, 모션 방향, 키보드 포커스 순서까지 영향을 줍니다. 뒤늦게 대응하면 거의 모든 컴포넌트를 재작업해야 합니다.

| 영역   | 기준                                          |
| :----- | :-------------------------------------------- |
| Layout | `left/right`보다 logical property 사용        |
| Icon   | 방향성이 있는 아이콘은 mirror 기준 정의       |
| Motion | slide/transition 방향 검토                    |
| Focus  | keyboard 이동 순서 확인                       |
| Data   | 전화번호, 날짜, 통화, 주소 포맷 locale별 처리 |

RTL은 단순히 `dir="rtl"`을 붙이는 작업이 아닙니다. 디자인 시스템 토큰과 컴포넌트 레벨에서 지원해야 합니다.

### 6.1 RTL 전환 결정 트리

```mermaid
flowchart TD
  PAGE([페이지 진입]) --> Q1{현재 locale이<br/>RTL 언어?}
  Q1 -->|아니오| LTR[dir=ltr 유지]
  Q1 -->|예| Q2{디자인 시스템이<br/>logical property 채택?}
  Q2 -->|아니오| BLOCK_RTL[RTL 비활성화<br/>+ 디자인 부채로 등록]
  Q2 -->|예| SET_DIR[html dir=rtl 적용]
  SET_DIR --> Q3{방향성 아이콘<br/>존재?}
  Q3 -->|예| MIRROR[mirror 규칙 적용<br/>화살표/back 버튼]
  Q3 -->|아니오| Q4
  MIRROR --> Q4{모션/슬라이드<br/>존재?}
  Q4 -->|예| FLIP_MOTION[방향 반전<br/>slide/transition]
  Q4 -->|아니오| Q5
  FLIP_MOTION --> Q5{숫자/날짜/통화<br/>locale별 포맷 적용?}
  Q5 -->|아니오| FORMAT[Intl API 적용]
  Q5 -->|예| KBD
  FORMAT --> KBD{키보드 포커스<br/>순서 검증?}
  KBD -->|아니오| TEST[RTL 키보드 테스트 추가]
  KBD -->|예| READY[RTL 정식 지원]
  TEST --> READY
  LTR --> READY
```

### 6.2 i18n 상태 다이어그램

```mermaid
stateDiagram-v2
  [*] --> NotPlanned: 신규 기능
  NotPlanned --> KeyDraft: 메시지 키 추출
  KeyDraft --> SourceReady: en 기준 작성
  SourceReady --> Translating: 번역 요청 송부
  Translating --> ICUFail: ICU 오류
  Translating --> PlaceholderMismatch: placeholder 불일치
  ICUFail --> SourceReady: 수정
  PlaceholderMismatch --> SourceReady: 수정
  Translating --> Reviewed: 사람 번역 검수
  Reviewed --> PseudoSmoke: pseudo-loc 검사
  PseudoSmoke --> Overflow: UI 깨짐
  Overflow --> KeyDraft: 키/UI 조정
  PseudoSmoke --> RTLSmoke: RTL 대상이면
  PseudoSmoke --> Released: RTL 비대상이면
  RTLSmoke --> Released
  Released --> Deprecated: 키 미사용 90일+
  Deprecated --> [*]: 정리 PR
```

비유: RTL 지원은 거울 방에서 작업하는 것과 같습니다. 좌우 개념을 직접 박지 말고, "시작쪽(inline-start)/끝쪽(inline-end)"이라는 추상 좌표를 사용해야 거울 안에서도 의미가 유지됩니다.

---

## 7. SEO와 라우팅

| 항목      | 기준                                            |
| :-------- | :---------------------------------------------- |
| URL       | locale이 안정적으로 드러나는 URL 구조           |
| Canonical | 중복 URL 정리                                   |
| Hreflang  | 지역/언어 대체 페이지 연결                      |
| Metadata  | title, description, Open Graph 번역             |
| Sitemap   | locale별 URL 포함                               |
| Redirect  | 자동 redirect가 crawler 접근을 막지 않도록 설계 |

검색 노출이 중요한 페이지는 클라이언트에서만 번역하지 말고, 서버/빌드 단계에서 localized metadata를 제공해야 합니다.

---

## 8. 성능 기준

> **왜 중요한가**: 글로벌 제품에서 locale 데이터는 가장 빠르게 비대해지는 자산입니다. 초기에 lazy 로딩 전략을 박지 않으면, locale 추가마다 LCP가 선형으로 악화됩니다.

| 항목           | 기준                                       |
| :------------- | :----------------------------------------- |
| 번역 번들      | 현재 locale과 route에 필요한 메시지만 로드 |
| 폰트           | locale별 subset, fallback, preload 최소화  |
| 날짜/숫자 포맷 | 표준 Intl API 우선                         |
| 캐시           | locale별 cache key와 fallback 명확화       |
| hydration      | 서버/클라이언트 locale 불일치 방지         |

모든 locale 번역을 초기 번들에 넣으면 글로벌 제품일수록 성능이 급격히 나빠집니다.

### 8.1 번역 번들 로딩 전략

```mermaid
flowchart LR
  REQ[요청] --> SSR[SSR locale 판별]
  SSR --> CORE[core 메시지<br/>nav/footer/error]
  SSR --> ROUTE[route별 메시지<br/>현재 경로만]
  CORE --> HYDRATE[hydration]
  ROUTE --> HYDRATE
  HYDRATE --> CLIENT[클라이언트 라우팅]
  CLIENT -->|새 경로 진입| LAZY[lazy chunk 로드]
  LAZY --> CACHE[(locale별 cache)]
  CACHE -.fallback miss.-> CORE
```

---

## 9. 체크리스트

- [ ] locale 결정 우선순위가 문서화되어 있는가
- [ ] 메시지가 plural/select/date/number 포맷을 지원하는가
- [ ] 누락/미사용 키와 placeholder 불일치가 CI에서 잡히는가
- [ ] pseudo-localization으로 overflow와 hard-coded text를 확인하는가
- [ ] RTL locale에서 layout, icon, focus, motion을 검증하는가
- [ ] hreflang/canonical/metadata/sitemap이 locale별로 생성되는가
- [ ] AI 번역 결과를 용어집, placeholder, 사람 검토로 검증하는가

---

## 10. 제외한 벤더 종속 항목

공통 개발 가이드에는 특정 번역 SaaS, 특정 AI 번역 모델, 특정 알림 도구, 특정 OTA 번역 SDK, 특정 배포 플랫폼의 워크플로우를 표준으로 포함하지 않습니다. 이 문서에는 어떤 국제화 도구를 쓰더라도 유지되어야 하는 locale, message format, QA, RTL, SEO, 성능 기준만 남깁니다.

---

## 실무 적용 가이드

### 언제 이 문서를 펼칠까

- 문자열 길이, 복수형, RTL, locale routing이 뒤늦게 문제될 때
- AI 번역 결과가 placeholder나 법무 문구를 깨뜨릴 때
- locale bundle이 성능을 악화시킬 때

### 적용 순서

1. locale 결정 규칙과 fallback 순서를 정한다.
2. ICU message로 plural/select/placeholder를 구조화한다.
3. 번역 키, source text, screenshot/context를 함께 관리한다.
4. pseudo-localization과 RTL smoke를 핵심 flow에 적용한다.
5. message compile, placeholder diff, locale SEO를 CI에서 확인한다.

### 함께 두는 파일

- feature별 메시지, screenshot context, test를 기능 폴더에 둔다.
- 전역 navigation/공통 컴포넌트 메시지만 shared i18n에 둔다.
- locale route metadata는 SEO 문서와 연결한다.

### 흔한 실수

- 문장 조각을 이어 붙인다.
- placeholder 검증 없이 번역을 merge한다.
- RTL에서 margin/padding 방향을 하드코딩한다.
- 모든 locale 메시지를 초기 번들에 넣는다.

### PR 완료 기준

- [ ] message compile이 통과한다.
- [ ] placeholder/plural 검증이 있다.
- [ ] pseudo-loc/RTL 핵심 flow가 통과한다.
- [ ] locale bundle 영향이 확인되었다.

## 추천 항목 실행 우선순위 매핑

- `P1(7일 내)` — locale routing, ICU message, fallback, RTL smoke 중 하나를 작은 변경 1건에 적용하고 증거(message compile)를 남긴다.
- `P2(30일 내)` — 국제화 기준을 팀 템플릿, 체크리스트, CI 중 한 곳에 고정한다.
- `P3(90일 내)` — missing key, overflow defect, locale SEO mismatch 추이를 보고 기준을 유지할지 조정할지 결정한다.
- `완료 기준` — i18n 오너가 증거와 철회 조건을 확인했다는 기록을 남긴다.

## 추천 항목 실행 체크리스트

- [ ] `1단계(7일)` : locale routing, ICU message, fallback, RTL smoke 적용 대상을 1개로 좁힌다.
- [ ] `2단계(30일)` : 증거(message compile, placeholder diff, pseudo-loc screenshot, hreflang 검사)를 PR, ADR, 회고 중 한 곳에 연결한다.
- [ ] `3단계(60일)` : missing key, overflow defect, locale SEO mismatch가 기준 안에 들어왔는지 확인한다.
- [ ] `문제 대응` : 미달성 사유와 다음 조치, 중단 여부를 같은 기록에 남긴다.

## 추천 항목 실행 운영 규칙

- `실행 게이트` : 번역 전에 변수, plural, fallback 규칙이 구조화됐는지 확인한다.
- `승인 체계` : i18n 오너가 영향 범위와 rollback 담당자를 적용 전에 확인한다.
- `재개 조건` : pseudo-loc/RTL smoke와 SEO metadata가 통과하면 locale을 공개한다.
- `정지 조건` : placeholder 깨짐이나 hard-coded text가 남으면 release를 막는다.
- `리스크 점수` : 지원 locale 수, 법적 문구, RTL 여부로 산정한다.
- `리더 승인자` : 글로벌 UX 리드가 최종 승인 책임을 맡는다.
- `승인 역할` : 국제화 작성자, 검토자, 운영 확인자를 분리해 기록한다.
- `재평가 주기` : locale 추가와 copy 변경 때마다 QA 샘플을 갱신한다.
