번역 한 줄 바꾸는 데 개발자를 거쳐야 했다 — 다국어 관리를 시트로 옮긴 이야기
4개 언어 서비스에서 번역이 바뀔 때마다 개발자가 JSON을 수기로 고치던 병목을, i18n SaaS 대신 '운영팀이 이미 쓰는 구글 시트'를 소스로 삼아 없앤 과정. 진짜 어려운 건 번역이 아니라 렌더링 변수였다.
번역 문구 하나를 바꾸는 데 개발자를 거쳐야 하는 구조였다. 이 글은 그 병목을 없앤 이야기다. 다만 핵심은 "자동화했다"가 아니라, 어디를 소스로 삼느냐를 어떻게 정했는가에 있다.
문제 — 번역이 개발자 병목이었다
서비스는 4개 언어(ko / en / jp / cn)로 운영 중이었다. 번역이 바뀌면 흐름은 이랬다.
- PM이 바뀐 문구를 영문으로 전달한다.
- 개발자가 중국어·일본어 번역을 확인해
JSON파일에 수기로 반영한다. - 배포한다.
문제는 2번이었다. 언어당 5~10분씩 걸렸고, 문구 수정이라는 비개발 작업이 개발자 일정에 물려 있었다. 게다가 손으로 옮기다 보니 오타·키 누락 같은 정합성 문제가 잦았다. 번역은 자주 바뀌는데, 그때마다 개발자가 붙어야 하는 구조 자체가 비용이었다.
선택지 — 세 갈래
| 안 | 방식 | 문제 |
|---|---|---|
| A | 현행 수기 JSON 유지 | 개발자 상시 개입, 정합성 취약 — 문제 그 자체 |
| B | 번역 SaaS(i18n 관리 툴) 도입 | 기능은 충분하나 도입 비용·운영팀 학습·기존 워크플로 변경 부담. 규모 대비 과함 |
| C | 구글 시트를 단일 소스로 한 자동화 | 운영팀이 이미 쓰는 도구를 소스로 — 학습 비용 0 |
B가 정석처럼 보였다. 하지만 이 서비스의 다국어 규모에서 전용 SaaS는 얻는 것보다 바꿔야 하는 게 많았다. 새 툴을 도입하면 운영팀이 그 툴을 배워야 하고, 기존 JSON 파이프라인도 그 툴 출력에 맞춰 다시 짜야 한다. 결국 출력물은 기존 JSON 구조 그대로 나와야 했다 — 소비하는 앱 코드는 그대로 둔 채로.
왜 시트였나 — 비개발자가 이미 쓰는 도구를 소스로
C를 택했다. 핵심 판단은 한 줄이다.
소스를, 개발자가 아니라 운영팀이 이미 익숙하게 쓰는 도구에 둔다.
운영팀은 구글 시트를 매일 쓴다. 그렇다면 번역의 원천을 시트로 옮기면, PM은 새 툴을 배울 필요 없이 시트에 영문만 입력하면 된다. 나머지는 파이프라인이 처리한다.
파이프라인 구조는 이렇게 잡았다.
[구글 시트] ← PM이 영문(및 검수된 번역) 입력
│ Apps Script: 빈 칸의 중·일 번역 자동 생성(초안)
▼
[시트 = 단일 소스]
│ Sheets API로 읽어 JSON 빌드 + 정합성 검증
▼
[ko/en/jp/cn JSON] → 앱이 소비 (구조 불변)자동 번역은 어디까지나 초안이라는 전제를 깔았다. 기계 번역을 그대로 배포하는 게 목적이 아니라, 개발자를 거치지 않고 운영팀이 시트에서 검수·수정할 수 있게 하는 게 목적이었다. 자동화가 지향한 건 "완벽한 번역"이 아니라 "개발자 병목 제거 + 정합성" 두 가지였다.
진짜 어려웠던 건 번역이 아니라 렌더링 변수였다
막상 들어가 보니 까다로운 쪽은 번역 텍스트 자체가 아니었다. 언어가 바뀌면 같이 흔들리는 것들이 문제였다.
- 텍스트 길이가 언어마다 다르다. 같은 문구도 언어별로 길이가 크게 달라 레이아웃이 깨졌다.
- 날짜·시간 형식이 다르다. ko와 en/jp/cn의 표기 관습이 갈린다.
- 줄바꿈·특수문자가 JSON으로 들어갈 때 이스케이프가 깨진다.
그래서 파이프라인의 무게중심은 "번역 생성"이 아니라 "변환 단계에서의 정규화·검증" 쪽에 실렸다. 시트의 값을 그대로 JSON에 붓는 게 아니라, 언어별 형식을 정규화하고 이스케이프를 안전하게 처리한 뒤 내보내는 단계를 뒀다.
정합성은 부산물이 아니라 목적이었다
수기 반영에서 가장 자주 터지던 게 키 누락과 오타였다. 어떤 언어에만 키가 빠지면, 그 언어 사용자에게만 문구가 비거나 깨진다 — 그리고 그건 대개 배포 후에 발견된다.
그래서 자동화의 목적 자체에 정합성 검증을 넣었다. 빌드 단계에서:
- 중복 키 검출 — 같은 키가 두 번 정의되면 빌드에서 잡는다.
- 필수 언어 누락 검증 — 4개 언어 중 하나라도 값이 비면 통과시키지 않는다.
// 검증의 형태(개념) — 빌드가 통과 = "네 언어 모두 채워졌다"
for (const key of allKeys) {
for (const lang of ["ko", "en", "jp", "cn"]) {
assert(entries[lang][key] != null, `누락: ${lang}/${key}`);
}
assertNoDuplicate(key);
}위 코드는 실제 구현이 아니라 검증이 하는 일을 드러내기 위한 개념 스케치다.
이렇게 하니 "사람이 조심해서" 막던 정합성을 파이프라인이 구조적으로 막게 됐다. 수기 시절엔 누락이 배포 후 버그였지만, 이제는 빌드 실패다.
정리
| 지표 | before | after |
|---|---|---|
| 번역 반영 주체 | 개발자(수기 JSON) | 운영팀(시트에서 직접) |
| 건당 소요 | 언어당 5~10분 | 1분 이내 |
| 배포 필요 | 매번 개발자·배포 | 코드 배포 없이 반영 |
| 정합성 | 사람이 조심 | 빌드가 강제(중복 키·누락 검증) |
| 새 도구 학습 | — | 없음(이미 쓰던 시트) |
돌아보면 이 일에서 배운 건 자동화 기술이 아니었다. 소스를 어디에 두느냐가 도입 비용의 대부분을 결정한다는 것이었다. 전용 SaaS가 기능은 더 좋았겠지만, 운영팀이 이미 손에 익은 도구를 소스로 삼은 덕에 "학습 없이 바로 운영"이 가능했다. 그리고 정합성은 자동화의 부산물이 아니라, 애초에 자동화가 풀려던 문제의 절반이었다.