iOS 디버그·실기기 테스트와 프로비저닝 프로파일 관계
작성일: 2026-07-15
목적: Xcode/Flutter 실기기 실행, Ad Hoc, TestFlight에서 어떤 인증서와 프로파일을 선택하는지 빠르게 판단하기 위한 기준
먼저 기억할 한 문장
빌드 모드(Debug/Release)와 배포 방식(Development/Ad Hoc/TestFlight)은 서로 다른 축입니다.
예를 들어 최적화된 Release 빌드를 Xcode에서 케이블로 연결한 iPhone에 직접 실행하더라도, 설치 방식이 개발 실행이면 Development 프로파일을 사용할 수 있습니다. 반대로 TestFlight는 앱 이름이나 서버 환경이 dev여도 App Store Connect 배포 프로파일을 사용합니다.
서명 구성요소의 역할
| 구성요소 | 의미 | 핵심 확인사항 |
|---|---|---|
| App ID | 어떤 앱인지 식별하고 Apple capability를 선언 | Bundle ID가 정확하고 Push Notifications 등이 활성화돼야 함 |
| Signing Certificate | 누가 앱에 서명하는지 증명 | Apple Development 또는 Apple Distribution 인증서와 개인 키 필요 |
| Device UDID | 어떤 실제 기기에 직접 설치할 수 있는지 지정 | Development/Ad Hoc 프로파일에서 사용 |
| Provisioning Profile | App ID, 인증서, 기기, entitlement를 묶은 서명 허가서 | 설치·배포 방식에 맞는 타입과 유효한 capability 필요 |
| Entitlements | 앱이 실제로 사용할 Apple 기능 | 최종 서명 앱의 값이 프로파일과 일치해야 함 |
프로파일은 단순한 설치 파일이 아닙니다. App ID + 인증서 + 허용 기기 + capability/entitlement를 하나로 묶습니다. 따라서 App ID에서 Push Notifications를 나중에 켜면 기존 프로파일은 Invalid가 될 수 있으며 재생성해야 합니다.
실행 방식별 선택표
| 실행·배포 방식 | 인증서 | 프로파일 타입 | 기기 등록 | APNs 환경 |
|---|---|---|---|---|
| Xcode/Flutter로 실제 iPhone 직접 실행 | Apple Development | iOS App Development | 필요 | development |
| Xcode에서 Release 최적화로 실제 기기 직접 실행 | 보통 Apple Development | iOS App Development | 필요 | development |
| IPA를 등록된 기기에 직접 배포 | Apple Distribution | Ad Hoc | 필요 | production |
| TestFlight 내부·외부 테스트 | Apple Distribution | App Store Connect | 불필요 | production |
| App Store 정식 배포 | Apple Distribution | App Store Connect | 불필요 | production |
| iOS Simulator | 일반적인 실기기 프로파일 불필요 | 해당 없음 | 불필요 | 실기기 검증을 대체하지 않음 |
Apple은 development 프로파일이면 aps-environment=development, production 프로파일과 TestFlight 베타라면 aps-environment=production으로 설정한다고 설명합니다.
가장 자주 헷갈리는 사례
dev 서버를 보는 TestFlight 앱
앱이 dev API와 dev Firebase를 사용하더라도 TestFlight로 설치한다면 프로파일은 App Store Connect다. 여기서 dev는 서버 환경 이름일 뿐 Apple의 Development 서명 방식이라는 뜻이 아닙니다.
Release 모드로 케이블 실행
flutter run --release 또는 Xcode Release configuration은 코드 최적화 방식을 뜻합니다. 실제 기기에 개발 실행하는 경우 프로파일은 여전히 iOS App Development일 수 있습니다. Release라는 단어만 보고 Apple Distribution 프로파일을 선택하면 안 됩니다.
같은 Bundle ID의 Debug와 TestFlight
동일한 Bundle ID를 쓰면 iPhone에서 같은 앱으로 취급됩니다. Debug 빌드를 설치하면 TestFlight 빌드를 덮어쓸 수 있고 반대도 동일합니다. APNs sandbox와 production의 device token도 서로 다를 수 있으므로 서버에는 최신 FCM token을 다시 등록해야 합니다.
자동 서명과 수동 서명
- 로컬 실기기 개발: Xcode Automatic Signing이 Xcode-managed Development 프로파일을 자동 생성할 수 있습니다.
- CI TestFlight 배포: 예시 프로젝트는 프로파일 파일을 CI 비밀 변수으로 주입하고 ExportOptions에서 이름을 지정하는 수동 서명 방식입니다.
- 자동 서명을 사용해도 App ID capability가 잘못돼 있으면 정상 entitlement를 만들 수 없습니다.
예시 프로젝트 기준 프로파일 구성
TestFlight용
| 환경 | Bundle ID | 프로파일 타입 | 프로파일 이름 |
|---|---|---|---|
| dev | com.example.app.dev |
App Store Connect | Example Dev |
| staging | com.example.app.stg |
App Store Connect | Example Stg |
| production | com.example.app |
App Store Connect | Example AppStore |
세 환경 모두 TestFlight로 배포하므로 이름이 dev/staging이어도 App Store Connect 프로파일을 사용합니다.
로컬 실기기 디버그용
필요할 때 다음 Development 프로파일을 별도로 만들거나 Xcode Automatic Signing에 맡깁니다.
| 환경 | Bundle ID | 프로파일 타입 | 권장 이름 |
|---|---|---|---|
| dev | com.example.app.dev |
iOS App Development | Example Dev Development |
| staging | com.example.app.stg |
iOS App Development | Example Stg Development |
| production | com.example.app |
iOS App Development | Example Prod Development |
로컬 테스트에 실제로 사용하지 않는 환경의 Development 프로파일은 미리 만들 필요가 없습니다.
Push Notifications와의 관계
- Bundle ID의 App ID에서 Push Notifications를 활성화합니다.
- capability 활성화 이후 프로파일을 생성하거나 재생성합니다.
- Development 프로파일에는
aps-environment=development가 있어야 합니다. - App Store Connect/TestFlight 프로파일에는
aps-environment=production이 있어야 합니다. - Firebase 프로젝트에는 해당 iOS 앱의 APNs 인증 정보가 설정돼 있어야 합니다.
- 실제 기기에서 알림 권한, APNs token, FCM token, 백엔드 등록 순으로 확인합니다.
Broadcast Capability은 ReplayKit 화면 방송용이므로 일반 APNs 푸시와 관계없습니다.
프로파일 파일 검사
다운로드한 .mobileprovision을 plist로 디코딩합니다.
security cms -D -i ExampleDev.mobileprovision > /tmp/profile.plist핵심 값을 확인합니다.
/usr/libexec/PlistBuddy -c 'Print :Name' /tmp/profile.plist
/usr/libexec/PlistBuddy -c 'Print :Entitlements:application-identifier' /tmp/profile.plist
/usr/libexec/PlistBuddy -c 'Print :Entitlements:aps-environment' /tmp/profile.plist
/usr/libexec/PlistBuddy -c 'Print :ExpirationDate' /tmp/profile.plistTestFlight용 dev 프로파일의 기대값 예시는 다음과 같습니다.
Name: Example Dev
application-identifier: ABCDE12345.com.example.app.dev
aps-environment: productionDevelopment 프로파일은 aps-environment: development여야 하며, 등록된 기기의 UDID가 ProvisionedDevices에 포함돼야 합니다.
최종 앱 서명 검사
소스의 .entitlements 파일만 보지 말고 최종 .app에 실제 서명된 entitlement를 확인합니다.
codesign -d --entitlements :- path/to/Runner.appCI에서는 프로파일 설치 직후와 archive/export 직후 두 번 검사하면 설정 누락을 TestFlight 업로드 전에 차단할 수 있습니다.
선택 체크리스트
- Xcode에서 케이블로 실행하는가? → iOS App Development 또는 Automatic Signing
- 등록된 소수 기기에 IPA를 전달하는가? → Ad Hoc
- TestFlight 또는 App Store Connect에 올리는가? → App Store Connect
- Push capability를 방금 변경했는가? → 기존 관련 프로파일 재생성
- 프로파일이 Invalid인가? → 신규 빌드에는 사용할 수 없으므로 재생성 후 교체
- 푸시가 안 오는가? → 최종
aps-environment, APNs token, FCM token 순으로 확인
공식 참고자료
함께 읽기
- EAS의 역사: 앱 빌드에서 모바일 배포 플랫폼까지EAS를 eas build 명령어의 이름으로만 이해하면 서비스의 절반만 보게 됩니다. EAS는 Expo Application Services의 약자입니다. 소스 코드를 앱 바이너리로 만들고, 스토어에 전달하고, 이미 설치된 앱에 호환되는 업데이트를 보내는 모바일 배포 과정을 여러 서비스로 나눈 플랫폼입니다.
- Expo의 역사: SDK 0에서 CNG와 개발 빌드까지Expo를 설명할 때 가장 자주 붙는 말은 "React Native를 쉽게 쓰게 해 주는 도구"입니다. 틀린 설명은 아니지만 지금의 Expo를 이해하기에는 범위가 너무 좁습니다. Expo는 미리 만들어진 앱에서 JavaScript를 실행하던 초기 경험을 출발점으로 삼았고, 지금은 네이티브 프로젝트 생성과 모듈 개발, 라…
- 실시간 소셜 룸 상태 관리: 입장·이탈·재접속 처리실시간 소셜 룸은 접속자 목록에 사용자를 추가하고 제거하는 기능만으로 유지되지 않습니다. 모바일 네트워크가 잠시 끊기거나 앱이 백그라운드로 가면 연결 종료 이벤트가 늦게 도착할 수 있고, 재접속한 사용자가 기존 아바타와 별도 참가자로 생성될 수도 있습니다.
- Unity 가상공간 로딩 최적화: Addressables와 Additive Scene 설계Unity 가상공간은 첫 화면에 필요한 UI와 사용자가 입장할 공간의 에셋이 다릅니다. 모든 Scene과 아바타, 텍스처를 시작 시점에 함께 로드하면 진입 시간이 길어지고 사용하지 않는 공간까지 메모리를 차지합니다.
- Unity 아바타 동기화: 위치·회전 보간과 네트워크 지터 처리Unity에서 원격 아바타의 위치를 네트워크로 받아 Transform에 바로 적용하면 움직임이 쉽게 끊깁니다. 화면은 매 프레임 렌더링되지만 위치 패킷은 더 낮은 빈도로 도착하고, 각 패킷의 간격도 일정하지 않기 때문입니다.