Globalization: i18n과 앱 다국어 지원이란

저자: IT Sectr 게시일: 2026-02-26 읽는 시간: 8 분

Globalization(글로벌화, 국제화, i18n) — 소스 코드를 변경하지 않고 모바일 애플리케이션이 여러 언어와 지역 형식으로 작동하도록 준비하는 프로세스입니다. 코드에서 문자열 리소스 추출, 다양한 날짜/숫자/통화 형식 지원, 텍스트 방향(LTR/RTL) 고려, 여러 언어에 대한 레이아웃 적응이 포함됩니다. iOS에서는 NSLocalizedString과 Localizable.strings가 사용되고, Android에서는 values-{lang} 디렉토리의 strings.xml이 사용됩니다. 자세한 내용은 Apple 국제화 문서를 참조하세요.

주요 내용

  • Globalization (i18n) — 여러 언어와 지역에 대한 애플리케이션 코드 준비
  • NSLocalizedString — Localizable.strings에서 번역된 문자열을 가져오는 Swift 매크로
  • strings.xml — 각 언어의 리소스 문자열을 저장하는 Android XML 파일
  • RTL — 오른쪽에서 왼쪽으로 쓰는 언어(아랍어, 히브리어, 우르두어) 지원
  • 형식 — 날짜, 숫자, 통화는 Locale 종속 API를 통해 형식화되어야 함

Globalization (i18n)이란 무엇이며 왜 필요한가?

Globalization(약어 i18n — "i"와 "n" 사이 18글자) — 모든 언어와 지역에서 작동하도록 애플리케이션을 아키텍처 수준에서 준비하는 것입니다. i18n의 핵심 규칙: 소스 코드에 하드코딩된 텍스트 문자열이 없어야 합니다. 대신 문자열을 리소스 파일로 추출하고 코드는 키를 통해 접근합니다. 새 언어를 추가할 때는 번역 파일만 추가하면 됩니다 — 코드는 변경되지 않습니다. 이것이 문자열 자체를 번역하는 지역화(l10n)와의 차이점입니다.

비즈니스 근거 — 글로벌화는 시장을 확장합니다. Common Sense Advisory(2023)에 따르면, 70% 이상의 사용자가 모국어 앱에서 구매를 선호합니다. 10개 언어로의 지역화는 잠재 고객을 80% 증가시킵니다. i18n이 없으면 새로운 언어로 확장할 때마다 코드 변경이 필요해 시장 진입이 지연되고 비용이 5~10배 증가합니다. 올바른 i18n 아키텍처는 최소 비용으로 40개 이상의 언어를 지원할 수 있게 합니다.

i18n 구성 요소에는 다음이 포함됩니다: 문자열 외부화, 복수형 처리(1/2/5+), 날짜 및 숫자 형식화(DateFormatter/SimpleDateFormat), RTL 언어 지원(Right-to-Left), 로케일별 정렬(Collator), 지역 기호(천 단위 구분 기호, 소수점). IT Sectr에서는 i18n을 아키텍처 단계에서 구현하며 사후에 추가하지 않습니다 — 이후 지역화에서 최대 60%의 시간을 절약할 수 있습니다.

iOS 국제화: NSLocalizedString과 XLIFF

NSLocalizedString — 번역 작업을 위한 주요 Swift 매크로입니다. 형식: NSLocalizedString("key", comment: "번역자 설명"). 이 매크로는 현재 기기 로케일(NSLocale.preferredLanguages)에 따라 Localizable.strings에서 자동으로 문자열을 대체합니다. 키에 대한 번역이 없으면 키 자체 또는 개발 언어(보통 en) 값이 반환됩니다. Apple은 영어 문자열을 키로 사용하는 대신 의미 있는 키를 사용할 것을 권장합니다.

swift
// Localizable.strings (en)
// "welcome_title" = "Welcome!";
// Localizable.strings (ru)
// "welcome_title" = "환영합니다!";

// Swift 코드 — 모든 언어에 통일
titleLabel.text = NSLocalizedString(
    "welcome_title",
    comment: "환영 화면 제목"
)

// Localizable.stringsdict를 통한 복수형
// 
// <dict>
//     <key>items_count</key>
//     <dict>
//         <key>NSStringLocalizedFormatKey</key>
//         <string>%#@items@</string>
//         <key>items</key>
//         <dict>
//             <key>one</key>
//             <string>%d개 상품</string>
//             <key>few</key>
//             <string>%d개 상품</string>
//             <key>many</key>
//             <string>%d개 상품</string>
//         </dict>
//     </dict>
// </dict>

// 복수형 사용
let items = 5
let label = String.localizedStringWithFormat(
    NSLocalizedString("items_count", comment: ""), items
)

XLIFF — 개발자와 번역가 간의 번역 교환 형식입니다. Xcode는 번역할 모든 문자열이 포함된 XLIFF 파일을 내보냅니다(Editor → Export for Localization). 번역가는 CAT 도구(Trados, memoQ, Smartcat)에서 XLIFF로 작업합니다. 번역 후 XLIFF는 Xcode로 다시 가져옵니다(Editor → Import Localizations). XLIFF는 자동으로 모든 .lproj 디렉토리를 업데이트합니다. 이것이 프로덕션 iOS 앱 지역화의 표준 워크플로입니다.

SwiftUI와 i18n

SwiftUI는 Text 초기화자를 통해 NSLocalizedString과 함께 작동합니다. SwiftUI의 텍스트는 자동으로 국제화됩니다: Text("welcome_title")은 NSLocalizedString과 동일하게 Localizable.strings에서 번역을 찾습니다. 복수형의 경우 Text("%d items", count: items)를 사용합니다. SwiftUI는 Text(date, style: .date)를 통해 날짜 형식을 지원하며 자동으로 Locale.current를 사용합니다. Apple은 국제화가 더 투명하므로 새 프로젝트에 SwiftUI를 권장합니다.

Android 국제화: strings.xml과 RTL

Android i18n은 리소스 시스템을 기반으로 합니다. 기본 언어(보통 영어)의 문자열은 res/values/strings.xml에 배치됩니다. 각 언어에 대해 별도의 디렉토리가 생성됩니다: res/values-ru/strings.xml(러시아어), res/values-de/strings.xml(독일어), res/values-fr/strings.xml(프랑스어). Android는 기기 시스템 언어(Locale.getDefault())에 따라 자동으로 문자열을 선택합니다. 정확한 로케일이 없으면 기본값(values/strings.xml)이 사용됩니다.

kotlin
// res/values/strings.xml (영어, 기본)
<resources>
    <string name="welcome_title">Welcome!</string>
    <string name="items_count">%d item(s)</string>
</resources>

// res/values-ru/strings.xml (러시아어)
<resources>
    <string name="welcome_title">환영합니다!</string>
    <plurals name="items_count">
        <item quantity="one">%d개 항목</item>
        <item quantity="few">%d %d개 항목</item>
        <item quantity="many">%d %d개 항목</item>
    </plurals>
</resources>

// Kotlin 코드
textView.text = getString(R.string.welcome_title)

// 복수형
val items = 5
textView.text = resources.getQuantityString(
    R.plurals.items_count, items, items
)

// 코드 내 RTL 지원
textView.textDirection = View.TEXT_DIRECTION_LOCALE
// Manifest: supportsRtl="true"

RTL(Right-to-Left) — 텍스트를 오른쪽에서 왼쪽으로 읽는 언어(아랍어, 히브리어, 우르두어, 페르시아어) 지원입니다. Android는 android:layoutDirection 및 android:textDirection 속성을 통해 RTL을 지원합니다. 매니페스트에서 android:supportsRtl="true"를 지정하면 Android가 자동으로 레이아웃을 미러링합니다. NavDrawer, 뒤로/앞으로 아이콘, 텍스트 정렬은 양방향으로 작동해야 합니다. 코드에서는 LEFT/RIGHT 대신 View.LAYOUT_DIRECTION_LOCALE과 Gravity.START/END를 사용합니다.

지역화된 리소스

Android Resource Qualifiers를 사용하면 문자열뿐만 아니라 이미지(res/drawable-ru/), 레이아웃(res/layout-ru/), 애니메이션, 색상도 지역화할 수 있습니다. 아랍어와 히브리어의 경우 요소가 미러링된 별도의 레이아웃이 필요합니다 — res/layout-ar/(아랍어)를 사용합니다. Android는 지역 변형도 지원합니다: values-rUS, values-rGB, values-de-DE. 한정자를 결합할 수 있습니다: values-ldrtl-ru — RTL 디스플레이용 러시아어.

지역 형식: iOS 및 Android의 날짜, 숫자, 통화

날짜와 시간 — i18n의 핵심 측면 중 하나입니다. 지역마다 다른 형식을 사용합니다: 러시아 — DD.MM.YYYY, 미국 — MM/DD/YYYY, 일본 — YYYY.MM.DD. 사용자에게 표시하기 위해 고정 형식(yyyy-MM-dd)을 사용하는 것은 오류입니다. iOS에서는 Locale(identifier: locale)과 함께 DateFormatter를 사용하고, Android에서는 DateFormat.getDateInstance(DateFormat.SHORT, locale)를 사용합니다. 음성 어시스턴트 및 AI 검색의 경우 날짜는 내부적으로 ISO 8601 형식이어야 합니다.

숫자와 통화 — 지역마다 다른 구분 기호가 있습니다: 1,234.56(미국) vs 1.234,56(러시아), 1 234,56(프랑스). iOS: .locale = locale인 NumberFormatter. Android: DecimalFormatSymbols(locale)이 있는 DecimalFormat. 통화의 경우: ¥1,234(일본) vs $1,234.56(미국) vs 1 234,56 ₽(러시아) 형식. 통화와 숫자를 수동으로 연결하지 마세요 — NumberFormatter.currencyCode와 .currencySymbol을 사용하세요.

지역날짜숫자통화
러시아31.12.20241 234,561 234,56 ₽
미국12/31/20241,234.56$1,234.56
독일31.12.20241.234,561.234,56 €
일본2024/12/311,234¥1,234
사우디아라비아31/12/20241,234.561,234.56 SAR

정렬(Collation) — 알파벳순 정렬은 언어마다 다릅니다. 스페인어에서 "ch"는 "c" 뒤에 옵니다. 스웨덴어에서 "ä"는 알파벳 끝에 있습니다. 독일어에서 "ß"는 "ss"로 정렬됩니다. iOS: LocalizedComparison(String.localizedCompare). Android: Collator.getInstance(locale). 사용자에게 표시되는 문자열에 compareTo()를 사용하지 마세요 — 지역 규칙을 고려하지 않는 Unicode Code Point 순서를 사용합니다.

모바일 앱 국제화 모범 사례

아키텍처 원칙 — 첫 번째 커밋부터 i18n을 시작하세요. 코드의 모든 문자열은 i18n이 설정될 때까지 존재하지 않는 래퍼 함수(tr("key"))를 통과해야 합니다 — 이렇게 하면 개발자가 즉시 문자열을 외부화하게 됩니다. 영어 문자열을 키로 사용하지 마세요 — 영어 표현이 변경되면 모든 번역을 업데이트해야 합니다. 의미 있는 키를 사용하세요: "profile.title", "settings.language.label".

의사 지역화(Pseudolocalization) — 실제 번역 전 i18n 테스트 기법입니다. 인코딩 확인을 위해 각 라틴 문자를 분음 부호가 있는 문자(á, é, ñ, ü)로 바꾸고, 문자열 잘림 확인을 위해 [XXX] 접두사를 추가합니다. Xcode: 실행 스키마 — "Double-Length Pseudolanguage" 의사 언어. Android: 개발자 옵션 — RTL 레이아웃 방향 강제, 시스템 글꼴 배율 200%까지. 의사 지역화는 번역가 참여 없이 i18n 문제의 80%를 발견합니다.

IT Sectr i18n 체크리스트 — 릴리스 전에 확인합니다: (1) 코드에 하드코딩된 문자열 없음(예외: 로그), (2) 복수형이 모든 언어에서 올바르게 작동, (3) 날짜/숫자가 Locale API를 통해 형식화됨, (4) RTL 언어에서 레이아웃이 올바르게 표시됨, (5) 최대 배율에서 문자열이 잘리지 않음, (6) 의사 지역화에서 오류 없음, (7) 스토어에 선언된 모든 언어에 완전한 번역 세트가 있음.

자주 묻는 질문

i18n과 l10n의 차이점은 무엇인가요?

i18n(국제화) — 코드 준비: 문자열 외부화, RTL 지원, 형식화. 개발자가 한 번 수행합니다. l10n(지역화) — 특정 언어로 문자열 번역. 번역가가 각 로케일에 대해 여러 번 수행합니다. i18n은 아키텍처, l10n은 콘텐츠입니다. i18n 없이는 지역화가 근본적으로 불가능합니다.

Swift에서 NSLocalizedString은 어떻게 작동하나요?

NSLocalizedString — 현재 기기 로케일의 Localizable.strings에서 키로 값을 찾는 매크로입니다. 번역이 있으면 반환하고, 없으면 키를 반환합니다. 형식: NSLocalizedString("key", comment: "설명"). 매개변수 형식화에는 String.localizedStringWithFormat()을 사용합니다.

Android에서 strings.xml은 어떻게 구성되나요?

strings.xml — res/values/{lang}/ 디렉토리의 번역 파일입니다. 기본 버전은 values/strings.xml에, 번역은 values-ru/strings.xml에 있습니다. 코드는 getString(R.string.key)를 통해 접근합니다. Android는 시스템 언어에 따라 자동으로 적절한 파일을 선택합니다. 복수형의 경우 zero/one/few/many/other 한정자가 있는 <plurals> 리소스가 사용됩니다.

i18n 맥락에서 RTL이란 무엇인가요?

RTL(Right-to-Left) — 아랍어, 히브리어, 우르두어, 페르시아어의 쓰기 방향입니다. Android: 매니페스트에서 supportsRtl="true", android:layoutDirection, Gravity.START/END. iOS: 강제 RTL은 UISemanticContentAttribute.forceLeftToRight. 레이아웃이 미러링되어야 합니다: 메뉴가 오른쪽에, 텍스트는 오른쪽에서 왼쪽으로, 탐색 아이콘은 반전됩니다.

출시에 필수적인 언어는 무엇인가요?

글로벌 출시 최소 세트: 영어, 스페인어, 프랑스어, 독일어, 일본어, 중국어, 한국어, 포르투갈어, 러시아어, 이탈리아어. App Store는 최소한 영어 지역화를 요구합니다. 추가 로케일마다 잠재 고객이 확장됩니다. 지역 시장의 경우 1~2개 언어면 충분합니다.

요약

  • Globalization (i18n) — 여러 언어와 지역에 대한 애플리케이션의 아키텍처 수준 준비
  • NSLocalizedString — Localizable.strings + XLIFF 내보내기를 통한 문자열 번역 Swift 매크로
  • strings.xml — values-{lang} 디렉토리에 번역이 있는 Android 리소스
  • RTL — 아랍어, 히브리어, 우르두어, 페르시아어 필수 지원
  • 형식 — 날짜와 숫자는 Locale API를 통해 엄격하게 형식화되며 수동으로 하지 않음
  • 복수형 — iOS: stringsdict, Android: 6가지 수량 형태의 <plurals>
  • 의사 지역화 — 번역 전 i18n 테스트 기법(문제의 80% 발견)

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기