Skip to main content

iOS 앱 현지화 완벽 가이드

Localizable.strings부터 App Store 메타데이터까지, Xcode, SwiftUI, Fastlane, AI 자동 번역으로 iOS 앱을 현지화하는 방법을 알아보세요.

1

Xcode에서 현지화 활성화

Xcode 프로젝트 설정을 열고 Info > Localizations로 이동한 다음 지원할 언어를 추가하세요. Xcode가 언어별 .lproj 디렉터리를 자동으로 생성해요.

Xcode Project Settings
// In Xcode:
// 1. Select your project in the navigator
// 2. Go to Info tab > Localizations
// 3. Click + to add languages (e.g., German, Japanese)
// 4. Select which files to localize
//
// Xcode creates .lproj directories automatically:
// en.lproj/Localizable.strings
// de.lproj/Localizable.strings
// ja.lproj/Localizable.strings
기본 현지화는 UI와 문자열을 분리해요. 언어를 추가하면 Xcode에서 스토리보드, XIB, 문자열 파일의 현지화 버전을 만들 수 있어요.
2

Localizable.strings 생성

표준 iOS 현지화 파일은 등호로 구분한 키-값 쌍을 사용하고 각 줄 끝에 세미콜론을 붙여요. 원문 언어 파일은 Base.lproj 폴더에 두세요.

Base.lproj/Localizable.strings
// Base.lproj/Localizable.strings

"welcome_title" = "Welcome to MyApp";
"login_button" = "Sign In";
"settings_label" = "Settings";
"greeting" = "Hello, %@!";    // %@ = string placeholder
"item_count" = "%d items";     // %d = integer placeholder
세미콜론이 없으면 눈에 띄는 오류 없이 번역이 실패해요. 파일은 로드되지만 번역 내용은 비어 있어요. 파일을 대상의 Copy Bundle Resources 빌드 단계에 추가했는지도 확인하세요. 추가하지 않으면 앱 번들에 포함되지 않아요.
Common .strings Mistakes
// ❌ Common mistakes in .strings files:

// Missing semicolon — file loads but translations are empty
"welcome_title" = "Welcome"

// Unescaped quotes — causes parse error
"message" = "Click "here" to continue";

// ✅ Correct versions:
"welcome_title" = "Welcome";
"message" = "Click \"here\" to continue";
3

String Catalog로 이전 (Xcode 15 이상)

String Catalog (.xcstrings)는 .strings 파일을 대체하는 Apple의 최신 방식이에요. Xcode의 시각적 편집기, SwiftUI 뷰의 자동 문자열 추출, 내장 복수형 지원을 제공해요.

Localizable.xcstrings
// Xcode 15+ String Catalog (Localizable.xcstrings)
// Xcode automatically extracts strings from your code
// and manages translations in a visual editor.

// In SwiftUI, strings are automatically localizable:
Text("Welcome to MyApp")
Text("Hello, \(userName)!")

// Mark strings explicitly:
let title = String(localized: "welcome_title")
String Catalog는 모든 언어를 하나의 .xcstrings JSON 파일에 저장해요. 팀에서 여러 사람이 문자열을 추가하면 Git 병합 충돌이 자주 발생해요. 대규모 프로젝트에서는 모듈마다 카탈로그를 하나씩 두는 방식을 고려하세요.
4

SwiftUI 및 UIKit에서 현지화 문자열 사용

SwiftUI의 Text 뷰는 문자열 리터럴을 자동으로 현지화해요. UIKit에서는 NSLocalizedString을 사용해요. iOS 16 이상에서는 컴파일러 지원이 내장된 최신 String(localized:comment:) API로 더 간결한 구문을 사용할 수 있어요.

ContentView.swift
import SwiftUI

struct ContentView: View {
    let userName: String

    var body: some View {
        VStack {
            // ✅ SwiftUI auto-localizes string literals
            Text("welcome_title")

            // ⚠️ This does NOT localize (String interpolation)
            // Text("Hello, \(userName)")

            // ✅ Use String(localized:) for dynamic strings
            Text(String(localized: "greeting \(userName)"))

            // ✅ UIKit style (works everywhere)
            let title = NSLocalizedString(
                "settings_label",
                comment: "Settings screen title"
            )

            // ✅ Modern API (iOS 16+)
            let modern = String(
                localized: "welcome_title",
                comment: "Main screen title"
            )
        }
    }
}
name이 일반 String 변수이면 Text("Hello \(name)")이 오류 없이 현지화에 실패해요. SwiftUI 문자열 보간은 LocalizedStringKey를 만들지만 특정 형식 (Int, Double 등)만 올바르게 보간해요. String 변수는 먼저 String(localized:)으로 현지화 문자열을 만드세요.
5

복수형 처리

iOS는 복수형 규칙에 .stringsdict 파일을 사용하며 zero, one, two, few, many, other를 포함한 모든 CLDR 복수형 범주를 지원해요. String Catalog에서는 Xcode의 시각적 편집기로 복수형을 처리할 수 있어 stringsdict XML을 직접 작성하는 것보다 훨씬 간단해요.

Localizable.stringsdict
<!-- Localizable.stringsdict -->
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
    <key>items_count</key>
    <dict>
        <key>NSStringLocalizedFormatKey</key>
        <string>%#@count@</string>
        <key>count</key>
        <dict>
            <key>NSStringFormatSpecTypeKey</key>
            <string>NSStringPluralRuleType</string>
            <key>NSStringFormatValueTypeKey</key>
            <string>d</string>
            <key>zero</key>
            <string>No items</string>
            <key>one</key>
            <string>%d item</string>
            <key>other</key>
            <string>%d items</string>
        </dict>
    </dict>
</dict>
</plist>

// Usage in Swift:
String(format: NSLocalizedString("items_count", comment: ""),
       itemCount)
아랍어에는 6가지, 러시아어에는 3가지, 일본어에는 1가지 복수형이 있어요. 대상 언어에 필요한 모든 CLDR 범주를 항상 정의하세요. String Catalog의 시각적 복수형 편집기를 사용하면 더 쉽게 처리할 수 있어요.
6

Fastlane으로 App Store 메타데이터 현지화

Fastlane의 deliver 도구를 사용하면 앱 이름, 부제, 설명, 키워드, 출시 노트 같은 App Store 메타데이터를 로케일별 일반 텍스트 파일로 저장소에서 버전 관리할 수 있어요.

Terminal
# Install Fastlane
$ gem install fastlane

# Initialize deliver for App Store metadata
$ fastlane deliver init

# Directory structure created:
# fastlane/metadata/
# ├── en-US/
# │   ├── name.txt            # App name (30 chars)
# │   ├── subtitle.txt        # Subtitle (30 chars)
# │   ├── description.txt     # Full description
# │   ├── keywords.txt        # Search keywords (100 chars)
# │   ├── release_notes.txt   # What's New
# │   └── promotional_text.txt
# ├── de-DE/
# │   └── ...
# └── ja/
#     └── ...

# Push metadata to App Store Connect:
$ fastlane deliver
교차 현지화: 미국 App Store는 영어와 스페인어 키워드를 모두 색인해요. 별도 시장을 대상으로 삼지 않아도 메타데이터를 스페인어로 현지화하면 미국 히스패닉 사용자의 검색 유입을 확보할 수 있어요.
7

현지화 테스트

기기 언어를 바꾸지 않고 현지화된 콘텐츠를 테스트하세요. Xcode 스킴 재정의로 원하는 언어로 앱을 실행하고, locale 환경을 적용한 SwiftUI 미리 보기와 실행 인수를 적용한 XCUITest로 자동 테스트하세요.

Testing Localization
// 1. Xcode Scheme Override:
// Edit Scheme > Run > Options > App Language > Choose language

// 2. SwiftUI Preview with locale:
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .environment(\.locale, Locale(identifier: "de"))

        ContentView()
            .environment(\.locale, Locale(identifier: "ja"))

        ContentView()
            .environment(\.locale, Locale(identifier: "ar"))
    }
}

// 3. XCUITest with language override:
let app = XCUIApplication()
app.launchArguments += ["-AppleLanguages", "(de)"]
app.launchArguments += ["-AppleLocale", "de_DE"]
app.launch()
독일어(영어보다 문자열이 약 30% 길어짐)와 일본어(문자열이 약 50% 짧아짐)로 테스트해 레이아웃 문제를 일찍 찾아내세요. 실제 번역 없이도 Xcode의 의사 현지화로 레이아웃을 집중 테스트할 수 있어요.

번역 품질 검사 자동화

i18n-validate를 사용해 누락된 키, 손상된 플레이스홀더, 복수형 문제를 배포 전에 찾아내세요. 실제 번역이 준비되기 전에 i18n-pseudo의 의사 번역으로 UI를 테스트하세요.
8

번역 자동화

AI로 .strings, .xcstrings, Fastlane 메타데이터 파일을 번역하세요. 앱 내 문자열과 App Store 메타데이터 번역을 모두 자동화해 완전히 현지화된 앱을 제공할 수 있어요.

Terminal
# Translate .strings files
> Translate Base.lproj/Localizable.strings
  to Japanese, German, and Spanish

# Translate App Store metadata too
> Translate fastlane/metadata/en-US/
  to de-DE, ja, es-MX

✓ 6 files translated in 3.2s
App Store 페이지를 현지화하면 비영어권 시장에서 다운로드가 30% 이상 증가해요. 앱 문자열과 함께 메타데이터도 번역하세요. 투자 대비 효과가 가장 큰 현지화예요.
+

추가 기능: LocaleChain을 활용한 스마트 로케일 폴백

기본적으로 iOS는 사용자의 로케일과 정확히 일치하는 번역이 없으면 개발 언어로 폴백해요. pt-PT 번역만 있는 경우 pt-BR 사용자에게 포르투갈어 대신 영어가 표시돼요. LocaleChain은 구성 가능한 폴백 체인으로 이 문제를 해결해요.

LocaleChain은 오픈 소스 Swift 패키지예요. GitHub에서 보기

Package Dependencies
// Swift Package Manager
// File > Add Package Dependencies >
// https://github.com/i18n-agent/ios-localechain.git
MyApp.swift
import LocaleChain

// In your App init or AppDelegate:
LocaleChain.configure()  // Activates all default chains

// pt-BR user with only pt-PT translations?
// → Shows Portuguese instead of falling back to English

// Custom overrides for your specific locales:
LocaleChain.configure(
    overrides: ["es-MX": ["es-419", "es"]]
)

흔한 실수

.strings 파일 구문 오류

세미콜론 누락, 이스케이프하지 않은 따옴표, 잘못된 인코딩 때문에 눈에 띄는 오류 없이 번역이 실패할 수 있어요. 파일은 로드되지만 번역이 비어 보여요. 커밋하기 전에 항상 .strings 파일을 검증하세요.

SwiftUI Text 보간 현지화 실패

Text("Hello \(stringVar)")은 예상대로 현지화되지 않아요. 계산된 문자열에는 String(localized:)을 사용하거나 보간 변수의 형식이 LocalizedStringKey.StringInterpolation에 맞는지 확인하세요.

위젯/확장 프로그램에 원시 키 표시

앱 확장 프로그램은 별도 번들을 사용해요. .strings 또는 .xcstrings 파일을 기본 앱 대상뿐 아니라 확장 프로그램 대상의 Copy Bundle Resources 단계에도 추가했는지 확인하세요.

실제 서비스에서 번역 대신 키 표시

사용자의 언어에 해당하는 번역이 없으면 iOS가 키 자체를 표시해요. 폴백 언어 전략을 사용하고 출시 전에 지원하는 모든 로케일을 테스트하세요.

권장 파일 구조

Project Structure
MyApp/
├── MyApp.xcodeproj
├── MyApp/
│   ├── Base.lproj/
│   │   ├── Localizable.strings       # Source strings
│   │   └── Localizable.stringsdict   # Plural rules
│   ├── en.lproj/
│   │   └── Localizable.strings
│   ├── de.lproj/
│   │   └── Localizable.strings
│   ├── ja.lproj/
│   │   └── Localizable.strings
│   ├── Localizable.xcstrings          # OR String Catalog
│   └── Info.plist
├── MyAppTests/
├── fastlane/
│   ├── Fastfile
│   └── metadata/
│       ├── en-US/
│       │   ├── name.txt
│       │   ├── description.txt
│       │   └── keywords.txt
│       ├── de-DE/
│       └── ja/
└── Package.swift

지금 i18n Agent 사용해 보기

번역 파일을 여기에 드롭

JSON, YAML, PO, XML, CSV, Markdown, Properties

또는 클릭하여 파일 선택

대상 언어

가입 불필요즉시 견적

ios-localechain을 활용한 로케일 폴백

de-AT 같은 지역 로케일에 번역 키가 없으면 iOS는 상위 로케일 de를 먼저 확인하지 않고 개발 언어로 바로 폴백해요.

Terminal
// Swift Package Manager
// https://github.com/i18n-agent/ios-localechain
Configuration
import LocaleChain

LocaleChain.configure(overrides: [
    "de": ["en-GB", "en"],
    "pt-BR": ["pt", "en"],
    "zh-Hant-HK": ["zh-Hant", "zh", "en"],
])

지원 프레임워크와 75개 내장 체인의 전체 목록은 로케일 폴백 가이드에서 확인하세요. Learn more →

iOS 현지화에 관해 자주 묻는 질문