DevOps / CI·CD 2026년 5월 7일

2026-05-07 iOS String Catalog(xcstrings) 로컬라이제이션 CI 게이트임대 Apple Silicon 클라우드 Mac (HK / JP / KR / SG / US)

MacXCode Engineering Team 2026년 5월 7일 약 24분

스트링 드리프트는 조용히 App Store 제출을 망칩니다: 영어 스크린샷은 멀쩡해 보이지만 말줄임, 복수형 규칙 누락, 오래된 변형 문자열은 QA가 기기에서 언어를 바꿀 때까지 드러나지 않습니다. Xcode String Catalog(.xcstrings)가 이를 한곳에 모으지만, 홍콩·도쿄·서울·싱가포르·미국에서 Mac mini M4를 임대하는 팀도 CI 계약이 필요합니다—PR마다 카타로그 검증, 번역가용 XLIFF 내보내기, 충돌 감지 가져오기, 비즈니스 중요 로케일마다 자동 UI 패스 최소 1회. 이 2026-05-07 글은 릴리스 노트에 없는 운영 세부—로케일을 12개 이상 추가해도 xcodebuild를 빠르게 유지하는 방법, 병렬 레인 한계와의 정렬, 로컬라이즈 자산 재생성 시 DerivedData 팽창 방지를 위해 작업별 격리를 설명합니다. 같은 호스트에서 의존성 해석도 한다면 SwiftPM 캐시 위생과 함께 적용해 릴리스 주간에 내보내기와 패키지 해결 큐가 NVMe에서 경쟁하지 않게 하세요.

로컬라이즈가 파이프라인에서 마지막으로 깨지는 이유

기능 테스트는 영어로 통과합니다. 마케팅은 저장소에 닿지 않는 카피로 승인합니다. 번역 업체에는 돌아올 때쯤 이미 오래된 ZIP이 갑니다. String Catalog가 프로세스를 자동으로 고치지는 않지만 Git에서 diff 할 단일 아티팩트를 줍니다. CI의 역할은 빠진 키·깨진 복수형·잘못된 플레이스홀더를 컴파일 오류만큼 크게 알리는 것입니다.

고정: PR에서 도입된 키에 대해 필수 로케일 중 하나라도 번역이 없으면 머지 차단—단위 테스트 실패와 동일하게 취급합니다.

xcstrings와 흩어진 .strings / stringsdict

레거시 레이아웃은 번역을 수십 파일로 나누어 삭제를 놓칩니다. .xcstrings는 메타데이터·상태·변형을 묶어 자동화하기 쉽지만 머지 충돌 표면이 넓어집니다. 마이그레이션 중에는 어떤 타깃이 여전히 레거시를 쓰는지 인프라 저장소에 호환 매트릭스를 유지하세요. 이중 소스는 빨리 제거—같은 키에 병렬 포맷은 git blame을 망칩니다.

GitHub/GitLab에서 강제할 수 있는 품질 게이트

  • 구문 검증 — 릴리스와 같은 DEVELOPER_DIR로 카탈로그 컴파일.
  • 키 커버리지 — 티어 1 목록 로케일에서 NEW_KEY 상태가 translated가 아니면 실패.
  • 플레이스홀더 일치%@, %d, 위치 인자 불일치 거부.
  • 스크린샷 Lint — 선택 사항이나 스크린샷 테스트를 쓰면 비영어 로케일을 야간에 1회 실행.

헤드리스 빌더용 가져오기 / 내보내기 런북

SSH만 있다고 가정하고 GUI 대신 반복 가능한 명령을 씁니다:

xcodebuild -exportLocalizations -project YourApp.xcodeproj -localizationPath ./exports xcodebuild -importLocalizations -project YourApp.xcodeproj -localizationPath ./imports

내보내기는 IPA 내보내기 및 ASC 업로드와 같은 NVMe 볼륨에 두어 서명과 로컬라이즈 자동화에서 권한과 umask를 일치시킵니다. 항상 전용 CI 사용자로 실행하고 root는 쓰지 마세요—TCC 결정을 유지합니다.

XLIFF 왕복 위생

번역가에게는 안정적인 ID가, 엔지니어에게는 결정적인 가져오기가 필요합니다. XLIFF는 버전 관리 또는 객체 저장소에 체크섬 태그와 함께 보관합니다. 베이스 카탈로그에 없는 키를 바꾸는 가져오기는 거부하고, 리뷰어가 의존하는 note 필드를 제거하는 파일도 거부합니다. 여러 지역이 변형을 추가할 때(예 zh-Hans vs zh-Hant) 비즈니스 규칙을 YAML에 두어 CI가 추측하지 않게 합니다.

머지 팁: XLIFF 충돌은 코드 충돌처럼 다루세요—플레이스홀더를 조정하지 않고 “둘 다”를 가져오지 마세요. UI 크래시는 App Store 리뷰보다 막는 편이 쌉니다.

복수형, 기기, 폭 변형

현대 앱은 워치 컴플리케이션, Dynamic Type 스크린샷, Shortcuts 문자열 등 기기별 폭이 필요합니다. 카탈로그는 변형을 지원하지만 QA 매트릭스에 있어야 합니다. 어떤 변형이 필수이고 어떤 것이 가능하면인지 문서화하고 CI 임계값에 반영—그렇지 않으면 엔지니어가 머지를 위해 모두 needs_review로 표시합니다.

호스트를 녹이지 않고 병렬 로케일 매트릭스

로케일을 추가할 때마다 UI 흐름을 XCTest하면 자산 작업이 배로 듭니다. 호스트당 동시 목적지 상한은 병렬 xcodebuild 작업과 같은 큐 규율을 따르세요. 샤딩을 권장: 레인 A는 동아시아, B는 유럽, C는 RTL 스모크. 샤드별 실시간을 기록하고 분기별로 p95가 25% 이상 늘면 번역팀과 가까운 지역에 두 번째 임대 노드를 추가합니다.

디스크, DerivedData, 로컬라이즈 캐시

내보내기와 가져오기는 수천 개의 작은 파일을 건드려 APFS 메타데이터를 바쁘게 합니다. 전체 내보내기 전에 빌더 볼륨에 최소 18% 여유를 두고, 이전 XLIFF 드롭은 DerivedData 옆에 쌓지 말고 콜드 스토리지로 보관합니다. TMPDIR과 xcresult 격리를 따라 로컬라이즈 작업이 다른 파이프라인의 아티팩트를 지우지 못하게 합니다.

내부에 공표할 수 있는 수치 목표

  • 릴리스 후보 태그 전 티어 1 로케일 100% 커버리지.
  • 카탈로그에서 14일 넘게 미해결인 stale0.
  • 일반적인 PR에서 증분 로컬라이즈 검증 12분 미만.

스트링 동결 전 9단계 체크리스트

  1. 제품 카피 동결, 커밋 SHA와 함께 벤더에 통지.
  2. 릴리스 브랜치에서 베이스라인 XLIFF 내보내기.
  3. App Store 빌드와 동일한 Xcode로 카탈로그 검증.
  4. 벤더 파일을 일회용 브랜치로 가져와 JSON 상태 diff.
  5. LTR, RTL, CJK 로케일에서 UI 스모크.
  6. 인앱 텍스트와 동기화한다면 App Store 메타데이터 문자열 확인.
  7. du -sh로 로컬라이즈 디렉터리 스냅샷—NVMe 회귀 추적.
  8. 머지에 태그하고 규정 준수 아카이브용 체크섬 매니페스트 첨부.
  9. needs_review에 대한 릴리스 후 감사 일정.

FAQ: App Store 검토, CI 사용자, 하이브리드 Pod

질문 실무 답변 (2026-05-07)
CocoaPods와 SPM 하이브리드 저장소에 추가 단계가 필요한가요? 예—의존성 해결 후 로컬라이즈하여 생성 번들이 준비되게 하세요. 순서는 SwiftPM vs CocoaPods를 참고합니다.
작은 오타 수정만이면 UI 테스트를 건너뛸 수 있나요? 변경이 공백만이고 정책 봇이 증명할 때만—그렇지 않으면 비영어 스모크를 최소 1회 실행합니다.

로컬라이즈 부하가 큰 CI에 Mac mini M4·1–2 TB가 맞는 이유

로컬라이즈 파이프라인은 메타데이터 랜덤입니다: 수천 개의 작은 파일이 이미 xcodebuild test를 실어 나르는 것과 같은 NVMe 컨트롤러를 두드립니다. MacXCode의 베어메탈 Mac mini M4 노드는 지연을 예측 가능하게 유지해 게이트가 번역 처리량을 재고—클라우드 이웃 소음이 아닙니다. 용량 계획이 또 다른 빌더를 요청하면 HK / JP / KR / SG / US지역별 요금을 인용하고, 번역 벤더가 릴리스 엔지니어와 함께 SSH할 수 있게 도움말에 온보딩을 두세요.

다음 로컬라이즈 물결 전 NVMe 여유 확보

Mac mini M4 · HK / JP / KR / SG / US · SSH / optional VNC