Xcode에서 사용하지 않는 로컬라이제이션 키를 제거할 때는 Stale 항목을 검토 대상으로 취급하세요. 삭제하기 전에 런타임 키 구성을 확인하고, 필요한 동적 메시지는 수동 관리 항목으로 보존한 다음, 정리 후 영향을 받는 Mac 앱 화면을 테스트하세요.

이 가이드는 String Catalog를 사용하는 SwiftUI Mac 앱을 관리하는 개발자를 위한 것입니다. 이 작업은 카탈로그를 정리하는 과정입니다. 제거할 수 있는 메시지를 찾는 동시에 앱에서 여전히 표시하는 레이블과 개수 메시지는 보존해야 합니다. 아래의 판단 자료는 추출 증거와 런타임 동작을 구분합니다.

오래된 로컬라이제이션 키는 실제로 무엇을 의미하나요?

Xcode는 빌드 중에 로컬라이즈 가능한 문자열을 검색합니다. Apple에 따르면 추출은 현재 스킴과 플랫폼을 대상으로 합니다. 이전에 추출한 문자열이 사라지면 Xcode는 번역되지 않은 항목을 자동으로 제거할 수 있지만, 번역이 있는 항목은 남겨 두고 Stale 상태를 표시합니다. 이 상태는 Xcode가 코드에서 해당 문자열을 더 이상 찾지 못한다는 뜻입니다. Apple은 문자열이 더 이상 필요하지 않음을 확인한 경우에만 삭제하라고 명시합니다. String Catalog 알아보기

실무적으로는 소스 참조가 없다는 사실을 확인하는 일부터 조사가 시작됩니다. panel.compact를 정확히 검색하면 리터럴 참조를 찾을 수 있지만, 코드가 panel.와 선택된 모드를 결합해 해당 키를 만드는지까지는 알 수 없습니다. 후보 키와 조회 키를 생성하는 코드를 모두 검토하세요.

각 후보에 대해 아래 검토 표를 사용하세요. 이는 문서화된 추출 범위를 바탕으로 만든 판단 자료이며, Xcode의 추가 기능은 아닙니다.

검토 중 발견한 증거 판단 다음 작업
제거된 화면만 사용했으며, 남아 있는 런타임 키 생성 코드가 없음 후보 삭제 항목을 제거한 뒤 다시 빌드하고 변경 사항을 확인합니다
런타임 코드가 이 키를 정확히 생성할 수 있음 유지 수동 관리로 보존하거나 조회를 명시적인 로컬라이즈 가능 참조로 바꿉니다
다른 타깃이나 빌드 조건에서 키를 계속 참조함 유지 해당 구성을 빌드하고 검사합니다
다른 테이블에 이름이 비슷한 키가 있음 별도로 조사 각 조회에 사용되는 테이블과 리소스 번들을 확인합니다
사용처는 찾지 못했지만 키 생성 코드가 불분명함 보류 삭제 여부를 결정하기 전에 생성 경로를 추적합니다

Xcode에서 유용한 기준 상태를 만들려면 어떻게 하나요?

먼저 복구할 수 있도록 카탈로그 사본을 저장하거나 현재 상태를 커밋하세요. 그런 다음 앱 프로젝트를 열고 검토하려는 Mac 스킴을 선택합니다. 영향을 받는 인터페이스에 메시지를 제공할 수 있는 타깃과 조건부 구성을 기록해 검토 범위를 명확히 하세요.

프로젝트 탐색기에서 카탈로그를 선택하고 Product > Build를 선택합니다. Apple 문서에 따르면 빌드는 로컬라이즈 가능한 소스 텍스트를 바탕으로 String Catalog를 채우고 업데이트합니다. 카탈로그를 선택한 상태에서 Editor > Assistant를 선택한 다음 키를 선택해 소스 위치를 확인합니다. 카탈로그에서 소스로 이동할 수도 있습니다. String Catalog를 사용해 텍스트 현지화 및 변형하기

예상한 Swift 문자열이 누락되었다면 타깃의 Use Compiler to Extract Swift Strings 빌드 설정이 활성화되어 있는지 확인하세요. Apple은 컴파일러 추출의 필수 조건으로 이를 문서화합니다. 추출이 불완전한 상태로 채워진 카탈로그는 제거할 항목을 결정하기에 적절한 기준이 아닙니다. SwiftUI 앱 현지화하기

각 후보에 대해 키, 카탈로그, 추정 사용처, 판단을 기록하세요. 먼저 정확한 키를 검색한 뒤 안정적인 접두사와 관련 로컬라이제이션 래퍼를 검색합니다. 해당 래퍼에 값을 전달하는 모델 값과 번들 조회 데이터를 살펴보세요. 다른 타깃이나 컴파일 조건에 따라 포함되는 소스가 달라지면 관련 빌드를 반복하세요.

두 항목이 같은 텍스트를 표시한다고 해서 판단을 합치지 마세요. Apple의 로컬라이제이션 API는 테이블 이름을 받으며, 기본 앱 이외의 리소스에는 다른 번들이 필요할 수 있습니다. 다른 항목을 대체 항목으로 취급하기 전에 조회에 사용되는 테이블과 번들을 추적하세요. 앱의 텍스트 번역 준비하기

동적으로 참조되는 메시지를 어떻게 보존하나요?

Apple은 키를 동적으로 구성하는 문자열에 대해 수동 관리를 문서화합니다. 필요한 항목을 선택하고 인스펙터에서 수동 관리 항목으로 설정하세요. 이러한 항목은 빌드 후 Xcode의 로컬라이제이션 동기화 과정에서 업데이트되거나 제거되지 않습니다. 동적 항목이 누락된 경우, Apple은 카탈로그의 더하기 버튼으로 수동 문자열을 추가하는 방법도 보여 줍니다. String Catalog 알아보기

수동 관리에는 명시적인 유지보수 규칙이 필요합니다. 유효한 키를 선택하는 코드나 데이터 옆에 기록하고, 카탈로그 주석에 사용 목적을 설명하세요. 나중에 지원 모드가 제거되면 해당 수동 항목도 검토하세요. 자동 추출은 대신 정리해 주지 않습니다.

SwiftUI가 실제로 조회를 수행하는지 확인하기

String 변수를 Text에 전달하면 로컬라이제이션 없이 표시됩니다. 변수를 조회 키로 사용하려면 Apple 문서에 따라 LocalizedStringKey를 만들어야 합니다. Text에 직접 전달한 리터럴은 자동으로 로컬라이즈 가능한 경로를 따릅니다. 이 오버로드는 소스 언어에서 같은 결과를 표시하더라도 동작은 다를 수 있습니다. LocalizedStringKey

다음 전체 예제 앱은 런타임에 선택되는 키를 보간된 개수와 분리합니다. Xcode 15 이상과 macOS 13 배포 대상을 사용하는 임시 SwiftUI Mac 앱 프로젝트에서 생성된 앱 선언을 이 코드로 바꾸세요. @main 선언은 하나만 남기세요. 문서화된 API를 기준으로 코드를 검토했지만, Swift 도구 모음을 사용할 수 없어 여기서 컴파일하지는 않았습니다.

import SwiftUI

@main
struct CatalogReviewDemoApp: App {
    var body: some Scene {
        WindowGroup {
            CatalogReviewView()
        }
    }
}

struct CatalogReviewView: View {
    @State private var compact = true
    @State private var itemCount = 2

    private var selectedKey: String {
        "panel." + (compact ? "compact" : "expanded")
    }

    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            Toggle("Compact layout", isOn: $compact)

            Text(LocalizedStringKey(selectedKey))

            Text("\(itemCount) items",
                 comment: "Number of items in the sample panel.")

            Button("Add item") {
                itemCount += 1
            }
        }
        .padding()
        .frame(minWidth: 320)
    }
}

앱 타깃에 Localizable.xcstrings를 추가하세요. panel.compact 및 panel.expanded에 대해 소스 값이 Compact panel 및 Expanded panel인 수동 관리 항목을 추가합니다. 리터럴 메시지를 추출하려면 프로젝트를 빌드하세요. 명시적인 LocalizedStringKey 변환은 런타임 조회를 요청하지만, 생성될 수 있는 모든 키를 리터럴로 선언해 추출기에 제공하지는 않습니다.

선택지가 적고 유한하다면 각 분기에서 로컬라이즈 가능한 리터럴을 명시적으로 사용하도록 키 구성을 바꾸는 방안을 고려하세요. 여러 컴포넌트 사이에 메시지를 전달하는 사용자 지정 인터페이스에는 테이블, 주석, 기본값 같은 로컬라이제이션 정보를 담는 LocalizedStringResource를 Apple이 권장합니다. 지원하는 전체 메시지 집합을 가장 쉽게 살펴볼 수 있는 표현을 선택하세요. 앱의 텍스트 번역 준비하기

변하는 개수는 왜 변하는 키와 다른가요?

예제에서 레이아웃을 선택하면 앱이 조회하는 메시지 키가 바뀝니다. itemCount을 변경하면 하나의 로컬라이즈 가능한 메시지에 전달되는 인수가 달라집니다. SwiftUI의 보간은 포함된 값을 로컬라이제이션용 서식 자리표시자로 변환하고, 런타임 렌더링은 그 자리에 값을 넣습니다. SwiftUI 앱 현지화하기

따라서 렌더링된 레이블 2 items, 3 items, 4 items마다 별도의 키가 필요하지 않습니다. 예제를 빌드하고 추출된 개수 메시지를 찾아 키를 Control-클릭한 다음 Vary by Plural을 선택하세요. 소스 로컬라이제이션이 영어라면 Xcode가 표시하는 정수 자리표시자를 사용해 One에는 %lld item, Other에는 %lld items를 입력합니다. Apple은 이 개수 메시지 작업 방식과 지원되는 다른 로컬라이제이션에 적절한 복수형 변형을 추가하는 방법을 문서화합니다. String Catalog를 사용해 텍스트 현지화 및 변형하기

정리하는 동안 개수 메시지를 변형을 포함한 완전한 리소스로 검사하세요. 소스 코드에 4 items 같은 렌더링 문구가 없다고 해서 기반 보간 메시지가 사용되지 않는 것은 아닙니다. 마찬가지로, 개수 템플릿을 유지한다고 해서 같은 패널에 있다는 이유만으로 관련 없는 동적 키까지 보존되는 것은 아닙니다.

정리 과정에서 실제로 어떤 항목을 제거해야 하나요?

후보 24개를 검토하는 예를 살펴보세요. 이 수치는 가상의 예시이며 실제 프로젝트를 측정한 결과가 아닙니다.

검토 결과 항목 수 조치
제거된 패널에만 사용처가 있었음 9 패널과 조회 데이터가 사라졌는지 확인한 뒤 삭제
키가 런타임 선택을 통해 계속 사용될 수 있음 8 유지하고 수동 관리 여부를 문서화
다른 타깃이나 조건부 빌드에 참조가 있음 5 유지하고 해당 빌드 범위를 확인
키의 출처가 아직 확인되지 않음 2 조사할 때까지 보존
검토한 총 항목 24 삭제 후보 9개

이 계산을 통해 정리 판단을 추적할 수 있습니다. 24개 항목을 검토했다고 해서 24개를 삭제하는 것은 아닙니다. 삭제 후보 9개 각각에 대해 제거된 사용처와 확인한 런타임 조회 경로를 설명하는 간단한 근거를 남기세요. 동적 항목 8개에는 허용된 키 집합을 기록해 다음 검토에서도 같은 판단을 반복할 수 있게 하세요.

확인된 후보만 제거한 다음 카탈로그 diff를 살펴보세요. 관련 없는 복수형이나 기기별 변형이 사라지지 않고 의도한 키와 관련 번역만 변경되었는지 확인합니다. 관련 구성을 다시 빌드하세요. 삭제한 키가 추출 과정에서 다시 나타나면 다시 삭제하기 전에 사용처를 재검토하세요.

Mac에서 보존된 메시지를 어떻게 확인하나요?

Product > Scheme > Edit Scheme을 사용하고 Run을 선택한 뒤 Options를 엽니다. App Language에서 지원되는 기존 로컬라이제이션을 선택하고 편집기를 닫은 다음 Mac 대상을 실행합니다. Apple은 로컬라이즈된 빌드를 테스트하기 위한 스킴 제어 기능을 문서화합니다. 앱에서 지원하는 로컬라이제이션마다 반복하세요. 앱 실행 중 로컬라이제이션 테스트하기

예제의 두 레이아웃을 모두 포함해 허용된 동적 선택을 전부 실행합니다. 앱이 식별자가 아니라 예상한 카탈로그 값을 표시하는지 확인하세요. 개수 메시지에는 0, 1, 2, 12 같은 값을 넣고, 지원되는 로컬라이제이션에 추가 복수 범주가 필요한 경우 그것도 확인합니다. 샘플의 초기 개수를 바꾸면 해당 테스트 값을 사용할 수 있습니다.

보존한 메시지가 잘못 표시되면 카탈로그를 변경하기 전에 정확한 키, 테이블, 번들, Text 초기화 코드를 확인하세요. Apple의 새로운 생성 심볼 워크플로를 사용하면 수동 리소스를 더 쉽게 참조할 수도 있습니다. Xcode 26에는 String Catalog 심볼 생성 기능이 도입되었으며, 기존 프로젝트에서는 Generate String Catalog Symbols를 통해 활성화할 수 있습니다. 이는 선택 가능한 리팩터링 경로이며, 참조되지 않는 수동 리소스가 사용되지 않는다는 증거는 아닙니다. 코드 따라 하기: Xcode로 로컬라이제이션 살펴보기

삭제 항목을 소수로 유지하고, 보존한 동적 메시지 목록을 문서화한 상태로 마무리하세요. 남은 각 항목에 식별 가능한 사용처가 있고, 런타임에 선택되는 키와 형식이 지정된 개수 메시지가 Mac 인터페이스에서 계속 작동하는 카탈로그가 정리의 유용한 결과입니다.

출처