React & Next.js에서 i18next JSON 파일 번역하는 방법 (2026)

다음 주 금요일까지 12개 언어로 출시해야 하는 React 앱을 막 완성했습니다. 로케일 파일은 public/locales/en/common.json에 있으며, 로케일당 340개의 키를 가지고 있고, 문자열 내부의 토큰은 중첩된 객체 전체에 흩어져 있는 {{userName}} 및 {{count}}와 같습니다. JSON을 ChatGPT에 붙여넣으면 {{ nombreUsuario }}와 추가 공백, 그리고 절반의 복수화 키가 이름이 변경된 채로 돌아옵니다. 앱이 빌드 시 충돌합니다.
i18next JSON 번역을 자동화하려고 시도해 본 적이 있다면 이 어려움을 아실 겁니다. JSON 형식은 유연하지만, 바로 그 때문에 대부분의 번역 도구가 이를 엉망으로 만듭니다. 진짜 문제는 언어 모델의 품질이 아니라, 일반 소비자용 AI 도구가 i18next의 구조적 규칙을 이해하지 못한다는 점입니다.
이 가이드에서는 i18next JSON이 다른 로케일 형식과 다른 점, 순진한 번역 접근 방식이 React 및 Next.js 앱을 손상시키는 이유, 그리고 모든 키를 수동으로 검토할 필요 없이 수십 개의 로케일에서 안전하게 번역을 자동화하는 방법을 설명합니다.
i18next JSON이란 무엇이며 왜 번역이 까다로운가
i18next는 JavaScript 생태계에서 가장 널리 사용되는 i18n 라이브러리입니다. React (react-i18next), Next.js (next-i18next, App Router next-intl), Vue, Node 백엔드 서비스의 기반이 됩니다. 각 로케일별로 평면 또는 중첩된 JSON 파일에 번역 가능한 문자열을 저장합니다.
일반적인 파일은 다음과 같습니다.
{
"welcome": "Welcome, {{userName}}!",
"cart": {
"empty": "Your cart is empty",
"items_one": "{{count}} item in your cart",
"items_other": "{{count}} items in your cart"
},
"errors": {
"network": "Network error. <strong>Please retry</strong>."
}
}
이는 간단해 보이지만, 세 가지 요인 때문에 범용 AI로 번역하는 것이 위험합니다.
보간 토큰은 구조적이며 텍스트가 아니다
시퀀스 {{userName}}은 단어가 아니라 런타임이 데이터로 대체하는 자리표시자입니다. 공백을 추가하거나 ({{ userName }}), 이름을 변경하거나, 내부 식별자를 번역하면 런타임이 조용히 실패하거나 오류를 발생시킵니다. 일부 번역기는 {{count}}를 스페인어로 {{conteo}}로 친절하게 변환하기도 합니다. 이렇게 되면 앱은 존재하지 않는 변수를 보간하려 시도하며, 원시 자리표시자를 사용자에게 렌더링하게 됩니다.
복수화 키는 마법의 접미사이다
i18next는 _zero, _one, _two, _few, _many, _other와 같은 접미사로 복수형을 감지합니다. 이는 임의의 문자열이 아니라 대상 로케일에 대한 CLDR 복수형 범주와 일치해야 합니다. 영어는 _one과 _other만 사용합니다. 러시아어, 아랍어, 폴란드어는 최대 6개의 범주를 사용합니다. 번역기가 _other를 삭제하거나 이름을 변경하면 대체(fallback) 체인이 깨집니다.
중첩된 키는 온전히 유지되어야 한다
평면 키-값 쌍인 Gettext .po 파일과 달리, i18next 파일은 임의로 중첩될 수 있습니다. 게으른 번역가는 구조를 평면화하거나, 번역된 텍스트와 일치하도록 키 이름을 변경하거나, 객체 순서를 재정렬할 수 있습니다. 코드 내 t('cart.items_other') 호출은 더 이상 해결되지 않습니다.
개발자들이 처음 시도하는 잘못된 해결책
모든 팀은 실제 솔루션에 투자하기 전에 동일한 3단계 실패 주기를 겪습니다.
1단계: ChatGPT에 붙여넣기
200개의 키를 ChatGPT에 복사하여 "이 JSON을 스페인어로 번역해 줘"라고 요청하고 결과를 다시 붙여넣습니다. 180개의 키는 잘 작동합니다. 하지만 20개는 {{...}} 안에 공백이 추가되고, 3개는 복수형 접미사가 다시 작성되며, 하나의 <strong> 태그가 <fuerte>로 번역됩니다. 빌드는 실패하거나, 조용히 깨진 문자열을 프로덕션으로 배포합니다.
2단계: Google Translate API
Google Translate REST API를 연결하고 JSON을 반복하며 각 값을 전송합니다. 속도는 훌륭합니다. 하지만 품질은 그렇지 않습니다. Google API는 각 문자열을 개별적으로 취급합니다. 앱에 대한 맥락이 없고, {{count}}가 자리표시자라는 이해가 없으며, cart.empty 키가 cart.items_one과 다르다는 인식이 없습니다. 여전히 모든 키에 대한 사람의 검토가 필요합니다.
3단계: 상용 TMS 플랫폼
번역 관리 시스템에 가입합니다. 이들은 단어당 요금을 부과하고, GitHub 통합을 요구하며, 월별 좌석 수에 따라 제한합니다. 사이드 프로젝트나 인디 앱의 경우 경제성이 빠르게 무너집니다. 또한 엔진이 i18next 형식을 특별히 파싱하지 않으면 동일한 자리표시자 손상 문제를 겪게 됩니다.
동일한 실패 모드는 Gettext 워크플로에서도 나타납니다. 코드 변수를 손상시키지 않고 .po 파일을 번역하는 방법에 대한 저희 가이드에서 WordPress 및 기타 Gettext 기반 스택의 유사한 문제를 다룹니다.
안전한 접근 방식: 구문 인식 번역
대규모로 i18next JSON을 번역하는 유일하게 신뢰할 수 있는 방법은 형식을 먼저 파싱하고, 구문을 고정하며, 번역 가능한 텍스트만 AI로 보내는 도구를 사용하는 것입니다.
구문 인식 처리가 내부적으로 수행하는 작업은 다음과 같습니다.
- JSON을 추상 트리로 파싱하여 키 경로와 중첩을 보존합니다.
- 보간 토큰(
{{name}},{{count, number}},{{date, datetime}})을 식별하고 자리표시자 ID로 대체합니다. - Trans 컴포넌트 내부의 HTML 태그(
<0>,<strong>,<br/>)를 식별하고 고정합니다. - 접미사를 통해 복수 키를 감지하고 대상 로케일의 CLDR 규칙에 매핑합니다.
- 정리된 텍스트만 키 경로에 대한 맥락과 함께 LLM으로 전송합니다.
- 원래 토큰과 태그를 정확한 위치에 다시 삽입합니다.
- 출력을 검증합니다. 자리표시자가 누락되거나 잘못된 형식인 경우 원본으로 되돌립니다.
이는 클라우드 기반 PO 번역을 안전하게 만드는 것과 동일한 원칙입니다. 기본 아키텍처에 대해 궁금하시다면, 저희의 AI 번역 품질 비교에서 다양한 LLM이 이러한 제약 조건을 어떻게 처리하는지 분석합니다.
단계별 가이드: SimplePoTranslate로 i18next JSON 번역하기
SimplePoTranslate는 Pro 및 Lifetime 요금제에서 i18next JSON을 기본적으로 지원합니다. 무료 티어는 현재 .po 및 .pot 파일을 지원하며, JSON 액세스를 위해서는 업그레이드하거나 평가판을 사용하세요.
1. 소스 파일 준비
영어 (또는 소스 로케일) 파일을 마스터로 사용하세요. 유효한 JSON 형식인지 확인하고 앱에서 사용하는 모든 키가 포함되어 있는지 확인하세요. 흔한 실수는 오래되었거나 사용하지 않는 키를 남겨두는 것인데, 이는 절대로 렌더링되지 않을 문자열에 대한 번역 할당량을 소모하게 됩니다.
# From your project root
cp public/locales/en/common.json ~/Desktop/common.json
2. SimplePoTranslate에 업로드
대시보드에 로그인하여 새 번역을 클릭하고 common.json을 업로드하세요. 플랫폼은 i18next 형식을 자동으로 감지합니다. 지원되는 41개 로케일 중에서 대상 언어를 선택하고, 톤(전문적, 비격식, 마케팅)을 선택한 후 제출하세요.
3. 엔진 작동
내부적으로 파일은 파싱되고, 안전한 배치로 분할되며, 병렬로 번역됩니다. 보간 토큰은 고정됩니다. 복수형 접미사는 보존되고 대상 로케일의 CLDR 규칙에 매핑됩니다. Trans 컴포넌트 내부의 HTML은 온전히 유지됩니다.
4. ZIP 다운로드
번역된 JSON과 함께 대체 형식(PHP 앱용 .php, 도구 간 호환성용 .po)을 포함하는 ZIP 파일을 받게 됩니다. JSON을 public/locales/es/common.json에 넣고 재배포하세요.
unzip common_es.zip
mv common.json public/locales/es/common.json
npm run build
5. 반복 또는 일괄 처리
12개의 모든 대상 로케일에 대해 12개의 작업을 제출하세요. Pro 요금제 할당량은 수십 개의 일반적인 SaaS 앱을 포괄합니다. 여러 네임스페이스 파일이 있는 모노레포의 경우 각 파일을 개별적으로 업로드하거나 순차적으로 일괄 처리하세요.
번역을 앱에 다시 통합하기
JSON 파일을 번역하고 나면, 통합은 쉬운 부분입니다. 몇 가지 주의할 점:
- 복수형 범주를 확인하세요. 로케일별로 간단한 스모크 테스트를 실행하세요.
count={0},count={1},count={5}로 컴포넌트를 렌더링하고 세 가지 모두 올바른 문자열을 생성하는지 확인하세요. - RTL 로케일을 확인하세요. 아랍어, 히브리어 또는 페르시아어로 번역했다면 UI에 RTL을 인식하는 CSS가 필요합니다. 저희의 WordPress RTL 번역 가이드는 React 앱에도 적용되는 CSS 패턴을 다룹니다.
- 대체 체인을 설정하세요. 키가 누락된 경우 i18next가 영어로 대체되도록 구성하여 배포 중인 상태에서 사용자에게 충돌이 발생하지 않도록 하세요.
- CI에서 소스 파일을 잠그세요.
en/common.json이 다른 로케일을 재생성하지 않고 변경되는 PR을 거부하는 검사를 추가하세요. 번역 드리프트는 프로덕션 i18n 버그의 가장 큰 단일 원인입니다.
React, Next.js 및 서버 측을 아우르는 팀의 경우, 하나의 소스에서 모든 형식을 생성하는 것은 엄청난 이점입니다. 하나의 파일 입력, 다섯 가지 형식 출력에 대한 저희 게시물에서 다중 형식 출력이 장기적인 유지 관리에 중요한 이유를 설명합니다.
JSON만으로는 부족할 때: 복잡한 사례 처리
몇 가지 예외적인 경우에는 특별한 주의가 필요합니다.
ICU MessageFormat
프로젝트에서 ICU 구문({count, plural, one {1 item} other {# items}})을 사용하는 경우, i18next는 이를 보간으로 처리하지만 구조는 더 복잡합니다. 번역 도구가 ICU 매개변수를 인식하고 one, other와 같은 범주 이름 또는 plural, number, date와 같은 형식 식별자를 번역하지 않도록 확인하세요.
React 노드가 포함된 Trans 컴포넌트
<Trans>는 번역된 문자열 내부에 React 컴포넌트를 인덱스(<0>, <1>)로 키 지정하여 렌더링합니다. 번역기는 정확한 태그 순서를 보존해야 합니다. SimplePoTranslate의 구문 잠금은 이를 처리하지만, 다른 도구를 사용하는 경우 배포 전에 확인해야 합니다.
네임스페이스 파일
대규모 앱은 로케일을 common.json, dashboard.json, checkout.json과 같은 네임스페이스로 분할합니다. 각 파일을 독립적으로 번역하세요. 병합하지 마세요. 각 네임스페이스의 키 경로가 범위 내에 유지될 때 컨텍스트 품질이 더 높습니다.
종합 정리
React 또는 Next.js 앱을 위한 i18next JSON을 번역하는 것은 최고의 AI 모델을 선택하는 것이 아닙니다. 이는 형식의 구조적 규칙을 존중하는 것입니다. 즉, 보간, 복수형 접미사, 중첩 키 및 HTML 태그가 왕복 프로세스를 손상 없이 거쳐야 합니다. 소비자용 AI 도구는 JSON을 비구조화된 텍스트로 취급합니다. 구문 인식 도구는 이를 구조화된 데이터로 파싱하고 번역 가능한 부분만 건드립니다.
다국어 앱을 출시하고 JSON을 채팅 인터페이스에 복사하여 붙여넣었다면 이미 그 비용을 알고 있을 것입니다. 즉, 로케일당 수 시간의 수동 검토, 무작위 프로덕션 버그, 그리고 점점 더 쌓여가는 깨진 복수형 형태들입니다. 형식 인식 파이프라인은 이러한 모든 실패 모드를 제거합니다.
i18next JSON 파일을 안전하게 번역할 준비가 되셨나요? SimplePoTranslate를 무료로 사용해 보세요 - 신용카드 정보가 필요 없습니다. 한 번 업로드로 41개 언어로 출시하세요.