
게임 내 텍스트와 UI 다국어화: 처음부터 흔들리지 않는 I18N 설계
게임의 텍스트와 UI를 여러 언어로 확장할 때 필요한 키 설계, 문장 조립 방지, 레이아웃 대응, 검수 흐름을 정리합니다. 출시 직전 번역을 붙이는 방식에서 자주 생기는 문제도 함께 짚습니다.
다국어화는 번역 파일을 추가하는 일이 아니다
게임 다국어화는 문자열을 다른 언어로 바꾸는 작업만을 뜻하지 않는다. 문장 구조, 글자 수, 문화권별 표기, 입력 방식, 화면 배치까지 함께 설계해야 한다. 초기에 이를 분리하지 않으면 번역이 늘어날수록 코드 수정과 UI 예외 처리가 빠르게 쌓인다.
가장 중요한 원칙은 플레이어에게 보이는 문장을 코드에서 직접 만들지 않는 것이다. 코드에는 의미를 나타내는 키와 필요한 값만 남기고 각 언어의 문장은 로컬라이제이션 데이터가 책임지게 한다.
키는 문구가 아니라 의미를 표현한다
"Start Game"처럼 원문 문장을 키로 쓰면 문구 변경과 번역 관리가 얽힌다. 대신 화면과 기능의 의미가 드러나는 안정적인 키를 사용한다.
{
"menu.start": "게임 시작",
"menu.settings": "설정",
"battle.turn.remaining": "남은 턴: {count}",
"inventory.item_count": "아이템 {count}개"
}
키는 다음 기준으로 정하면 유지보수가 편하다.
- 화면 또는 기능을 앞에 둔다. 예:
menu,battle,quest - 같은 의미의 문구는 한 키를 공유한다.
- 우연한 화면 위치가 아니라 역할을 이름에 담는다. 예:
button.confirm - 번역가가 이해하기 어려운 축약어와 내부 구현명은 피한다.
문구가 바뀌어도 키를 무조건 새로 만들 필요는 없다. 의미가 같은 표현을 다듬는 정도라면 기존 키를 유지한다. 반대로 버튼의 역할 자체가 바뀌었다면 새 키로 분리하는 편이 안전하다.
문장을 코드에서 이어 붙이지 않는다
한국어에서는 자연스러운 문장이 영어권 언어에서 어순이 바뀌거나 단복수 표현이 달라질 수 있다. 그래서 아래 방식은 처음에는 간단해 보여도 언어가 추가될수록 문제가 된다.
// 피해야 할 방식
message.text = playerName + "님이 " + gold + " 골드를 획득했습니다.";
플레이스홀더를 사용해 언어별 문장 전체를 번역 데이터에 둔다.
{
"reward.gold_received": "{playerName}님이 골드 {gold}을(를) 획득했습니다.",
"reward.gold_received.en": "{playerName} received {gold} gold."
}
message.text = t("reward.gold_received", {
playerName,
gold
});
조사까지 완전히 자연스럽게 처리해야 하는 한국어 문장이라면 표시 이름과 조사를 분리한 규칙이 필요할 수 있다. 다만 이런 규칙을 모든 문구에 강제하기보다 문장 자체를 바꿔 조사가 필요 없는 표현으로 해결할 수 있는지 먼저 검토하는 편이 좋다.
복수형도 단순히 {count}개를 붙이는 방식으로 일반화하면 안 된다. 언어마다 복수 규칙이 다르므로 사용하는 I18N 라이브러리의 복수형 기능을 이용하거나 언어별 형식화 규칙을 명시적으로 둔다.
UI는 번역된 뒤의 크기를 기준으로 만든다
영어와 비교하면 독일어·러시아어처럼 길어지는 언어가 있고 중국어·일본어처럼 짧아지지만 줄바꿈 규칙이 달라지는 언어도 있다. 버튼과 패널의 고정 폭을 전제로 하면 특정 언어에서 텍스트가 잘리거나 서로 겹친다.

실무에서는 다음 대응이 효과적이다.
- 버튼은 가능하면 내용 기준의 최소 크기와 여백을 사용한다.
- 텍스트 영역에는 줄바꿈, 최대 줄 수, 넘침 처리 정책을 정한다.
- 아이콘만으로 의미가 불명확한 조작에는 텍스트 또는 접근성 이름을 함께 제공한다.
- 숫자와 날짜는 문자열 결합 대신 로케일 형식화 기능으로 표시한다.
- 오른쪽에서 왼쪽으로 읽는 언어를 지원할 계획이라면 정렬, 아이콘 방향, 진행 표시의 반전 가능성을 초기에 점검한다.
특히 확인, 취소, 장비 관리처럼 자주 쓰는 버튼은 실제 번역문을 넣은 상태에서 확인해야 한다. 가짜 영어 문구만으로는 레이아웃 위험을 발견하기 어렵다.
데이터 흐름을 하나로 통일한다
UI마다 번역 파일을 제각각 읽거나 런타임에 원문을 직접 치환하면 누락을 찾기 어렵다. 언어 선택부터 키 조회, 형식화, 화면 렌더링까지 경로를 통일하면 진단 지점도 명확해진다.
flowchart LR
A[언어 설정] --> B[로컬라이제이션 로더]
B --> C[키와 번역 데이터]
C --> D[변수·복수형·날짜 형식화]
D --> E[UI와 대사 렌더링]
C --> F[누락 키 검사]
누락 키를 발견했을 때 빈 문자열을 보여 주는 것은 좋지 않다. 개발 빌드에서는 눈에 띄는 대체 표기와 로그를 남기고 출시 빌드에서는 기준 언어 문구로 안전하게 대체하는 정책을 정한다. 다만 기준 언어로 대체된 문구도 품질 문제이므로 수집 대상에서 제외하면 안 된다.
function localizedText(key: string, params?: Record<string, unknown>) {
const value = dictionary[currentLocale]?.[key] ?? dictionary[defaultLocale]?.[key];
if (!value) {
reportMissingLocalization(key, currentLocale);
return `[${key}]`;
}
return formatMessage(value, params);
}
번역가에게 맥락을 제공한다
같은 단어라도 UI 버튼인지, 아이템 이름인지, 튜토리얼 문장인지에 따라 번역이 달라진다. Save는 저장 동작일 수도 있고 저장 파일일 수도 있다. 키만 전달하면 번역가는 추측해야 한다.
번역 관리 데이터에는 가능한 한 다음 정보를 함께 둔다.
- 화면 또는 사용 위치
- 글자 수 제한과 줄 수 제한
- 변수의 의미와 예시 값
- 성별, 복수형, 존댓말처럼 문법에 영향을 주는 조건
- 스크린샷 또는 UI 미리보기 링크
예를 들어 {count}가 적의 수인지 보상 수량인지 설명이 없으면 적절한 단위와 문장을 고르기 어렵다. 설명 필드는 번역 품질뿐 아니라 나중에 팀원이 문구를 수정할 때도 도움이 된다.
출시 전에는 언어별로 확인한다
자동 검사와 실제 플레이 검수는 서로 대체할 수 없다. 자동 검사는 누락 키, 사용하지 않는 키, 잘못된 변수 이름, 형식 오류를 빠르게 찾는다. 반면 실제 플레이에서는 잘림, 줄바꿈, 잘못된 강조, 컷신 타이밍, 폰트 누락을 발견한다.
권장 검수 순서는 다음과 같다.
- 빌드 과정에서 모든 참조 키와 번역 데이터를 비교한다.
- 긴 번역문을 넣은 의사 로케일로 화면의 여백과 넘침을 점검한다.
- 지원 언어마다 메뉴, 전투, 인벤토리, 상점, 저장·불러오기 등 주요 화면을 순회한다.
- 대사, 튜토리얼, 시스템 알림처럼 변수와 줄바꿈이 많은 구간을 별도로 확인한다.
- 플랫폼별 폰트 렌더링과 입력 방식도 확인한다.
의사 로케일은 글자를 늘리거나 특수 문자로 감싼 테스트용 언어다. 원문이 화면에 남았는지 고정 폭 UI가 버티는지 빠르게 찾는 데 유용하다.
자주 발생하는 실수
원문을 코드에 남기는 경우
디버그 메시지, 예외 처리, 튜토리얼 팝업은 번역 대상에서 빠지기 쉽다. 플레이어에게 노출될 가능성이 있다면 모두 같은 번역 경로를 사용해야 한다.
번역문 안에 마크업을 과도하게 섞는 경우
색상 태그나 클릭 가능한 링크를 문장 내부에 무분별하게 넣으면 번역 과정에서 태그가 깨지기 쉽다. 필요한 경우 구조화된 리치 텍스트 토큰을 제공하고 번역가에게 이동 가능한 요소와 이동하면 안 되는 요소를 명확히 안내한다.
폰트와 문자 범위를 나중에 확인하는 경우
번역 데이터가 있어도 글리프가 없으면 네모 상자나 빈 글자로 표시된다. 지원 언어의 문자 범위, 폰트 라이선스, 폴백 폰트를 출시 초기에 검증해야 한다.
언어 전환을 재시작에만 묶는 경우
재시작이 필요한 엔진 구조일 수는 있다. 그러나 설정 화면에서 그 사실을 분명히 알리지 않으면 오류처럼 느껴진다. 가능하다면 언어 변경 후 UI를 즉시 다시 그리는 구조가 사용자 경험과 테스트 효율 모두에 유리하다.
마무리
좋은 I18N 설계의 핵심은 번역을 독립된 사후 작업으로 취급하지 않는 데 있다. 의미 중심 키, 완결된 문장, 확장 가능한 레이아웃, 누락을 잡는 자동 검사, 맥락을 갖춘 번역 데이터가 함께 있어야 한다. 이 기반을 초기에 마련하면 새 언어를 추가할 때 비용이 줄고 기존 언어의 문구를 개선하는 일도 훨씬 안전해진다.


