Bitcode는 iOS 애플리케이션의 컴파일 단계에서 프로그램의 중간 표현입니다. 기계어 코드와 달리 Bitcode는 특정 프로세서 아키텍처에 종속되지 않습니다. Apple Developer Documentation에 따르면 App Store는 대상 아키텍처에 맞게 Bitcode를 재컴파일하여 성능을 향상시키고 설치 파일 크기를 줄일 수 있습니다. 개발자는 Bitcode를 App Store에 제출하면 스토어 자체에서 각 기기 유형에 최적화된 바이너리 파일을 생성합니다.
핵심 포인트
Bitcode는 LLVM 컴파일러 인프라에서 생성되는 프로그램의 중간 표현(Intermediate Representation, IR)입니다. Apple은 Xcode 7 및 iOS 9부터 watchOS 애플리케이션에는 필수, iOS 및 tvOS에는 선택 사항으로 Bitcode 지원을 도입했습니다. Xcode 14부터 watchOS를 제외한 모든 플랫폼에서 이 요구 사항이 제거되었습니다.
중간 코드 표현의 개념은 2000년대부터 일리노이 대학에서 Chris Lattner가 창립한 LLVM 프로젝트의 일부로 존재해 왔습니다. Apple은 2011년에 LLVM을 Xcode에 적용했고, 2015년에 Bitcode를 App Store에 다시 제출하지 않고 애플리케이션을 업데이트하는 방법으로 발표했습니다. 이 기술은 WWDC 2015의 “What's New in Xcode” 세션에서 발표되었습니다.
기계어 코드는 특정 프로세서(arm64, armv7 또는 x86_64)를 위한 이진 명령어입니다. Bitcode는 하드웨어 독립적인 형식으로 저장되어 App Store가 단일 소스 표현에서 다양한 아키텍처에 최적화된 바이너리 파일을 생성할 수 있게 합니다. 이 핵심적인 차이가 기술의 모든 이점을 정의합니다.
| 특성 | Bitcode | 기계어 코드 |
|---|---|---|
| 아키텍처 의존성 | 독립적 | CPU에 종속 |
| 바이너리 파일 크기 | 컴팩트 | 더 큼 |
| 재컴파일 기능 | 있음 | 없음 |
| App Store 지원 | 재컴파일됨 | 그대로 사용 |
| 디버깅 | 제한적 | 완전 지원 |
Bitcode는 실행 파일이 아닙니다. 개발자가 프로젝트 메타데이터와 함께 App Store에 제출하는 바이너리 형식의 LLVM IR입니다. 앱 스토어는 재컴파일 프로세스를 실행하여 각 대상 플랫폼 및 운영 체제 버전에 맞게 코드를 조정합니다.
Bitcode 생성 프로세스는 Swift 또는 Objective-C 소스 코드를 LLVM IR로 변환하는 컴파일러 프론트엔드에서 시작됩니다. 링킹 단계에서 Xcode는 IR을 .bc(Bitcode) 형식 파일로 패키징한 후 .xcarchive와 함께 App Store로 전송합니다. App Store는 자체적으로 재컴파일 프로세스를 실행합니다.
LLVM 인프라는 세 부분으로 구성됩니다: 프론트엔드(C/ObjC용 Clang, Swift용 Swift Frontend), Middle-End 최적화기, 백엔드(기계어 코드 생성기). Bitcode는 어셈블리 명령어 생성으로 진행하지 않고 처음 두 단계의 결과입니다. Middle-End는 플랫폼 독립적 최적화(죽은 코드 제거, 인라인화, 상수 폴딩)를 수행합니다.
// Swift 소스 코드 예제
func calculateSum(a: Int, b: Int) -> Int {
return a + b
}
// 컴파일 후 LLVM IR (간략화)
; define i32 @calculateSum(i32 %a, i32 %b)
; %result = add i32 %a, %b
; ret i32 %result
IR 생성 후 컴파일러는 표현 수준에서 일련의 최적화(죽은 코드 제거, 함수 인라인화, 상수 폴딩)를 수행합니다. 이러한 최적화는 아키텍처에 독립적이며 Bitcode에 보존됩니다. App Store에서 재컴파일하는 동안 특정 프로세서에 대한 명령어 재정렬과 같은 아키텍처 종속 최적화가 추가됩니다.
App Store Connect는 Bitcode가 포함된 아카이브를 수신하고 자체 컴파일 인프라를 실행합니다. 시스템은 사용자 기기의 대상 아키텍처를 확인하고 기계어 코드를 생성하여 특정 프로세서 특성에 맞게 추가 최적화합니다. arm64e(A12+ 및 M 시리즈 프로세서)의 경우 추가 보안 최적화가 적용됩니다.
이 프로세스를 App Thinning이라고 합니다 — 기기 아키텍처에 필요한 리소스와 코드만 해당 기기에 전달하는 기술입니다. A17 Pro 프로세서를 탑재한 iPhone 사용자는 이전 아키텍처를 위한 불필요한 명령어 없이 arm64e에 최적화된 바이너리 파일을 받습니다. 이는 다운로드 시간을 단축하고 기기 공간을 절약합니다.
Bitcode는 iOS 애플리케이션 개발자에게 여러 주요 이점을 제공합니다. 주요 이점은 App Store에 업데이트를 다시 제출하지 않고도 새로운 Apple 프로세서에 자동으로 최적화된다는 점입니다. 이는 armv7에서 arm64로의 전환과 같은 새로운 아키텍처로의 전환 시 특히 중요합니다.
Apple이 새로운 아키텍처의 프로세서를 출시하면 Bitcode와 함께 제출된 애플리케이션이 자동으로 해당 아키텍처에 맞게 재컴파일됩니다. 개발자는 프로젝트를 다시 빌드하고 업데이트를 게시할 필요가 없습니다 — App Store가 사용자가 처음 다운로드할 때 자체적으로 처리합니다. 이는 수년간 유지 관리되는 장수명 애플리케이션에 특히 중요합니다.
App Thinning과 Bitcode를 결합하면 설치된 애플리케이션 크기를 15~40%까지 줄일 수 있습니다. App Store는 특정 기기에 필요한 기계 명령어만 생성하여 다른 아키텍처 및 다양한 iOS 버전에 대한 코드를 제거합니다. 실제로 새로운 iPhone 사용자는 컴팩트한 바이너리 파일을 받게 됩니다.
Apple WWDC 2015 Session 102에 따르면 Bitcode와 App Thinning을 사용하면 모든 아키텍처를 포함하는 유니버설 바이너리 파일과 비교하여 다운로드되는 애플리케이션 크기를 평균 25% 줄일 수 있습니다. 100MB 애플리케이션의 경우 사용자 기기에서 최대 40MB까지 절약할 수 있습니다.
Bitcode 구성은 Xcode의 빌드 설정에서 수행됩니다. Enable Bitcode 매개변수는 Build Settings에 있으며 새 프로젝트의 경우 기본적으로 활성화되어 있지만 개발자는 디버깅 시나 Bitcode를 지원하지 않는 타사 라이브러리 사용 시 비활성화할 수 있습니다.
// Build Settings -> Apple Clang - Code Generation
// Enable Bitcode = YES
// 또는 개별 타겟의 Info.plist를 통해
@property (nonatomic, assign) BOOL enableBitcode;
- (void)configureBuildSettings {
// 구성에서 Bitcode 상태 확인
if (self.enableBitcode) {
NSLog(@"Bitcode is enabled for this target");
} else {
NSLog(@"Bitcode is disabled");
}
}
아카이브에 Bitcode가 포함되어 있는지 확인하려면 Xcode Organizer를 통해 .xcarchive 파일을 열거나 터미널에서 otool -l 명령을 실행합니다. 바이너리 파일에 __LLVM 섹션이 있으면 Bitcode가 활성화되어 올바르게 패키징되었음을 확인합니다. 섹션이 없으면 빌드 중에 Bitcode가 생성되지 않은 것입니다.
# 아카이브에서 Bitcode 존재 확인
otool -l YourApp.app/YourApp | grep __LLVM
# 출력: __LLVM 섹션이 있는 경우 — Bitcode가 존재함
# 출력이 비어 있는 경우 — Bitcode가 활성화되지 않았거나 생성되지 않음
# size 명령을 사용하여 확인할 수도 있음
size -m -l YourApp.app/YourApp | grep __LLVM
CocoaPods 또는 SPM을 통해 타사 라이브러리를 사용하는 경우 모든 종속성이 Bitcode로 빌드되었는지 확인하십시오. 하나라도 Bitcode를 지원하지 않는 라이브러리가 있으면 Xcode가 아카이빙 중에 링킹 오류를 생성합니다. CocoaPods의 경우 서브스펙에서 bitcode_enabled 플래그를 확인하거나 enable_bitcode와 함께 use_frameworks!를 사용하십시오.
Bitcode는 모든 유형의 iOS 프로젝트에 대한 보편적인 해결책이 아닙니다. 이 기술에는 개발자가 빌드 구성에서 옵션을 활성화하기 전에 고려해야 할 제한 사항이 있습니다. 이러한 제한 사항을 이해하면 아카이빙 및 게시 시 문제를 방지하는 데 도움이 됩니다.
모든 타사 라이브러리가 Bitcode를 지원하는 것은 아닙니다. 라이브러리가 Bitcode 없이 컴파일된 바이너리 파일로만 배포되는 경우 옵션이 활성화된 프로젝트는 빌드되지 않습니다. 이 경우 개발자는 Bitcode를 비활성화하거나 공급업체에 Bitcode 지원 버전을 요청해야 합니다. 이는 더 이상 업데이트되지 않는 오래된 라이브러리의 경우 특히 중요합니다.
Bitcode로 빌드된 애플리케이션의 충돌 보고서는 추가 처리가 필요합니다. 재컴파일된 코드의 심볼(dSYM)은 App Store에서 생성되며 Xcode Organizer를 통해 다운로드할 수 있습니다. 해당 dSYM 파일을 로드하지 않으면 충돌 보고서의 호출 스택을 읽을 수 없어 문제 진단이 어려워집니다.
iOS 17 및 Xcode 15 기준으로 Apple은 App Store 게시를 위해 Bitcode를 필수로 요구하지 않습니다. 그러나 watchOS 애플리케이션의 경우 Bitcode는 App Store Connect 정책 수준에서 필수 요구 사항으로 남아 있습니다. 개발자는 모든 종속성이 지원하는 경우 새 프로젝트에 Bitcode를 활성화하는 것이 좋습니다.
자주 묻는 질문
iOS 및 tvOS 애플리케이션의 경우 Xcode 14부터 Bitcode는 필수가 아닙니다. watchOS의 경우 Bitcode 지원은 계속 필수입니다. Apple은 새 프로젝트에 Bitcode를 활성화할 것을 권장하지만 활성화하지 않아도 게시를 차단하지는 않습니다.
Bitcode를 통해 App Store는 App Thinning을 적용할 수 있습니다 — 사용자 기기 아키텍처에만 맞는 기계어 코드를 생성합니다. 이는 프로젝트에서 지원하는 아키텍처 수에 따라 다운로드되는 바이너리 파일 크기를 15~40% 줄입니다.
네, dSYM 파일은 재컴파일된 바이너리 파일의 충돌 보고서를 심볼화하는 데 필요합니다. App Store는 아카이브 처리 후 Xcode Organizer를 통해 dSYM을 다운로드할 수 있는 기능을 제공합니다. 이것이 없으면 Crashlytics 및 콘솔의 호출 스택에 메모리 주소만 포함됩니다.
SPM은 종속성이 바이너리 파일이 아닌 소스 코드로 배포되는 경우 Bitcode를 지원합니다. SPM을 통한 바이너리 종속성은 Bitcode가 포함된 버전을 제공해야 하며, 그렇지 않으면 옵션이 활성화된 프로젝트가 컴파일되지 않습니다.
Bitcode는 하드웨어 독립적인 중간 LLVM IR 표현으로 프로세서가 직접 실행할 수 없습니다. 기계어 코드는 특정 아키텍처(arm64, x86_64)에 대한 준비된 명령어를 포함하며 추가 컴파일 없이 실행됩니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.