IPA 파일이란?
iOS 앱이 배포되고 설치되는 IPA 파일의 정체와 앱 번들 구조. Info.plist, 두 겹의 코드 서명, 프로비저닝 프로파일, App Thinning을 그림과 함께 정리합니다.
iOS 앱은 IPA 파일로 배포되고 설치됩니다. IPA가 무엇이고 그 안에 무엇이 어떤 규칙으로 들어 있는지, 그리고 코드 서명이 무결성을 어떻게 지키는지 정리합니다.
IPA는 zip이다
IPA는 iOS 앱을 담은 zip 압축 파일입니다. 확장자만 .ipa일 뿐 실제로는 zip이라 unzip으로 그대로 풀 수 있습니다.
unzip -q MyApp.ipa -d MyApp
풀면 최상위에 Payload/ 디렉토리가 있고 그 안에 앱 번들(.app)이 들어 있습니다. 앱 스토어에 올리는 IPA에는 SwiftSupport/(스위프트 런타임)나 Symbols/(크래시 심볼화용) 같은 폴더가 더 붙기도 합니다.
앱 번들 구조
앱의 실체는 Payload/MyApp.app/ 디렉토리 하나입니다. iOS에서 앱은 파일 하나가 아니라 번들이라는 폴더입니다.
| 구성요소 | 하는 일 |
|---|---|
| 실행 바이너리 | 앱의 코드. 확장자 없는 Mach-O 파일이고 번들 이름과 같음 |
Info.plist | 번들 식별자, 실행 파일 이름, 버전, 최소 iOS 버전 등 |
_CodeSignature/CodeResources | 번들 안 모든 파일의 해시 목록. 리소스 변조까지 잡는다 |
embedded.mobileprovision | 어떤 기기와 인증서로 실행을 허용하는지 담은 프로파일 |
Frameworks/ | 앱이 쓰는 동적 라이브러리와 프레임워크(각각 내부에 dylib) |
Assets.car | 이미지와 에셋 카탈로그를 하나로 컴파일한 파일 |
PlugIns/ | 위젯, 공유 익스텐션 같은 앱 익스텐션(.appex) |
Info.plist에는 무엇이 있나?
Info.plist는 시스템이 앱을 다루는 데 필요한 정보를 담은 딕셔너리입니다. 사람이 읽을 수 있게 plutil로 볼 수 있습니다.
plutil -p Payload/MyApp.app/Info.plist
자주 보는 키는 이렇습니다.
| 키 | 의미 |
|---|---|
CFBundleIdentifier | 앱을 유일하게 식별하는 번들 ID(com.example.MyApp) |
CFBundleExecutable | 실행할 바이너리 파일 이름 |
CFBundleShortVersionString | 사용자에게 보이는 버전(1.2.0) |
CFBundleVersion | 빌드 번호 |
MinimumOSVersion | 설치 가능한 최소 iOS 버전 |
UIRequiredDeviceCapabilities | 필요한 하드웨어 기능(예: arm64) |
번들 ID와 버전이 여기 박혀 있어서, 시스템은 앱을 실행하기 전에 이 파일부터 읽습니다.
코드 서명: 두 겹의 봉인
IPA 구조에는 이 파일을 바꾸지 말라는 물리적 잠금이 없습니다. 무결성을 지키는 유일한 장치가 코드 서명이고, 서명은 두 겹으로 걸립니다.
한 겹은 실행 바이너리 자체입니다. Mach-O 안의 LC_CODE_SIGNATURE가 코드 페이지마다의 해시를 담아, 코드 한 바이트만 바뀌어도 검증이 실패합니다. 다른 한 겹은 번들 전체입니다. _CodeSignature/CodeResources에 Info.plist, Assets.car 같은 리소스 파일의 해시가 들어 있어, 코드가 아니라 리소스를 바꿔도 걸립니다. 여기에 embedded.mobileprovision이 더해져, 이 서명이 어떤 인증서로 어떤 기기에서 유효한지를 못박습니다.
고치고 다시 묶기
바이너리나 리소스를 수정했다면 서명이 깨지므로 다시 서명해야 합니다. 안쪽 파일부터 서명하고 번들을 마지막에 봉인합니다.
# 1) 안쪽(프레임워크/바이너리)부터 재서명
codesign -f -s "<identity>" Payload/MyApp.app/Frameworks/*.framework
# 2) 번들 전체 재서명
codesign -f -s "<identity>" Payload/MyApp.app
# 3) 서명 검증
codesign -v --verbose=4 Payload/MyApp.app
# 4) 다시 zip 으로 묶어 .ipa 로
zip -qr MyApp.resigned.ipa Payload
서명에 쓴 인증서와 프로비저닝이 허용하는 기기에서만 설치됩니다. 이 재서명 단계를 이용해 완성된 앱에 코드를 심는 방법은 배포된 iOS 앱에 프레임워크 주입하기에서 다룹니다.
앱 스토어의 App Thinning
개발 중 만드는 IPA와 앱 스토어가 사용자에게 내려주는 IPA는 다릅니다. 앱 스토어는 업로드된 앱을 받아 기기별로 필요한 것만 골라 다시 포장합니다. 사용자의 기기 아키텍처에 맞는 슬라이스, 그 화면 배율에 맞는 이미지만 담아 내려주므로, 사용자가 실제로 받는 IPA는 업로드본보다 작습니다. 이것을 App Thinning이라고 부릅니다.