Files

219 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 일본어 string_resource 반영 PRD
## 문서 정보
| 항목 | 내용 |
|---|---|
| 문서 상태 | 구현 기준 확정 |
| 작성일 | `2026-08-11` |
| 최종 수정일 | `2026-08-11` |
| 대상 제품 | SodaLive iOS 일본어 문자열 리소스 |
| 작성자·결정권자 | 작성자: Sisyphus / 결정권자: 제품·iOS 담당자 |
| 관련 API Contract | 해당 없음 |
| 관련 구현 계획 | `docs/20260811_일본어_string_resource_반영/plan-task.md` |
| 관련 원본 | `docs/20260811_일본어_string_resource_반영/kr_jp_string_resource.csv` |
| 관련 review | 없음 |
### 요구사항 상태
| 상태 | 의미 | 구현 처리 |
|---|---|---|
| 확정 | CSV와 현재 iOS 문자열 구조만으로 구현 기준을 정할 수 있음 | `plan-task.md`의 Task와 완료 증거로 추적 |
| 미결 | 제품·번역·키 매핑 결정이 더 필요함 | Open Questions에 기록하고 임의 구현 금지 |
| 제외 | 이번 작업에서 구현하지 않음 | Non-Goals와 Decision Log에 기록 |
### 문서 우선순위와 갱신 순서
1. CSV의 KR/JP 원문은 이 PRD의 입력 기준으로 사용한다.
2. `SodaLive/Sources/I18n/I18n.swift`의 기존 `pick(ko:en:ja:)` 구조를 우선 유지한다.
3. `{{키워드}}의 오디오`처럼 `{{...}}`, `{...}`, `n%`, `n위`, `0:00` 형태로 런타임 값이 들어가는 CSV 문구는 Swift interpolation 문구와 정규화 매칭한다.
4. CSV 셀 안의 실제 줄바꿈과 HTML br 표기는 문자열 그대로 반영하지 않고 Swift 문자열 줄바꿈 escape `\n`으로 변환한다.
5. CSV와 구현 구조가 충돌하면 Decision Log → 요구사항 → `plan-task.md` 순서로 갱신한다.
6. 확정된 결정 밖의 추정 번역, 추정 영어 문구, 추정 키는 구현하지 않는다.
## 1. Overview
`kr_jp_string_resource.csv`에 정리된 한국어-일본어 문구를 SodaLive iOS 앱의 문자열 리소스에 반영해 일본어 환경에서 사용자 노출 문구를 최신 번역으로 표시한다. 현재 앱은 `SodaLive/Sources/I18n/I18n.swift`의 하드코딩 맵과 `pick(ko:en:ja:)` 헬퍼를 통해 언어별 문자열을 선택한다. 이 작업은 코드 구현 전 PRD와 실행 계획만 작성하며, 실제 `I18n.swift` 수정은 후속 승인 후 진행한다.
## 2. Problem Statement
현재 사용자는 다음 문제를 겪는다.
- 일본어 번역 CSV가 앱 문자열 리소스에 아직 반영되지 않아 일본어 UI 문구가 최신 번역 기준과 다를 수 있다.
- CSV에는 개행 문구, placeholder 문구, 오탈자 후보가 섞여 있어 임의 치환 시 포맷 깨짐이나 잘못된 일본어 노출 위험이 있다.
- `I18n.swift``ko`, `en`, `ja`를 함께 요구하므로 CSV에 없는 영어 문구를 임의 생성하면 기존 영어 UX가 변할 수 있다.
문제를 해결했다는 판단은 CSV의 확정 가능한 JP 값이 `I18n.swift`에 반영되고, 일본어 선택 시 해당 문구가 표시되며, 빌드가 성공하는 것으로 한다.
## 3. Goals
### 3.1 제품 목표
- CSV 데이터 242행 중 기존 한국어 리소스가 확인된 KR/JP 문구만 iOS 일본어 문자열에 반영한다.
- 기존 `I18n.swift`에 동일 KR 문구가 있거나 placeholder 정규화 후 같은 문구로 판정되는 항목은 기존 `en` 값을 유지하고 `ja` 값만 CSV 기준으로 갱신한다.
- 동일 KR 문구가 없는 CSV 항목은 신규 리소스로 추가하지 않는다.
- 개행 33행과 placeholder 유사 12행은 기존 한국어 리소스가 있는 경우에만 CSV 셀 안의 실제 줄바꿈을 Swift 문자열 `\n`으로 변환하고 함수 인자 순서를 보존해 반영한다.
- CSV에 HTML br 표기가 있으면 literal이 아니라 Swift 문자열 `\n`으로 변환해 반영한다.
- 같은 KR 또는 같은 정규화 KR이 여러 `I18n` 항목에 중복되어 있고 기존 JP가 서로 다르면 CSV JP를 우선해 같은 값으로 반영한다.
### 3.2 UX 목표
- 일본어 환경에서 홈, 콘텐츠, 대화, 마이페이지, 인증, 구매, 보관함 등 CSV가 포함한 주요 화면 문구가 자연스럽게 표시된다.
- placeholder가 포함된 문구는 실제 값 삽입 후 일본어 문장 순서가 깨지지 않는다.
- CSV의 `しいシリーズ` 오탈자 후보는 `新しいシリーズ`로 보정해 반영한다.
## 4. Non-Goals
- 이번 요청에서는 코드, 리소스, Xcode 프로젝트 설정을 수정하지 않는다.
- String Catalog(`.xcstrings`) 도입이나 `I18n.swift` 구조 개편은 하지 않는다.
- CSV에 없는 영어 번역을 새로 작성하지 않는다.
- 기존 한국어 리소스가 없는 CSV 항목을 신규 리소스로 추가하지 않는다.
- 서버 API, CMS, 백엔드 번역 리소스는 변경하지 않는다.
- 일본어 폰트, 레이아웃, 줄바꿈 UI 디자인 조정은 이 작업의 범위가 아니다.
## 5. Target Users and Permissions
| 사용자 | 목표 | 주요 작업 | 사용 환경 |
|---|---|---|---|
| 일본어 앱 사용자 | 일본어 UI 문구를 최신 번역으로 확인 | 앱 탐색, 콘텐츠 소비, 대화, 구매, 인증 | iOS 앱, 언어 설정 `ja` 또는 시스템 일본어 |
| iOS 개발자 | CSV 기준으로 안전하게 문자열 반영 | 문자열 매핑, 빌드 검증, 수동 QA | Xcode, `SodaLive.xcworkspace` |
| 제품·번역 담당자 | 확정된 일본어 반영 범위 확인 | 오탈자 보정과 제외 기준 승인 | PRD/계획문서 리뷰 |
권한 요구사항은 해당 없음이다. 단, 인증/구매/성인 관련 문구는 실제 기능 동작을 바꾸지 않고 표시 문자열만 바꾼다.
## 6. 핵심 사용자 흐름
1. 사용자가 앱 언어를 일본어로 설정하거나 시스템 언어가 일본어인 상태에서 앱을 실행한다.
2. 앱은 `LanguageHeaderProvider.current` 결과가 `ja`일 때 `I18n.pick`의 일본어 문자열을 선택한다.
3. 사용자는 홈, 콘텐츠, 대화, 마이페이지, 인증/구매 화면에서 CSV 기준 일본어 문구를 본다.
4. placeholder 문구는 실제 크리에이터명, 이메일, 요일, 퍼센트 등 런타임 값과 함께 자연스럽게 표시된다.
## 7. 정보 구조와 라우팅
별도 route 변경은 없다. 문자열 반영 대상은 기존 화면과 모듈에 종속된다.
```text
SodaLive/Sources/I18n/I18n.swift
I18n.Module.ScreenOrDomain.Role
```
역할 중심 키 이름을 유지한다. 이번 작업에서는 기존 한국어 리소스가 없는 CSV 항목의 신규 키를 추가하지 않으며, 공통 네임스페이스 승격도 하지 않는다.
## 8. 기능 요구사항
### 8.1 CSV 입력과 매핑
| ID | 상태 | 요구사항 | 수용 기준 | 계약/Goal 연결 |
|---|---|---|---|---|
| `JSR-001` | 확정 | `kr_jp_string_resource.csv``KR`, `JP` 컬럼을 입력 기준으로 사용한다. | CSV가 242개 데이터 행, KR 누락 0건, JP 누락 0건으로 파싱된다. | `P1-T1` |
| `JSR-002` | 확정 | 기존 `I18n.swift`에 동일 KR literal이 있거나 placeholder 정규화 후 매칭되는 항목은 `ja` 값만 CSV 기준으로 갱신한다. | 기존 `en` 값과 호출부는 변경되지 않는다. 현재 스캔 기준 exact 103행, placeholder 정규화 추가 0행으로 총 103행이 매핑 후보다. | `P1-T2`, `P2-T1` |
| `JSR-003` | 제외 | 동일 KR literal 또는 placeholder 정규화 매칭이 없는 139개 CSV 항목은 신규 키로 추가하지 않는다. | 기존 한국어 리소스가 없는 항목은 `I18n.swift`와 호출부를 변경하지 않는다. | `P1-T3`, `P2-T2` |
| `JSR-004` | 확정 | CSV 셀 안의 실제 줄바꿈과 HTML br 표기는 Swift 문자열 줄바꿈 escape `\n`으로 변환한다. | 일본어 `\n` 위치가 CSV와 동일하거나 제품 승인된 위치로 반영되며, HTML br 표기가 앱 문자열에 그대로 남지 않는다. | `P2-T1` |
| `JSR-005` | 확정 | placeholder 유사 12개 문구는 앱 내에서 변경 가능한 리소스 후보로 보고 Swift interpolation과 정규화 매칭한다. | 정규화 매칭되는 기존 리소스는 Swift 함수 인자 순서를 보존해 반영하고, 정규화 후에도 기존 리소스가 없으면 신규 키를 추가하지 않고 제외한다. | `P1-T3`, `P2-T1` |
| `JSR-006` | 확정 | CSV의 `しいシリーズ` JP 오탈자는 `新しいシリーズ`로 보정한다. | 해당 KR이 기존 한국어 리소스와 매칭될 때만 보정 JP를 반영한다. | `P1-T3`, `P2-T1` |
| `JSR-007` | 확정 | 같은 KR 또는 같은 정규화 KR이 여러 `I18n` 항목에 중복되어 있고 기존 JP가 다르면 CSV JP를 우선한다. | 현재 스캔 기준 중복 KR의 기존 JP 상이 항목 12건은 CSV JP로 통일한다. | `P1-T2`, `P2-T1` |
### 8.2 품질과 검증
| ID | 상태 | 요구사항 | 수용 기준 | 계약/Goal 연결 |
|---|---|---|---|---|
| `QA-001` | 확정 | 문자열 변경 후 두 앱 스킴 Debug 빌드를 실행한다. | `SodaLive`, `SodaLive-dev` Debug 빌드가 `** BUILD SUCCEEDED **`로 끝난다. | `P2-GATE` |
| `QA-002` | 확정 | 테스트 스킴 제약을 확인한다. | 테스트 액션 미구성 상태면 실패가 코드 실패가 아님을 Progress에 기록한다. | `P2-GATE` |
| `QA-003` | 확정 | 일본어 언어 선택 상태에서 대표 화면 수동 QA를 수행한다. | CSV 대표 문구, 개행, placeholder 표시를 스크린별로 확인하고 결과를 Progress에 남긴다. | `P2-GATE` |
| `QA-004` | 확정 | 민감 정보나 SDK 입력값을 번역 대상으로 오인하지 않는다. | 인증 토큰, API path, Bootpay/SDK 고정값은 변경하지 않는다. | `P2-T1` |
## 9. UI/UX Expectations
- 기존 화면 레이아웃과 컴포넌트 구조를 유지한다.
- 일본어 번역이 길어져도 이번 작업에서는 레이아웃을 임의 조정하지 않는다. 잘림이 발견되면 후속 UI 이슈로 기록한다.
- 개행이 포함된 문구는 CSV 의도를 우선하고, 화면에서 부자연스러운 경우 제품·번역 담당자 확인 후 보정한다.
## 10. API 계약
해당 없음. 이 작업은 클라이언트 로컬 문자열 리소스 반영이다.
## 11. 보안과 데이터 취급
- 인증 헤더, 토큰 저장소, `UserDefaultsKey.token` 관련 로직은 변경하지 않는다.
- 이메일 placeholder 문구는 예시 이메일을 문서나 테스트 fixture에 하드코딩하지 않는다.
- 구매/결제 SDK에 전달되는 고정 문자열은 사용자 노출 문구가 아닌 경우 번역하지 않는다.
## 12. 성능과 품질 요구사항
- 런타임 성능 요구사항은 변경하지 않는다.
- 신규 dependency를 추가하지 않는다.
- 문자열 선택 방식은 기존 `I18n.pick` 구조를 유지한다.
- 검증은 정적 매핑 점검, Xcode 빌드, 일본어 대표 화면 수동 QA로 수행한다.
## 13. 성공 기준
### 13.1 기능 수용 기준
- [x] CSV 242행의 처리 상태가 `기존 키 갱신`, `placeholder 정규화 후 기존 키 갱신`, `오탈자 보정 후 기존 키 갱신`, `기존 리소스 없음으로 제외` 중 하나로 분류된다.
- [x] 확정 항목의 일본어 문구가 `I18n.swift`에 반영된다.
- [x] placeholder와 개행 문구가 깨지지 않는다.
- [x] CSV 셀 안의 실제 줄바꿈과 HTML br 표기는 문자열 그대로가 아니라 Swift 문자열 `\n`으로 반영된다.
- [x] 중복 KR 또는 중복 정규화 KR의 JP는 CSV JP 우선으로 정리된다.
- [x] 기존 한국어 리소스가 없는 항목은 구현하지 않고 제외 사유가 문서화된다.
### 13.2 품질 수용 기준
- [x] `SodaLive` Debug 빌드가 성공한다.
- [x] `SodaLive-dev` Debug 빌드가 성공한다.
- [x] 테스트 액션 실행 가능 여부와 결과가 기록된다.
- [x] 일본어 언어 설정에서 대표 화면 수동 QA가 완료된다.
### 13.3 추적성 완료 기준
- [x] 모든 확정 요구사항이 `plan-task.md`의 Goal과 연결된다.
- [x] 모든 제외 항목에 제외 근거와 영향 Goal이 있다.
- [x] 구현 결과와 검증 기록은 `plan-task.md` Progress에 누적된다.
## 14. Open Questions
| ID | 상태 | 결정 필요 사항 | 현재 권고 | 결정 주체 | 결정 기한/시점 | 영향 Goal |
|---|---|---|---|---|---|---|
| `OQ-001` | 확정 | CSV 물리 line 281~283의 JP `最近見たシリーズはありません。\nしいシリーズを見つけましょう`에서 `しいシリーズ`가 오탈자인지 확인이 필요했다. | `新しいシリーズを見つけましょう!`로 보정한다. | 사용자 | 확정 완료 | `P1-T3`, `P2-T1` |
| `OQ-002` | 확정 | `{{장르}}`, `{{크리에이터이름}}`, `{email}`, `{요일}`, `n%`, `n위`, `0:00` 토큰을 Swift 함수 인자로 변환할지 결정이 필요했다. | 기존 한국어 리소스가 있는 항목만 함수 인자로 변환하고, 기존 한국어 리소스가 없는 항목은 반영하지 않는다. | 사용자 | 확정 완료 | `P1-T3`, `P2-T1` |
| `OQ-003` | 확정 | CSV KR 원문 중 `메세지`, `메거진` 같은 한국어 오탈자 후보를 보정할지 결정이 필요했다. | 한국어 리소스는 보정하지 않고 JP만 반영한다. | 사용자 | 확정 완료 | `P1-T3`, `P2-T1` |
| `OQ-004` | 확정 | 기존 `I18n.swift`에 동일 KR literal이 없는 139개 항목을 신규 키로 추가할지 결정이 필요했다. | 기존 한국어 리소스가 없는 항목은 추가하지 않는다. | 사용자 | 확정 완료 | `P1-T3`, `P2-T2` |
| `OQ-005` | 확정 | 신규 키 추가 시 CSV에 없는 `en` 값을 어떻게 채울지 결정이 필요했다. | 없는 리소스는 추가하지 않으므로 신규 `en` 작성도 하지 않는다. | 사용자 | 확정 완료 | `P2-T2` |
| `OQ-006` | 확정 | `{{키워드}}의 오디오`처럼 `{{...}}` 형태로 들어간 CSV 문구를 기존 앱 리소스 매핑 후보로 볼지 결정이 필요했다. | 앱 내에서 변경 가능한 리소스이므로 Swift interpolation 문구와 정규화 매칭한다. | 사용자 | 확정 완료 | `P1-T2`, `P2-T1` |
| `OQ-007` | 확정 | 중복 KR 항목의 기존 JP가 서로 다를 때 어떤 값을 우선할지 결정이 필요했다. | CSV JP를 우선 반영한다. | 사용자 | 확정 완료 | `P1-T2`, `P2-T1` |
| `OQ-008` | 확정 | CSV에 HTML br 표기가 있을 때 앱 문자열에 그대로 반영할지 결정이 필요했다. | HTML br 표기는 literal이 아니라 Swift 문자열 줄바꿈 `\n`으로 변환한다. | 사용자 | 확정 완료 | `P1-T1`, `P2-T1` |
| `OQ-009` | 확정 | CSV 셀 안의 실제 줄바꿈을 앱 문자열에 어떤 형태로 반영할지 결정이 필요했다. | CSV 실제 줄바꿈은 Swift 문자열 줄바꿈 escape `\n`으로 변환한다. | 사용자 | 확정 완료 | `P1-T1`, `P2-T1` |
## 15. 요구사항 추적표
| 요구사항 범위 | API Contract | 계획 Phase | Goal | 자동 검증 | 수동 검증 |
|---|---|---:|---|---|---|
| `JSR-001` | 해당 없음 | 1 | `P1-T1` | CSV 파싱 명령 | CSV 행 수와 누락 확인 |
| `JSR-002` | 해당 없음 | 1, 2 | `P1-T2`, `P2-T1` | KR literal 매칭 스크립트, 빌드 | 일본어 대표 화면 확인 |
| `JSR-003~007` | 해당 없음 | 1, 2 | `P1-T2`, `P1-T3`, `P2-T1`, `P2-T2` | placeholder 정규화/개행/중복 JP 점검 스크립트 | 제외 목록과 보정 JP 리뷰 |
| `QA-001~004` | 해당 없음 | 2 | `P2-GATE` | `xcodebuild` | 언어 설정 `ja` 수동 QA |
## 16. Decision Log
| 날짜 | ID | 상태 | 결정 | 근거 | 영향 요구사항·계약·Goal |
|---|---|---|---|---|---|
| `2026-08-11` | `DEC-001` | 확정 | 이번 요청에서는 PRD와 `plan-task.md`만 생성하고 앱 코드는 수정하지 않는다. | 사용자 직접 지시 | 전체 |
| `2026-08-11` | `DEC-002` | 확정 | 일본어 문자열 반영의 기본 대상은 `SodaLive/Sources/I18n/I18n.swift`로 둔다. | 현재 코드의 `I18n.pick(ko:en:ja:)` 구조 확인 | `JSR-002`, `P2-T1` |
| `2026-08-11` | `DEC-003` | 폐기 | 신규 키 추가는 영어 기준과 호출부가 확인된 항목으로 제한한다. | 사용자 결정으로 기존 한국어 리소스가 없는 항목은 추가하지 않기로 변경 | `JSR-003`, `OQ-004`, `OQ-005` |
| `2026-08-11` | `DEC-004` | 확정 | `しいシリーズ``新しいシリーズ`로 보정한다. | 사용자 확인 | `JSR-006`, `OQ-001`, `P2-T1` |
| `2026-08-11` | `DEC-005` | 확정 | placeholder 문구는 기존 한국어 리소스가 있는 항목만 Swift 함수 인자로 변환한다. | 사용자 결정 | `JSR-005`, `OQ-002`, `P2-T1` |
| `2026-08-11` | `DEC-006` | 확정 | 한국어 리소스 원문은 보정하지 않고 JP만 반영한다. | 사용자 결정 | `OQ-003`, `P2-T1` |
| `2026-08-11` | `DEC-007` | 확정 | 기존 한국어 리소스가 없는 CSV 항목은 신규 리소스로 추가하지 않는다. | 사용자 결정 | `JSR-003`, `OQ-004`, `OQ-005`, `P2-T2` |
| `2026-08-11` | `DEC-008` | 확정 | `{{...}}`, `{...}`, `n%`, `n위`, `0:00` 형태 placeholder는 Swift interpolation과 정규화해 매핑 후보를 판정한다. | 사용자 결정과 재스캔 결과 | `JSR-002`, `JSR-005`, `OQ-006`, `P1-T2` |
| `2026-08-11` | `DEC-009` | 확정 | 같은 KR 또는 같은 정규화 KR의 기존 JP가 여러 값이면 CSV JP를 우선 반영한다. | 사용자 결정과 중복 JP 재스캔 결과 | `JSR-007`, `OQ-007`, `P2-T1` |
| `2026-08-11` | `DEC-010` | 확정 | HTML br 표기는 앱 문자열에 그대로 반영하지 않고 줄바꿈 `\n`으로 변환한다. | 사용자 결정 | `JSR-004`, `OQ-008`, `P2-T1` |
| `2026-08-11` | `DEC-011` | 확정 | CSV 셀 안의 실제 줄바꿈은 Swift 문자열 줄바꿈 escape `\n`으로 변환한다. | 사용자 결정 | `JSR-004`, `OQ-009`, `P2-T1` |
## 17. 변경 관리
요구사항 변경 시 다음을 확인한다.
- [x] Decision Log에 변경 이유와 날짜를 기록했다.
- [x] 관련 요구사항 상태·본문·수용 기준을 갱신했다.
- [x] `plan-task.md`의 범위·Files·Interfaces·체크박스·완료 증거를 코드 변경 전에 갱신했다.
- [x] 기존 Progress와 검증 기록을 삭제하거나 덮어쓰지 않았다.