Xcode 26 이상에서는 문자열 카탈로그가 직접 입력한 지역화 키를 대체하는 Swift 접근자를 생성할 수 있습니다. 이 가이드에서는 소규모 Mac 앱의 선택 요약을 타입이 지정된 속성과 함수로 마이그레이션한 다음, 컴파일러가 실제로 무엇을 보호하는지 확인합니다.

작업 범위는 의도적으로 좁게 설정했습니다. 창 제목과 정수 개수 두 개를 포함한 요약을 표시합니다. 모든 레이블과 값은 예시용입니다. 카탈로그 계약을 만들고, 이를 SwiftUI에 연결하고, 컴파일러 진단과 화면 출력이 모두 올바른지 확인합니다.

지역화 접근자가 컴파일 시점에 검사되는 이유

Apple은 Xcode 26에서 네이티브 문자열 카탈로그 심볼 생성을 도입했습니다. 자리표시자가 없는 항목은 정적 속성을 생성하고, 자리표시자가 있는 항목은 타입이 지정된 매개변수를 받는 함수를 생성합니다. 둘 다 LocalizedStringResource를 반환합니다. 새 Xcode 26 프로젝트에서는 기본적으로 생성이 활성화되지만, 기존 프로젝트에서는 빌드 설정을 활성화해야 할 수 있습니다. 코드 따라 하기: Xcode에서 지역화 살펴보기

유용한 변화는 호출 지점에 있습니다. 문자열 리터럴은 Swift 선언을 참조하지 않고 조회 키를 표기할 수 있습니다. 생성된 접근자는 실제로 존재해야 하는 멤버를 참조하고, 생성된 함수는 시그니처에 맞는 인수를 요구합니다. 문서에 설명된 이러한 동작에서 실제로 얻을 수 있는 효과는 오타가 있는 멤버나 호환되지 않는 인수가 컴파일러 오류가 된다는 점입니다.

이 보호에는 명확한 범위가 있습니다. Swift는 접근자가 존재하는지, 인수가 타입에 맞는지 확인할 수 있습니다. 하지만 문구가 의도한 인터페이스를 설명하는지, 유효한 두 정수 인수가 올바른 개수를 나타내는지는 판단할 수 없습니다. 접근자를 메시지에 대한 검사 가능한 프로그래밍 인터페이스로 취급하세요.

소규모 Mac 앱과 메시지 계약 설정하기

Xcode 26 이상과 macOS SwiftUI 앱 타깃을 사용합니다. 이 예시에서는 배포 대상 버전을 macOS 15 이상으로 설정합니다. 기반이 되는 LocalizedStringResource 타입은 macOS 13부터 사용할 수 있습니다. 예시의 더 높은 배포 대상 버전은 선택한 전제 조건이지, 해당 타입의 최소 버전은 아닙니다. 리소스는 필요할 때까지 조회를 미룰 수 있는 지역화 가능 텍스트를 나타냅니다. LocalizedStringResource

File > New > File from Template에서 카탈로그를 추가합니다. Resource 아래에서 String Catalog를 선택하고 이름을 Workbench로 지정한 다음 앱 타깃에 포함합니다. Apple 문서에 따르면 각 카탈로그는 하나의 테이블을 나타냅니다. 여기서는 별도의 테이블을 사용해 예시의 두 메시지를 한곳에 모읍니다. 문자열 카탈로그로 텍스트 지역화 및 변형하기

프로젝트 편집기에서 Build Settings를 열고 Generate String을 필터링한 다음, 타깃의 유효한 구성에서 Generate String Catalog Symbols를 Yes로 설정합니다. 이는 이전 프로젝트에서 설정해야 하는 스위치로 문서화되어 있습니다. 코드에서 생성된 지역화 가능 심볼 사용하기

Workbench.xcstrings에서 영어 원본 지역화를 선택합니다. 카탈로그 편집기의 도구 모음에서 + 버튼을 사용해 다음 항목 두 개를 추가합니다. 주석은 인수의 역할을 포함해 메시지가 무엇을 뜻하는지 정의합니다.

키 영어 원본 값 주석
TITLE Selection overview 선택 요약 위에 표시되는 제목.
SUBTITLE %1$(selectedCount)lld selected; %2$(availableCount)lld available 선택 요약. selectedCount는 선택된 항목 수이고, availableCount는 선택된 항목을 포함한 전체 항목 수입니다.

SUBTITLE의 경우 Xcode의 자동 완성 메뉴에서 각 자리표시자를 입력할 수 있습니다. %을 입력하고 정수 자리표시자를 선택한 다음 이름을 selectedCount 또는 availableCount로 지정합니다. Apple은 이러한 형식 지정자에 이름이 지정된 변수와 생성된 매개변수를 사용한다고 설명합니다. 각 항목을 선택하고 Attributes 인스펙터에서 Generate Swift Symbol과 Example Usages를 확인합니다. 코드에서 생성된 지역화 가능 심볼 사용하기

의도한 계약은 제목 속성과 Int 값 두 개를 받는 부제목 함수입니다. 계속하기 전에 인스펙터에 표시된 실제 생성 이름을 확인하세요. Apple에 따르면 심볼 이름은 키와 그 값 모두를 사용합니다. 아래 예시에서는 Apple이 문서화한 대문자 키 패턴에 따라 .Workbench.title과 .Workbench.subtitle(selectedCount:availableCount:)을 사용합니다. 코드 따라 하기: Xcode에서 지역화 살펴보기

이 계약은 중요한 구분을 명확히 합니다. availableCount에는 선택된 항목이 포함됩니다. 이 주석이 없다면 호출자는 이를 남은 항목 수로 해석할 수도 있습니다. 두 해석 모두 타입 검사를 통과하므로 의미를 문서화해야 접근자를 유용하게 쓸 수 있습니다.

완전한 창에서 생성된 접근자 사용하기

카탈로그를 만든 다음 Product > Build를 선택합니다. 템플릿 앱 선언과 콘텐츠 뷰를 다음 프로그램으로 교체하고, 타깃에 @main 선언이 정확히 하나만 있도록 합니다. 이 프로그램에는 카탈로그가 필수 리소스입니다. Swift 코드를 독립 파일에 붙여 넣는 것만으로는 접근자가 생성되지 않습니다.

import Foundation
import SwiftUI

@main
struct SelectionOverviewApp: App {
    var body: some Scene {
        WindowGroup {
            SelectionOverviewView(
                selectedCount: 3,
                availableCount: 12
            )
        }
    }
}

struct SelectionOverviewView: View {
    let selectedCount: Int
    let availableCount: Int

    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            Text(.Workbench.title)
                .font(.title2)

            Text(
                .Workbench.subtitle(
                    selectedCount: selectedCount,
                    availableCount: availableCount
                )
            )
        }
        .padding(24)
        .frame(minWidth: 360, minHeight: 140)
    }
}

영어 원본 지역화가 활성화된 상태에서 예시 입력은 Selection overview와 3 selected; 12 available을 표시해야 합니다. 선택 관리 코드를 추가하지 않고 인수 위치를 확인할 수 있도록 개수는 고정했습니다.

Apple은 생성된 리소스를 SwiftUI에서 Text 등으로 사용할 수 있고 Foundation의 String(localized:) 초기화자를 통해서도 사용할 수 있다고 설명합니다. 기존 Mac 인터페이스에서 변환된 String이 필요한 경우 해당 경계에서 생성된 리소스를 변환하세요. 코드 따라 하기: Xcode에서 지역화 살펴보기

예를 들어 카탈로그가 만들어진 뒤 같은 앱 타깃에 추가할 수 있는 완전한 헬퍼 함수는 다음과 같습니다.

import Foundation

func selectionSummary(
    selectedCount: Int,
    availableCount: Int
) -> String {
    String(
        localized: .Workbench.subtitle(
            selectedCount: selectedCount,
            availableCount: availableCount
        )
    )
}

직접 만든 인터페이스에서 LocalizedStringResource를 반환하면 나중에 조회할 리소스가 유지되고, String을 반환하면 초기화자가 실행될 때 조회가 이루어집니다. 수신 인터페이스에 필요한 값에 따라 선택하세요. Apple은 Foundation 문서에서 조회를 미루는 방식과 즉시 수행하는 방식의 차이를 설명합니다. LocalizedStringResource

예시는 가져온 문서를 기준으로 검토했습니다. 사용 가능한 환경에 Swift 실행 파일이나 Xcode가 없어 여기서 컴파일하지는 않았습니다.

선행 점과 인수 레이블이 중요한 이유

선행 점은 Swift의 암시적 멤버 구문입니다. 주변 문맥에서 타입을 추론할 수 있으면 타입 멤버 접근을 줄여 쓸 수 있습니다. 이는 특수한 문자열 키 연산자가 아니라 일반적인 Swift 구문입니다. 표현식 — 암시적 멤버 표현식

생성된 지역화 심볼에서 기본 Localizable 테이블은 멤버를 직접 노출하고, 이름이 지정된 테이블은 테이블 네임스페이스를 추가합니다. 그래서 이 예시에서는 멤버 이름 앞에 .Workbench를 포함합니다. Apple은 두 형식 모두 문서화하고 있습니다. 코드에서 생성된 지역화 가능 심볼 사용하기

selectedCount:와 availableCount: 레이블은 함수 호출에 속합니다. Swift는 호출 지점에 표시되는 인수 레이블과 함수 내부에서 사용하는 매개변수 이름을 구분합니다. 매개변수에 레이블이 필요하면 호출자가 이를 제공해야 합니다. 함수 — 함수 인수 레이블과 매개변수 이름

읽기 쉬운 레이블은 실수를 줄이는 데 도움이 되지만, 여기서 두 인수는 타입이 같습니다. 정수 값 두 개를 서로 바꾸어도 유효한 Swift 코드입니다. 따라서 메시지 계약과 화면 출력 확인은 컴파일러를 보완합니다.

기존 키의 의미를 유지하며 마이그레이션하기

기존 지역화 문자열을 위해 Apple은 리팩터링 절차를 제공합니다. 문자열 카탈로그에서 항목을 선택하고 Control-클릭한 다음 Refactor > Convert Strings to Symbols를 선택합니다. 미리 보기를 살펴보고 필요하면 제안된 심볼이나 매개변수 이름을 조정한 뒤 Convert를 선택합니다. 코드에서 생성된 지역화 가능 심볼 사용하기

먼저 이 창의 제목과 요약처럼 서로 연관된 항목 하나를 마이그레이션합니다. 미리 보기를 승인하기 전에 기존 메시지와 새 계약을 비교합니다. 같은 테이블을 사용하고, 같은 인터페이스 요소를 설명하며, 모든 자리표시자에 같은 의미를 부여하나요? 키 변경의 영향을 받는 기존 지역화 값도 검토하세요. 리팩터링이 해당 값의 정확성을 보증한다고 가정하지 마세요.

리팩터링에서 업데이트되지 않은 호출 지점은 카탈로그 인스펙터의 생성된 사용 예시를 참고해 해당 참조를 직접 교체합니다. 그런 다음 빌드하고 결과 텍스트를 확인합니다. 해당 호출을 모두 확인하기 전에 기존 항목을 삭제하지 마세요.

설치된 Xcode에서 네이티브 생성 기능을 지원하지 않으면 이 절차를 사용하려면 더 최신 툴체인이 필요합니다. Apple은 지역화 가능한 API에서 문자열을 추출해 카탈로그에 넣는 기능도 지원하며, 추출을 시작 단계의 작업 흐름으로 권장합니다. 이는 계속 지원되는 지역화 관리 방법이지만, 여기서 설명하는 생성된 접근자 계약 자체를 제공하지는 않습니다. 코드 따라 하기: Xcode에서 지역화 살펴보기

간단한 진단 순서로 마이그레이션 확인하기

샘플 창에 다음 검사를 적용합니다. 이 검사를 통해 컴파일러가 보호하는 부분과 메시지의 정확성 및 리소스 통합을 구분할 수 있습니다.

  1. 변경하지 않은 예시를 빌드해 정상 작동 기준을 확인합니다.
  2. 제목 멤버 이름을 임시로 잘못 입력하고 빌드합니다. 존재하지 않는 멤버에 대해 컴파일러 진단이 표시되어야 합니다. 원래 이름으로 되돌립니다.
  3. 부제목에 Int가 필요한 자리에 String 값을 임시로 전달합니다. 타입 불일치를 확인하기 위해 빌드한 다음 정수로 되돌립니다.
  4. selectedCount를 3로, availableCount을 12로 설정해 실행합니다. 숫자가 의도한 위치에 표시되는지 확인합니다.
  5. 카탈로그 제목 값만 Current selection으로 변경하고 다시 빌드해 표시된 제목을 확인합니다. 생성된 시그니처가 코드에서 사용하는 시그니처와 일치하는지 확인합니다.

멤버가 예상치 않게 없으면 먼저 카탈로그 항목의 생성된 사용 예시를 확인합니다. 그런 다음 생성 설정, 카탈로그의 타깃 포함 여부, 테이블 이름을 확인합니다. 컴파일러 진단은 참조가 실패했음을 알려 줍니다. 이 점검을 통해 철자 오류인지 생성된 선언을 사용할 수 없는 상태인지 구분할 수 있습니다.

마지막으로 실제 인터페이스를 테스트합니다. Apple이 문서화한 방법은 Product > Scheme > Edit Scheme을 선택한 다음 Run > Options에서 실행 전에 App Language를 선택하는 것입니다. 프로젝트가 지원하는 지역화별로 반복합니다. 앱 실행 시 지역화 테스트하기

초기 레이아웃을 확인할 때 Xcode의 Double-Length Pseudolanguage를 사용하면 지역화 가능한 텍스트가 길어져 크기 문제를 확인할 수 있습니다. 좁은 창 너비에서 요약을 살펴보세요. 컴파일 성공만으로 텍스트가 화면에 맞는지는 알 수 없습니다. 지역화 테스트하기

마이그레이션이 완료되면 각 호출 지점은 실제 Swift 멤버를 사용하고, 각 변수에는 문서화된 역할이 있으며, 의도한 카탈로그 항목으로 이어지는 검사된 경로가 유지됩니다. 컴파일러 검사와 창 검사를 함께 수행하세요. 전자는 접근자 계약을 확인하고, 후자는 독자에게 의도한 메시지가 표시되는지 확인합니다.

출처