Showing posts with label xcode. Show all posts
Showing posts with label xcode. Show all posts

Friday, September 1, 2023

有効なプロビジョニングプロファイルが見つからない問題の修正

Chapter 1: プロビジョニングプロファイルの理解

プロビジョニングプロファイル(provisioning profile)は、iOSアプリケーション開発プロセスにおいて重要な要素です。これは開発者とそのアプリケーションを認証されたデバイスやサービスに関連付けるデジタルコレクションです。プロファイルにはアプリID、証明書、およびデバイス識別子が含まれ、これらすべてがアプリをデバイスにインストールするか、アプリストアに提出するために有効である必要があります。

プロビジョニングプロファイルは、Appleからの許可証としての役割を果たします。これはオペレーティングシステムにアプリが信頼できる出所(開発者)から署名され、デバイスで特定の操作を実行する権限を持っていることを示します。

プロビジョニングプロファイルには2つのタイプがあります: 開発(development)ディストリビューション(distribution)。開発プロビジョニングプロファイルは、アプリを開発中に登録されたデバイスで実行できるようにします。一方、ディストリビューションプロビジョニングプロファイルは、特定の登録済みデバイスに対するAd Hocデプロイメントまたはアプリストアを介したアプリのディストリビューションを可能にします。

これらのプロファイルが正しく機能するには、特定の要素を含める必要があります:

  • 証明書(Certificates): これらはApple開発者としてあなたを認証するデジタルドキュメントです。これにより、あなただけがアプリをあなたの名前で提出できるようになります。
  • アプリID: この識別子は、すべてのアプリのサービス(ゲームセンター、プッシュ通知など)を結びつけます。
  • デバイスリスト: 開発プロファイルの場合、このリストはアプリを実行できるテスト中のデバイスを識別します。

このグループ内のどの要素でも無効または欠落している場合、例えば、証明書が期限切れであるか、誤ったアプリIDが使用されている場合など、iOSはどのデバイスにもアプリをインストールしません。そのため、しばしば "この実行可能なアプリに対する有効なプロビジョニングプロファイルが見つかりません" などのエラーが発生します。次の章では、これらのエラーの原因と効果的な解決方法について詳しく説明します。

Chapter 2: 一般的なエラーの原因

"この実行可能なアプリに対する有効なプロビジョニングプロファイルが見つかりません" というエラーメッセージは、いくつかの要因によって発生する可能性があります。これらの原因を理解することは、問題の解決の第一歩です。一般的な原因は次のとおりです:

  • 期限切れのプロビジョニングプロファイルまたは証明書: プロビジョニングプロファイルと証明書には有効期限があります。どちらかが期限切れの場合、アプリを開発またはディストリビュートし続けるためにそれらを更新する必要があります。
  • 不一致のアプリID: プロビジョニングプロファイルに指定されたアプリIDは、アプリで使用されるものと一致する必要があります。不一致がある場合、このエラーが発生する可能性があります。
  • プロビジョニングプロファイルに含まれていないデバイス: 開発プロビジョニングプロファイルの場合、プロファイルに含まれていないデバイスにアプリをインストールしようとすると、このエラーが発生する可能性があります。
  • アプリ署名プロセスが未完了: アプリ署名プロセスには、コード署名および有効な証明書およびプロビジョニングプロファイルでのパッケージ生成などの複数のステップが含まれます。ここでのどんな誤りもエラーを引き起こす可能性があります。

これ以外にも、プロジェクト設定内で直接変更された内容や、デバイス上で互いに競合する可能性のある複数のバージョンのXcodeがインストールされている場合など、一般的でない理由でこの問題が発生する可能性があります。

いずれの場合でも、根本原因を特定することは効果的な解決のために重要です。次の章では、これらの問題を診断し、解決に役立つさまざまな方法について詳しく説明します。

Chapter 3: エラーの解決方法

"この実行可能なアプリに対する有効なプロビジョニングプロファイルが見つかりません" エラーの潜在的な原因を確認した後、解決策を試すことができます。以下に一般的な解決策のいくつかを示します:

  • 期限切れの証明書またはプロビジョニングプロファイルを更新: 証明書またはプロビジョニングプロファイルが期限切れの場合、Appleの開発者ポータルを使用してそれらを更新してください。更新されたプロファイルをダウンロードし、マシンにインストールする必要があります。
  • 不一致のアプリIDを修正: アプリとプロビジョニングプロファイルで使用されるアプリIDが一致するように修正してください。これには、アプリのバンドル識別子やプロビジョニングプロファイルに指定されたアプリIDのいずれかを更新する作業が含まれる場合があります。
  • プロビジョニングプロファイルにデバイスを追加: 開発プロビジョニングプロファイルに含まれていないデバイスにアプリをインストールしようとする場合、該当するデバイスのUDIDをAppleの開発者アカウントのデバイスリストに追加してください。その後、プロビジョニングプロファイルを再生成し、再度インストールしてみてください。
  • プロジェクトをクリーンアップして再ビルド: Xcode内で定期的にプロジェクトをクリーンアップ(Cmd+Shift+K)し、再ビルド(Cmd+B)することは、古いビルドアーティファクトや古いキャッシュに関連する問題を解決するのに役立つことがあります。

これらの方法のいずれも問題を解決しない場合、いくつかの高度なテクニックを試すこともできます:

  • 派生データの削除: Xcodeは「派生データ(Derived Data)」と呼ばれる中間ビルド情報を保存します。これらのデータを削除(Xcode > Preferences > Locations > Derived Data > Delete)することで、さまざまなビルドの問題を解決できることがあります。
  • プロジェクトの.pbxprojファイルを編集: プロジェクトの.pbxprojファイルにはプロジェクト設定に関する重要な情報が含まれています。時にはここで手動で編集が必要で、自動設定が期待どおりに動作しない場合があります。

すべての他の試みが失敗した場合、AppleサポートやStack Overflowなどのオンラインコミュニティから助けを求めることが、問題解決に追加の洞察を提供するかもしれません。

Chapter 4: 将来のエラーの予防

"この実行可能なアプリに対する有効なプロビジョニングプロファイルが見つかりません" エラーを解決した後、このような問題が将来発生しないように対策を講じることが重要です。以下はいくつかの最善の実践方法です:

  • 定期的に証明書とプロビジョニングプロファイルの有効性を確認: 証明書とプロビジョニングプロファイルの有効期限を定期的に確認し、期限が切れる前に更新してください。
  • 一貫性のあるアプリIDを維持: アプリとプロビジョニングプロファイルで使用するアプリIDが一致するように維持してください。これらの識別子を頻繁に変更しないよう努力してください。
  • デバイスリストを更新: テストデバイスを追加または削除するたびに、開発プロビジョニングプロファイルのデバイスリストを定期的に更新してください。
  • プロジェクトを定期的にクリーンアップ: Xcode内で定期的にプロジェクトをクリーンアップ(Cmd+Shift+K)し、再ビルド(Cmd+B)して古いキャッシュや古いビルドアーティファクトに関連する問題を避けてください。

これら以外にも、Appleがアプリ開発プロセスとツールに関する変更を発表するたびに、更新または廃止された機能に関連する問題を回避するために常に注意を払ってください。

デバッグに計画的なアプローチを採用して最良の結果を得てください。すべての問題には解決策が存在することを覚えており、それを見つけるのは問題ではありません!

초보자도 1분 만에 해결하는 iOS 앱 실행 오류

Chapter 1: 프로비저닝 프로파일 이해하기

프로비저닝 프로파일(provisioning profile)은 iOS 앱 개발 프로세스에서 중요한 구성 요소입니다. 이것은 개발자와 그들의 앱을 인증된 기기 및 서비스에 연결하는 디지털 개체 모음입니다. 프로필에는 앱 ID, 인증서 및 기기 식별자가 포함되어 있으며, 이 모든 것이 앱을 기기에 설치하거나 앱 스토어에 제출하기 위해 유효해야 합니다.

프로비저닝 프로파일은 Apple로부터의 허가서 역할을 합니다. 이것은 운영 체제에게 앱이 신뢰할 수 있는 출처(개발자)에서 서명되었고 기기에서 특정 작업을 수행할 권한을 갖고 있음을 알려줍니다.

프로비저닝 프로파일에는 두 가지 유형이 있습니다: 개발(development)배포(distribution). 개발 프로비저닝 프로파일은 앱을 개발하는 동안 등록된 기기에서 앱을 실행할 수 있게 합니다. 다른 쪽으로, 배포 프로비저닝 프로파일은 Ad Hoc 배포(특정 등록된 기기로) 또는 앱 스토어를 통해 앱을 배포할 수 있게 합니다.

이러한 프로필이 제대로 작동하려면 특정 요소를 포함해야 합니다:

  • 인증서(Certificates): 이것들은 당신을 Apple 개발자로 인증하는 디지털 문서입니다. 이것들은 당신만이 당신의 이름으로 앱을 제출할 수 있도록 보장합니다.
  • 앱 ID: 이 식별자는 모든 앱의 서비스(게임 센터, 푸시 알림 등)를 하나로 묶습니다.
  • 기기 목록: 개발 프로필의 경우, 이 목록은 테스트 중에 앱을 실행할 수 있는 기기를 식별합니다.

이 그룹 내의 어떤 요소라도 유효하지 않거나 누락된 경우 - 예를 들어, 인증서가 만료되었거나 잘못된 앱 ID가 사용된 경우 - iOS는 어떤 기기에도 앱을 설치하지 않습니다. 이로 인해 종종 "이 실행 가능한 앱에 대한 유효한 프로비저닝 프로파일을 찾을 수 없음"과 같은 오류가 발생합니다. 다음 장에서는 이러한 오류의 원인과 효과적으로 해결하는 방법에 대해 자세히 살펴보겠습니다.

Chapter 2: 에러의 일반적인 원인

"이 실행 가능한 앱에 대한 유효한 프로비저닝 프로파일을 찾을 수 없음"이라는 오류 메시지는 여러 가지 요인에 의해 발생할 수 있습니다. 이러한 원인을 이해하는 것은 문제 해결의 첫걸음입니다. 일반적인 원인은 다음과 같습니다:

  • 만료된 프로비저닝 프로파일 또는 인증서: 프로비저닝 프로파일과 인증서는 만료 날짜가 있습니다. 둘 중 하나라도 만료되면 앱을 계속 개발하거나 배포하기 위해 갱신해야 합니다.
  • 잘못된 앱 ID: 프로비저닝 프로파일에 지정된 앱 ID가 앱에서 사용하는 것과 일치해야 합니다. 불일치하면 이 오류가 발생할 수 있습니다.
  • 프로비저닝 프로파일에 포함되지 않은 기기: 개발 프로비저닝 프로파일의 경우, 앱을 설치하고 테스트할 수 있는 기기 목록이 프로필에 포함된 것으로 제한됩니다. 그 목록에 포함되지 않은 기기에 앱을 설치하려고 하면 이 오류가 발생할 수 있습니다.
  • 앱 서명 프로세스 미완료: 앱 서명 프로세스는 코드 서명 및 유효한 인증서 및 프로비저닝 프로파일로 패키지 생성과 같은 여러 단계를 포함합니다. 여기서 어떤 실수든 오류를 발생시킬 수 있습니다.

이외에도 Xcode의 프로젝트 설정 내에서 직접 변경된 내용이나 기기 빌드 중에 서로 충돌할 수 있는 머신에 여러 버전의 Xcode가 설치된 경우와 같이 덜 일반적인 이유로 이 문제가 발생할 수 있습니다.

어떤 경우에도 루트 원인을 식별하는 것은 효과적으로 해결하기 위해 필수적입니다. 다음 장에서는 이러한 문제를 진단하고 해결하는 데 도움이 될 수 있는 여러 가지 방법을 논의합니다.

Chapter 3: 에러 해결 방법

"이 실행 가능한 앱에 대한 유효한 프로비저닝 프로파일을 찾을 수 없음" 오류의 잠재적인 원인을 확인한 후, 해결 방법을 시도할 수 있습니다. 여기에 일반적인 해결책 몇 가지가 있습니다:

  • 만료된 인증서 또는 프로비저닝 프로파일 갱신: 인증서 또는 프로비저닝 프로파일이 만료된 경우, Apple의 개발자 포털을 통해 갱신하십시오. 업데이트된 프로필을 다운로드하고 머신에 설치해야 합니다.
  • 불일치하는 앱 ID 수정: 앱과 프로비저닝 프로파일에서 사용되는 앱 ID 사이에 불일치가 있는 경우, 이를 수정하십시오. 이는 앱의 번들 식별자나 프로비저닝 프로파일에 지정된 앱 ID 중 하나를 업데이트하는 작업을 포함할 수 있습니다.
  • 프로비저닝 프로파일에 기기 추가: 개발 프로비저닝 프로파일에 포함되지 않은 기기에 앱을 설치하려는 경우, 해당 기기의 UDID를 Apple 개발자 계정의 기기 목록에 추가하십시오. 그런 다음 프로비저닝 프로파일을 재생성하고 다시 설치하십시오.
  • 프로젝트 정리 및 재빌드: 때로는 Xcode 내에서 정리(Cmd+Shift+K) 및 재빌드(Cmd+B)를 수행하는 것이 오래된 빌드 아티팩트 또는 오래된 캐시와 관련된 문제를 해결하는 데 도움이 될 수 있습니다.

이러한 방법 중 어느 것도 문제를 해결하지 못하는 경우, 더 고급 기술 몇 가지를 시도할 수 있습니다:

  • 파생 데이터 삭제: Xcode는 "파생 데이터(Derived Data)"라고 하는 중간 빌드 정보를 저장합니다. 이 데이터를 삭제(Xcode > 환경 설정 > 위치 > 파생 데이터 > 삭제)하면 다양한 빌드 문제를 해결할 수 있습니다.
  • 프로젝트.pbxproj 파일 편집: 프로젝트.pbxproj 파일에는 프로젝트 설정에 관한 중요한 정보가 포함되어 있습니다. 때로는 여기에서 수동 편집이 필요할 수 있으며, 자동 설정이 예상대로 작동하지 않는 경우입니다.

모든 다른 시도가 실패하는 경우, Apple 지원이나 Stack Overflow와 같은 온라인 커뮤니티에서 도움을 요청하는 것이 문제 해결에 대한 추가 통찰력을 제공할 수 있습니다.

Chapter 4: 미래 에러 방지

"이 실행 가능한 앱에 대한 유효한 프로비저닝 프로파일을 찾을 수 없음" 오류를 해결한 후, 이러한 문제가 향후 발생하지 않도록 조치를 취하는 것이 중요합니다. 여기에 몇 가지 최상의 실천 방법이 있습니다:

  • 인증서와 프로비저닝 프로파일 유효성 주기적으로 확인: 인증서와 프로비저닝 프로파일의 만료 날짜를 주기적으로 확인하고, 만료 전에 갱신하십시오.
  • 일관된 앱 ID 유지: 앱과 프로비저닝 프로파일에서 사용하는 앱 ID가 일치하도록 확인하십시오. 이러한 식별자를 자주 변경하지 않도록 노력하십시오.
  • 기기 목록 업데이트: 테스트 기기를 추가하거나 제거할 때마다 개발 프로비저닝 프로파일의 기기 목록을 정기적으로 업데이트하십시오.
  • 프로젝트 정기적으로 정리: Xcode 내에서 정기적으로 프로젝트를 정리(Cmd+Shift+K)하고 재빌드(Cmd+B)하여 오래된 캐시나 오래된 빌드 아티팩트와 관련된 문제를 피하십시오.

이러한 것 외에도 Apple이 앱 개발 프로세스와 도구에 관한 변경 사항을 발표할 때마다 업데이트 또는 폐기된 기능으로 인한 잠재적인 문제를 피하려면 항상 주시하십시오.

최상의 결과를 얻기 위해 디버깅에 대한 계획적인 접근 방식을 채택하십시오. 모든 문제에는 해결 방법이 있다는 것을 기억하십시오 - 단지 그것을 찾는 문제입니다!

Solving "A valid provisioning profile for this executable was not found"

Chapter 1: Understanding Provisioning Profiles

A provisioning profile is a crucial component in the iOS app development process. It is essentially a collection of digital entities that tie developers and their apps to authorized devices and services. The profile includes an App ID, certificates, and device identifiers, all of which must be valid for an app to be installed on a device or submitted to the App Store.

The provisioning profile can be seen as a permission slip from Apple. It tells the operating system that the app has been signed by a trusted source (the developer) and that it has permission to perform certain actions on the device.

There are two types of provisioning profiles: development and distribution. A development provisioning profile allows your app to run on registered devices while you're developing it. On the other hand, a distribution provisioning profile allows you to distribute your app either through Ad Hoc distribution (to specific registered devices), or through the App Store.

In order for these profiles to work properly, they must contain certain elements:

  • Certificates: These are digital documents that authenticate you as an Apple developer. They ensure that only you can submit apps under your name.
  • App ID: This identifier ties together all your apps' services like Game Center, Push Notifications etc., into one group.
  • List of Devices: For development profiles only, this list identifies which devices are allowed to run your application during testing.

If any element within this group is invalid or missing - such as if a certificate has expired or if an incorrect App ID is used - then iOS will not permit installation of the application on any device. This often results in errors like "A valid provisioning profile for this executable was not found". In our subsequent chapters we will delve deeper into what causes these errors and how we can fix them effectively.

Chapter 2: Common Causes of the Error

The error message "A valid provisioning profile for this executable was not found" can be caused by a number of factors. Understanding these causes is the first step towards resolving the issue. Here are some common causes:

  • Expired Provisioning Profile or Certificate: Provisioning profiles and certificates have an expiration date. If either expires, you will need to renew them in order to continue developing or distributing your app.
  • Invalid App ID: The App ID specified in your provisioning profile must match the one used in your app. If there is a mismatch, this error may occur.
  • Device Not Included in Provisioning Profile: For development provisioning profiles, the list of devices on which you can install and test your app is limited to those included in the profile. If you attempt to install your app on a device not included in that list, this error may occur.
  • Incomplete App Signing Process: The process of signing an application involves various steps including code signing and package generation with valid certificates and provisioning profiles. Any misstep here could lead to errors.

In addition to these, there could be other less common reasons causing this issue like changes made directly within Xcode's project settings or having multiple versions of Xcode installed on your machine which might conflict with each other during builds.

In any case, identifying the root cause is essential for resolving it effectively. In our next chapter we will discuss several methods that can help you diagnose and fix these issues.

Chapter 3: How to Fix the Error

Once you've identified the potential cause of the "A valid provisioning profile for this executable was not found" error, you can start implementing solutions. Here are some common fixes:

  • Renew Expired Certificates or Provisioning Profiles: If your certificate or provisioning profile has expired, renew it through Apple's Developer portal. Make sure to download and install any updated profiles on your machine.
  • Correct Mismatched App IDs: If there's a mismatch between the App ID in your app and in your provisioning profile, correct it. This may involve updating either the app's bundle identifier or the App ID specified in the provisioning profile.
  • Add Missing Devices to Your Provisioning Profile: If you're trying to install your app on a device that isn't included in your development provisioning profile, add that device's UDID to the list of devices in your Apple Developer account. Then regenerate and reinstall the provisioning profile.
  • Clean and Rebuild Your Project: Sometimes, cleaning (Cmd+Shift+K) and rebuilding (Cmd+B) your project within Xcode can resolve issues related to stale caches or old build artifacts.

If none of these methods solve your problem, there are a few more advanced techniques you can try:

  • Delete Derived Data: Xcode stores intermediate build information known as "Derived Data." Deleting this data (Xcode > Preferences > Locations > Derived Data > Delete) can often resolve various build issues.
  • Edit Project.pbxproj File: The project.pbxproj file contains important information about project settings. Sometimes manual edits here might be required if automatic settings aren't working as expected.

If all else fails, reaching out for help from Apple Support or online communities like Stack Overflow could provide further insights into resolving this issue.

Chapter 4: Preventing Future Errors

After troubleshooting the "A valid provisioning profile for this executable was not found" error, it's important to take steps to prevent such issues from recurring in the future. Here are some best practices:

  • Regularly Check Certificate and Provisioning Profile Validity: Make a habit of checking the expiration dates of your certificates and provisioning profiles regularly, and renew them before they expire.
  • Maintain Consistent App IDs: Ensure that the App ID in your app matches with that in your provisioning profile. Avoid changing these identifiers frequently.
  • Keep Device List Updated: Regularly update the list of devices in your development provisioning profile as you add or remove test devices.
  • Clean Project Regularly: Regularly clean (Cmd+Shift+K) and rebuild (Cmd+B) your project within Xcode to avoid issues related to stale caches or old build artifacts.

In addition to these, always keep up with changes announced by Apple regarding app development processes and tools. This will help you stay ahead of potential issues caused by updates or deprecated features.

Above all, adopting a systematic approach towards debugging can save you a lot of time and effort. Remember that every problem has a solution - it's just about finding it!

Friday, November 29, 2019

Xcode 빌드 환경 완벽 분리: dev, stage, prod 환경별 GoogleService-Info.plist 자동 전환 설정법

하나의 앱을 개발하다 보면 단순히 '개발'과 '출시'라는 두 가지 상황만 존재하지 않습니다. 실제 현업에서는 내부 테스트를 위한 개발(Development) 서버, QA팀이나 외부 테스터를 위한 스테이징(Staging) 서버, 그리고 실제 사용자가 사용하는 운영(Production) 서버 등 여러 환경을 동시에 관리해야 하는 경우가 비일비재합니다. 각 환경은 서로 다른 데이터베이스, API 엔드포인트, 그리고 외부 서비스 키를 사용하게 됩니다.

이러한 복잡성 속에서 iOS 개발자들이 가장 흔하게 마주치는 난관 중 하나는 바로 Firebase 설정입니다. 특히 푸시 알림을 위한 FCM(Firebase Cloud Messaging)을 사용한다면, 각 빌드 환경에 맞는 별도의 Firebase 프로젝트를 사용해야 합니다. 이는 즉, 환경마다 다른 Bundle Identifier를 가져야 하고, 그에 따라 고유한 GoogleService-Info.plist 파일을 필요로 한다는 의미입니다. 많은 개발자들이 이 파일을 수동으로 교체하거나, 주석 처리하는 방식으로 번거롭게 관리하곤 합니다. 하지만 이런 방식은 실수를 유발하기 쉽고, 팀 단위 협업에서는 큰 혼란을 야기할 수 있습니다.

이 글에서는 Xcode의 빌드 설정(Build Configurations)과 스킴(Schemes)을 활용하여 개발, 스테이징, 운영 환경을 체계적으로 분리하고, 빌드 시점에 각 환경에 맞는 GoogleService-Info.plist 파일이 자동으로 적용되도록 설정하는 전문가적인 방법을 상세히 다룹니다. 이 가이드를 끝까지 따라오시면, 더 이상 .plist 파일 때문에 고통받는 일 없이, 버튼 클릭 한 번으로 원하는 환경의 앱을 빌드하고 실행할 수 있게 될 것입니다.

1. 기본 개념 이해하기: Configurations와 Schemes

본격적인 설정에 앞서 Xcode의 핵심 개념인 빌드 설정(Build Configurations)과 스킴(Schemes)에 대한 이해가 필요합니다. 이 둘의 관계를 정확히 알아야 전체 프로세스를 효과적으로 제어할 수 있습니다.

빌드 설정 (Build Configurations)

빌드 설정은 특정 타겟을 빌드할 때 사용되는 '설정 값들의 묶음'입니다. Xcode 프로젝트를 처음 생성하면 기본적으로 DebugRelease 두 가지 설정이 제공됩니다.

  • Debug: 개발 과정에서 사용되는 설정입니다. 디버깅 심볼이 포함되고, 코드 최적화 수준이 낮아 변수 값을 확인하거나 브레이크포인트를 사용하는 데 용이합니다.
  • Release: 앱 스토어에 배포하거나 사용자에게 전달할 때 사용되는 설정입니다. 코드가 최적화되어 실행 속도가 빠르고, 앱 용량이 작아지며, 디버깅 정보는 포함되지 않습니다.

우리는 이 기본 설정에 더해 'development', 'staging', 'production'과 같은 우리만의 환경 구분을 추가할 것입니다. 예를 들어, Debug-development, Release-production 과 같이 조합하여 사용할 수 있습니다.

스킴 (Schemes)

스킴은 '무엇을(Target), 어떻게(Configuration), 어떤 액션(Run, Test, Profile...)으로 실행할 것인가'를 정의하는 '실행 계획'입니다. Xcode 상단에서 타겟 기기 옆에 보이는 드롭다운 메뉴가 바로 스킴을 선택하는 곳입니다.

하나의 스킴은 다음과 같은 정보를 포함합니다.

  • 빌드할 타겟(들)의 목록
  • 빌드(Build), 실행(Run), 테스트(Test), 프로파일링(Profile), 분석(Analyze), 아카이브(Archive) 각 액션에 사용할 빌드 설정(Configuration)
  • 실행 시 전달할 인자(Arguments)나 환경 변수(Environment Variables)

우리는 "MyApp-Dev", "MyApp-Prod"와 같은 스킴을 만들고, "MyApp-Dev" 스킴의 'Run' 액션은 Debug-development 설정을 사용하고, "MyApp-Prod" 스킴의 'Archive' 액션은 Release-production 설정을 사용하도록 연결할 것입니다. 이로써 개발자는 단순히 스킴을 전환하는 것만으로 빌드 환경 전체를 손쉽게 바꿀 수 있습니다.

2. 단계별 실전 가이드: 빌드 환경 구축하기

이제 개념을 알았으니, 실제 프로젝트에 적용해 보겠습니다. 여기서는 간단하게 개발(development)과 운영(production) 두 가지 환경을 분리하는 것을 목표로 하겠습니다. 이 원리를 이해하면 스테이징(staging) 등 더 많은 환경으로 확장하는 것은 매우 쉽습니다.

Step 1: Firebase에서 환경별 프로젝트 및 `GoogleService-Info.plist` 준비

  1. Firebase 콘솔로 이동하여 2개의 프로젝트를 생성합니다. 하나는 개발용(예: 'MyAwesomeApp-Dev'), 다른 하나는 운영용(예: 'MyAwesomeApp-Prod')입니다.
  2. 각 Firebase 프로젝트에 iOS 앱을 추가합니다. 이때 가장 중요한 것은 Bundle Identifier를 다르게 설정하는 것입니다.
    • 개발용 앱: com.mycompany.myawesomeapp.dev
    • 운영용 앱: com.mycompany.myawesomeapp
  3. 각 프로젝트에서 GoogleService-Info.plist 파일을 다운로드합니다. 이제 2개의 .plist 파일이 준비되었습니다.
  4. 혼동을 피하기 위해 파일 이름을 명확하게 변경합니다.
    • 개발용 파일 → GoogleService-Info-dev.plist
    • 운영용 파일 → GoogleService-Info-prod.plist

Step 2: Xcode에서 커스텀 빌드 설정(Configurations) 생성하기

이제 Xcode 프로젝트로 돌아와 빌드 설정을 복제하고 새로운 설정을 만듭니다.

  1. Xcode에서 프로젝트 파일을 선택하고, 'PROJECT' 섹션의 'Info' 탭으로 이동합니다.
  2. 'Configurations' 항목을 찾습니다. 기본적으로 'Debug'와 'Release'가 보일 것입니다.
  3. 하단의 '+' 버튼을 클릭하고 'Duplicate "Debug" Configuration'을 선택합니다. 새로 생성된 'Debug Copy'의 이름을 Debug-development로 변경합니다.
  4. 같은 방식으로 'Duplicate "Debug" Configuration'을 한번 더 선택하고, 이름을 Debug-production으로 변경합니다.
  5. 이번에는 'Duplicate "Release" Configuration'을 선택하고, 이름을 Release-development로 변경합니다.
  6. 마지막으로 'Duplicate "Release" Configuration'을 다시 선택하고, 이름을 Release-production으로 변경합니다.

작업이 끝나면 아래와 같이 총 6개의 설정(기본 2개 + 신규 4개)이 보일 것입니다. (필요에 따라 기본 Debug/Release는 삭제하거나, 더 단순하게 Debug-dev, Release-prod 2개만 추가해도 무방합니다. 여기서는 모든 경우의 수를 다루기 위해 4개를 추가했습니다.)

Step 3: 환경별 Bundle Identifier 및 기타 설정 적용하기

새로 만든 빌드 설정에 따라 각기 다른 Bundle Identifier를 적용해야 합니다.

  1. 'TARGETS' 섹션에서 당신의 앱 타겟을 선택하고 'Build Settings' 탭으로 이동합니다.
  2. 검색창에 Product Bundle Identifier를 검색합니다.
  3. 해당 항목의 각 설정 옆에 다른 값을 입력할 수 있습니다.
    • Debug-development: com.mycompany.myawesomeapp.dev
    • Release-development: com.mycompany.myawesomeapp.dev
    • Debug-production: com.mycompany.myawesomeapp
    • Release-production: com.mycompany.myawesomeapp
  4. 같은 방식으로 앱 이름(Product Name), 앱 아이콘(Asset Catalog App Icon Set Name) 등도 환경별로 다르게 설정할 수 있습니다. 예를 들어 개발용 앱은 이름 뒤에 '(Dev)'를 붙이고 아이콘에 'DEV' 리본을 추가하면 구분이 매우 용이해집니다.

Step 4: 커스텀 스킴(Schemes) 생성 및 연결하기

이제 이 모든 설정을 편리하게 사용하기 위한 스킴을 만들 차례입니다.

  1. Xcode 상단의 스킴 드롭다운 메뉴를 클릭하고 'Manage Schemes...'를 선택합니다.
  2. 기존 스킴을 선택하고 하단의 톱니바퀴 아이콘을 클릭한 뒤 'Duplicate'를 선택합니다.
  3. 복제된 스킴의 이름을 'MyAwesomeApp-Dev'로 변경합니다.
  4. 새로 만든 'MyAwesomeApp-Dev' 스킴을 선택하고 'Edit...' 버튼을 클릭합니다.
  5. 왼쪽 메뉴에서 각 액션(Run, Test, Profile, Analyze, Archive)을 선택하고, 오른쪽의 'Build Configuration'을 우리가 만든 설정과 연결합니다.
    • Run: Debug-development
    • Test: Debug-development
    • Profile: Release-development
    • Analyze: Debug-development
    • Archive: Release-development
  6. 같은 방식으로 'MyAwesomeApp-Prod' 스킴을 생성하고, 이번에는 production용 설정과 연결합니다.
    • Run: Debug-production
    • Test: Debug-production
    • Profile: Release-production
    • Analyze: Debug-production
    • Archive: Release-production

이제 Xcode 상단 메뉴에서 'MyAwesomeApp-Dev' 스킴을 선택하고 빌드하면 development 설정으로, 'MyAwesomeApp-Prod'를 선택하면 production 설정으로 앱이 빌드됩니다.

3. 핵심: Run Script로 `GoogleService-Info.plist` 자동 교체하기

지금까지의 설정은 앱의 Bundle ID나 이름을 바꾸는 것이었습니다. 하지만 가장 중요한 GoogleService-Info.plist 파일은 아직 그대로입니다. 이 파일을 빌드 시점에 동적으로 교체해주는 마법이 바로 'Run Script' 빌드 단계입니다.

Step 1: 프로젝트에 설정 파일 추가하기

  1. Xcode 프로젝트 내부에 설정 파일을 보관할 그룹(폴더)을 만듭니다. 'Config' 또는 'Firebase' 같은 이름이 적합합니다.
  2. Finder에서 해당 폴더를 열고, Step 1에서 이름을 변경해 두었던 GoogleService-Info-dev.plistGoogleService-Info-prod.plist 파일을 복사해 넣습니다.
  3. 이 파일들을 Xcode 프로젝트 내비게이터의 'Config' 그룹으로 드래그 앤 드롭하여 프로젝트에 추가합니다.
  4. 파일 추가 시 나타나는 옵션 창에서 **'Add to targets' 체크박스를 반드시 해제해야 합니다.** 이것이 매우 중요합니다. 만약 체크하면 Xcode가 이 파일들을 직접 번들에 포함시키려 하여 우리가 작성할 스크립트와 충돌하거나, 의도치 않은 파일이 포함될 수 있습니다. 우리는 스크립트를 통해 '복사'할 것이므로, 타겟 멤버십에는 포함시키지 않습니다.

Step 2: Run Script 빌드 단계 추가하기

이제 빌드 프로세스 중에 실행될 스크립트를 추가합니다.

  1. 'TARGETS' 섹션에서 당신의 앱 타겟을 선택하고 'Build Phases' 탭으로 이동합니다.
  2. 상단의 '+' 버튼을 클릭하고 'New Run Script Phase'를 선택합니다.
  3. 새로 생성된 'Run Script' 단계가 보일 것입니다. 이 단계의 순서는 매우 중요합니다. 'Copy Bundle Resources' 단계 **바로 이전**으로 드래그하여 옮겨주세요. 이렇게 해야 우리가 복사한 파일이 최종 앱 번들에 정상적으로 포함됩니다.
  4. 'Run Script' 단계의 이름을 'Copy GoogleService-Info.plist'와 같이 명확하게 변경하면 나중에 관리하기 좋습니다.
Xcode의 Build Phases 탭에서 New Run Script Phase 추가
Xcode Build Phases에서 새로운 Run Script 단계 추가하기

Step 3: 스크립트 작성 및 적용

이제 새로 만든 Run Script 단계의 쉘 스크립트 입력창에 아래 코드를 붙여넣습니다. 코드는 각자의 프로젝트 구조에 맞게 일부 수정이 필요할 수 있습니다.


# 스크립트 실행 시점에 현재 어떤 빌드 설정(Configuration)인지 출력합니다. (디버깅용)
echo "Executing 'Copy GoogleService-Info.plist' script for configuration: ${CONFIGURATION}"

# plist 파일들이 위치한 경로를 지정합니다. 
# ${PROJECT_DIR}은 프로젝트의 루트 디렉토리를 의미하는 Xcode 환경 변수입니다.
# 'Config'는 Step 1에서 우리가 만든 폴더(그룹) 이름입니다. 실제 폴더 경로와 일치해야 합니다.
PATH_TO_GOOGLE_PLISTS="${PROJECT_DIR}/YourAppName/Config"

# 현재 빌드 설정(Configuration)에 따라 사용할 plist 파일을 결정합니다.
case "${CONFIGURATION}" in

  # Development 환경용 설정들
  "Debug-development" | "Release-development" )
    SOURCE_PLIST_PATH="${PATH_TO_GOOGLE_PLISTS}/GoogleService-Info-dev.plist"
    echo "Using Development plist."
    ;;

  # Production 환경용 설정들
  "Debug-production" | "Release-production" )
    SOURCE_PLIST_PATH="${PATH_TO_GOOGLE_PLISTS}/GoogleService-Info-prod.plist"
    echo "Using Production plist."
    ;;

  # 그 외의 경우 (예: 기본 Debug, Release 등) - 기본적으로 Production을 사용하도록 설정하거나 에러를 발생시킬 수 있습니다.
  *)
    SOURCE_PLIST_PATH="${PATH_TO_GOOGLE_PLISTS}/GoogleService-Info-prod.plist"
    echo "Warning: No specific plist for this configuration. Using Production plist as a fallback."
    ;;
esac

# 최종적으로 앱 번들에 복사될 경로를 지정합니다.
# ${BUILT_PRODUCTS_DIR}는 빌드된 결과물(.app 파일)이 위치한 디렉토리입니다.
# ${PRODUCT_NAME}은 빌드 설정에 따라 정해진 제품 이름입니다.
DESTINATION_PLIST_PATH="${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"

# 원본 파일이 존재하는지 확인합니다.
if [ -f "${SOURCE_PLIST_PATH}" ]; then
  # 원본 파일을 최종 목적지로 복사합니다. 
  # 복사 후 파일 이름은 반드시 'GoogleService-Info.plist'가 되어야 Firebase SDK가 인식할 수 있습니다.
  cp -r "${SOURCE_PLIST_PATH}" "${DESTINATION_PLIST_PATH}"
  echo "Successfully copied ${SOURCE_PLIST_PATH} to ${DESTINATION_PLIST_PATH}"
else
  # 원본 파일을 찾을 수 없는 경우, 빌드를 실패시켜 문제를 즉시 인지하게 합니다.
  echo "error: GoogleService-Info plist not found at ${SOURCE_PLIST_PATH}. Please check the path and file name."
  exit 1
fi

스크립트 해설:

  • ${CONFIGURATION}: Xcode가 빌드 시점에 자동으로 채워주는 환경 변수로, 현재 사용 중인 빌드 설정의 이름(예: 'Debug-development')을 담고 있습니다.
  • case "${CONFIGURATION}" in ... esac: 쉘 스크립트의 switch-case 구문입니다. ${CONFIGURATION} 변수 값에 따라 다른 동작을 하도록 분기합니다. | 문자는 OR 조건으로, 여러 설정을 하나의 케이스에서 처리할 수 있게 해줍니다.
  • PATH_TO_GOOGLE_PLISTS: GoogleService-Info-dev.plistGoogleService-Info-prod.plist 파일이 위치한 실제 폴더 경로를 지정해야 합니다. ${PROJECT_DIR}은 프로젝트의 .xcodeproj 파일이 있는 루트 디렉토리입니다. 그 하위 경로를 정확하게 적어주세요.
  • ${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist: 이 부분이 핵심입니다. 빌드 과정에서 생성되는 앱 패키지(.app) 내부에, 우리가 선택한 원본 plist 파일을 GoogleService-Info.plist라는 최종 이름으로 복사해 넣는 명령입니다. 어떤 원본 파일을 사용했든, 최종 결과물의 이름은 항상 이것이어야 합니다.
  • if [ -f ... ] / else / exit 1: 스크립트의 안정성을 높이는 부분입니다. 지정된 경로에 원본 plist 파일이 존재하는지 확인하고, 만약 없다면 빌드 로그에 에러 메시지를 출력하고 빌드를 강제로 실패시킵니다. 이는 잘못된 설정으로 앱이 빌드되어 런타임에 크래시가 발생하는 것을 사전에 방지하는 매우 중요한 방어 코드입니다.

이제 모든 설정이 끝났습니다. Xcode 상단에서 'MyAwesomeApp-Dev' 스킴을 선택하고 빌드(Cmd+R)하면 Run Script가 실행되어 GoogleService-Info-dev.plist가 앱 번들에 포함되고, 'MyAwesomeApp-Prod' 스킴으로 빌드하면 GoogleService-Info-prod.plist가 포함됩니다. 이제 더 이상 수동으로 파일을 관리할 필요가 없습니다!

4. 고급 팁: `.xcconfig` 파일로 설정 관리 고도화하기

Run Script 방식은 매우 강력하지만, Bundle ID나 Product Name 같은 설정들을 Xcode의 GUI(Build Settings)에서 직접 관리하는 것은 프로젝트가 커질수록 불편해질 수 있습니다. 이 설정들을 텍스트 기반의 .xcconfig 파일로 분리하면 훨씬 깔끔하고 전문적인 관리가 가능합니다.

`.xcconfig` 파일이란?

Xcode Configuration Settings File(.xcconfig)은 빌드 설정을 Key-Value 형태로 저장하는 텍스트 파일입니다. 이를 사용하면 다음과 같은 장점이 있습니다.

  • 가독성 및 관리 용이성: 복잡한 Build Settings UI 대신 텍스트 파일에서 설정을 한눈에 파악하고 수정할 수 있습니다.
  • 소스 컨트롤(Git 등) 친화적: .pbxproj 파일의 충돌(conflict)을 줄여줍니다. 여러 개발자가 빌드 설정을 변경할 때 .pbxproj 파일은 충돌이 잦지만, .xcconfig 파일은 텍스트 기반이라 병합(merge)이 훨씬 쉽습니다.
  • 재사용성: 공통 설정을 담은 파일을 만들고, 각 환경별 파일에서 이를 가져와(import) 사용하는 등 모듈화된 관리가 가능합니다.

`.xcconfig` 파일 적용 방법

  1. Xcode에서 'File' > 'New' > 'File...'을 선택하고 'Configuration Settings File'을 검색하여 선택합니다.
  2. 먼저 공통 설정을 담을 Shared.xcconfig 파일을 생성합니다.
  3. 같은 방식으로 Development.xcconfigProduction.xcconfig 파일을 생성합니다.
  4. Shared.xcconfig:
    // 모든 환경에 공통으로 적용될 설정
    MARKETING_VERSION = 1.0.0
    CURRENT_PROJECT_VERSION = 1
    ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon
    
  5. Development.xcconfig:
    // Shared.xcconfig 파일을 가져옵니다.
    #include "Shared.xcconfig"
    
    // Development 환경 고유의 설정
    PRODUCT_BUNDLE_IDENTIFIER = com.mycompany.myawesomeapp.dev
    PRODUCT_NAME = MyAwesomeApp (Dev)
    // 다른 커스텀 플래그 등도 추가 가능
    // GCC_PREPROCESSOR_DEFINITIONS[config=Debug-development] = $(inherited) IS_DEV=1
    // GCC_PREPROCESSOR_DEFINITIONS[config=Release-development] = $(inherited) IS_DEV=1
    
  6. Production.xcconfig:
    // Shared.xcconfig 파일을 가져옵니다.
    #include "Shared.xcconfig"
    
    // Production 환경 고유의 설정
    PRODUCT_BUNDLE_IDENTIFIER = com.mycompany.myawesomeapp
    PRODUCT_NAME = MyAwesomeApp
    // GCC_PREPROCESSOR_DEFINITIONS[config=Debug-production] = $(inherited) IS_PROD=1
    // GCC_PREPROCESSOR_DEFINITIONS[config=Release-production] = $(inherited) IS_PROD=1
    
  7. 마지막으로, 이 .xcconfig 파일들을 프로젝트의 빌드 설정과 연결합니다. 'PROJECT' > 'Info' > 'Configurations'로 이동하여 각 설정에 맞는 .xcconfig 파일을 지정해줍니다.
    • Debug-development, Release-developmentDevelopment.xcconfig
    • Debug-production, Release-productionProduction.xcconfig
  8. 이제 Build Settings에서 수정했던 Bundle Identifier, Product Name 등의 값들은 .xcconfig 파일에서 정의한 값으로 덮어씌워집니다. Xcode UI에서는 해당 값들이 볼드체로 표시되며, 마우스를 올리면 어떤 .xcconfig 파일에서 온 설정인지 확인할 수 있습니다.

이처럼 .xcconfig를 도입하면 설정이 코드처럼 관리되어 프로젝트의 확장성과 유지보수성이 크게 향상됩니다.

결론: 안정적이고 자동화된 개발 환경을 향하여

우리는 Xcode의 빌드 설정, 스킴, 그리고 Run Script를 조합하여 여러 개발 환경을 관리하는 체계적인 시스템을 구축했습니다. 이 방법을 통해 얻는 이점은 명확합니다.

  • 휴먼 에러 방지: 더 이상 개발자가 직접 파일을 바꾸거나 설정을 수정할 필요가 없으므로, 실수로 개발용 설정으로 운영 버전을 배포하는 등의 치명적인 사고를 예방할 수 있습니다.
  • 생산성 향상: 스킴 전환 한 번으로 모든 관련 설정(Bundle ID, 앱 이름, 아이콘, 서버 환경 등)이 자동으로 변경되어, 개발자는 환경 전환에 드는 시간과 노력을 아끼고 핵심 로직 개발에만 집중할 수 있습니다.
  • 팀 협업 효율 증대: 프로젝트를 처음 접하는 팀원도 스킴의 의미만 이해하면 복잡한 설정 과정 없이 즉시 원하는 환경에서 개발을 시작할 수 있습니다.
  • 확장성: 'staging', 'qa' 등 새로운 환경이 추가되더라도, 설정과 plist 파일을 추가하고 Run Script의 case 구문에 한 줄을 더하는 것만으로 손쉽게 확장이 가능합니다.

단순히 GoogleService-Info.plist 파일을 교체하는 것을 넘어, 빌드 환경 자동화는 모든 전문 iOS 개발팀이 갖춰야 할 필수적인 역량입니다. 오늘 배운 내용을 당신의 프로젝트에 바로 적용하여, 한 단계 더 성숙하고 안정적인 개발 프로세스를 경험해 보시길 바랍니다.

Wednesday, July 31, 2019

iOS 개발자를 괴롭히는 'A Valid Provisioning Profile...' 오류, 근본 원인부터 해결까지 총정리

iOS 앱 개발 여정에서 Xcode는 가장 강력한 동반자이지만, 때로는 가장 큰 골칫거리가 되기도 합니다. 수많은 개발자들이 개발 막바지 단계나 테스트 과정에서 한 번쯤은 마주쳤을 붉은색 오류 메시지, 'A Valid Provisioning Profile for this Executable was not Found'. 이 메시지는 마치 견고한 성벽처럼 앞을 가로막으며, 특히 iOS 생태계의 복잡한 인증 시스템에 익숙하지 않은 개발자에게는 거대한 좌절감을 안겨줍니다. "분명히 프로비저닝 프로파일을 제대로 설정했는데 왜?" 라는 의문과 함께 구글 검색과 Stack Overflow의 바다를 몇 시간이고 헤매게 만드는 주범이기도 합니다.

문제는 이 오류가 단순히 파일 하나를 잘못 지정해서 발생하는 경우보다, iOS 코드 서명(Code Signing)이라는 거대한 시스템에 대한 이해 부족에서 비롯되는 경우가 많다는 점입니다. 디버그 빌드는 잘 되다가 릴리즈(Release) 빌드로 전환하여 최종 테스트를 하려는 순간, 혹은 다른 팀원에게 테스트용 앱을 전달하려는 순간에 이 오류는 어김없이 나타나 우리를 괴롭힙니다. 이 글은 더 이상 이 오류 메시지 앞에서 시간을 낭비하지 않도록, 오류의 근본적인 원인부터 시작하여 다양한 시나리오에 맞는 명확하고 구체적인 해결책, 그리고 나아가 더욱 견고한 개발 프로세스를 위한 고급 전략까지 총망라하여 제시합니다. 이 글을 끝까지 읽으신다면, 앞으로는 'Valid Provisioning Profile' 오류를 마주했을 때 당황하는 대신, 마치 숙련된 의사가 환자를 진단하듯 체계적으로 원인을 파악하고 해결하는 자신을 발견하게 될 것입니다.

오류의 실체: 당신의 '의도'와 Xcode의 '설정'이 충돌할 때

가장 먼저 이해해야 할 것은 이 오류 메시지가 '틀렸다'가 아니라 '맞지 않다'고 말하고 있다는 점입니다. Xcode는 당신이 현재 실행하려는 작업(Action)에 유효한(Valid) 프로비저닝 프로파일을 찾지 못했다는, 지극히 논리적인 사실을 전달하고 있을 뿐입니다. 문제는 개발자의 '의도'와 Xcode 프로젝트에 설정된 '규칙'이 서로 어긋나는 데 있습니다.

대부분의 경우, 이 오류는 '릴리즈(Release) 빌드 구성(Build Configuration)으로 실제 기기에서 앱을 실행(Run)하려는' 상황에서 발생합니다. 왜 그럴까요? 개발 과정에서 우리는 보통 두 가지 주요 빌드 구성을 사용합니다.

  • Debug Configuration: 이름 그대로 디버깅을 위한 설정입니다. 개발 중인 앱을 시뮬레이터나 개발용으로 등록된 실제 기기에 설치하고, 중단점(Breakpoint)을 설정하고, 변수 값을 확인하는 등 모든 디버깅 기능을 활용할 수 있도록 최적화되어 있습니다. 이 구성은 보통 'Development'용 인증서와 프로비저닝 프로파일을 사용하도록 설정됩니다.
  • Release Configuration: 사용자에게 배포될 최종 버전을 만들기 위한 설정입니다. 코드 최적화 레벨이 높아지고, 디버깅 심볼이 제거되어 앱의 용량이 줄고 실행 속도가 빨라집니다. 이 구성은 기본적으로 App Store에 제출하거나 Ad Hoc 방식으로 배포하기 위한 'Distribution'용 인증서와 프로비저닝 프로파일을 사용하도록 설정됩니다.

바로 여기서 충돌이 발생합니다. 개발자는 'Release' 구성이 실제 배포 환경과 얼마나 유사하게 동작하는지 최종적으로 '테스트(디버깅)'하고 싶어합니다. 그래서 Xcode에서 빌드 스킴(Scheme)을 'Release'로 변경하고 자신의 아이폰에 직접 실행하려고 합니다. 하지만 Xcode는 'Release' 구성의 규칙에 따라 'Distribution'용 프로파일을 찾습니다. 그런데 App Store 배포용 프로파일은 특정 기기에 앱을 설치하고 디버깅하는 것을 허용하지 않습니다. 그 프로파일의 목적은 오직 Apple의 심사를 위해 App Store Connect에 업로드하는 것이기 때문입니다. 따라서 Xcode는 당신의 아이폰에 'Release' 빌드를 설치하고 실행할 권한을 부여하는 유효한 프로파일을 찾지 못하고, 결국 'A Valid Provisioning Profile for this Executable was not Found' 오류를 띄우는 것입니다.

이 핵심적인 충돌을 이해하는 것이 문제 해결의 첫걸음입니다. 이제부터는 이 문제를 근본적으로 해결하기 위해 반드시 알아야 할 iOS 코드 서명 시스템의 구성 요소들을 하나씩 파헤쳐 보겠습니다.

오류 해결의 열쇠, iOS 코드 서명(Code Signing) 시스템 완벽 이해

iOS 코드 서명은 Apple이 사용자의 보안과 개인정보를 보호하고, 신뢰할 수 있는 개발자가 만든 앱만이 기기에서 실행되도록 보장하는 매우 정교하고 강력한 메커니즘입니다. 이 시스템은 여러 구성 요소들이 마치 하나의 교향곡처럼 조화롭게 작동해야 합니다. 이 중 하나라도 엇박자를 내면, 우리는 앞서 본 오류와 같은 불협화음을 듣게 됩니다. 주요 연주자들을 소개합니다.

1. 인증서 (Certificates): "나는 누구인가?"를 증명하는 신분증

인증서는 개발자 또는 개발팀의 신원을 증명하는 디지털 신분증입니다. Apple Developer Program에 등록하면 이 인증서를 생성할 수 있습니다. 인증서는 당신의 Mac 키체인에 저장되며, 당신이 만든 앱이 정말 당신에 의해 서명되었음을 보장하는 역할을 합니다. 주요 인증서는 두 종류입니다.

  • Apple Development Certificate (개발용 인증서): 개발 과정에서 사용됩니다. 이 인증서로 서명된 앱은 개발용으로 등록된 제한된 수의 기기에만 설치하고 디버깅할 수 있습니다. 즉, 'Debug' 빌드 구성과 짝을 이룹니다.
  • Apple Distribution Certificate (배포용 인증서): 개발이 완료된 앱을 사용자에게 전달할 때 사용됩니다. 이 인증서 자체는 다시 두 가지 주요 목적으로 나뉩니다.
    • App Store: App Store에 앱을 제출하기 위해 사용됩니다. 이 인증서로 서명된 앱은 최종적으로 Apple에 의해 다시 서명되어 스토어를 통해 불특정 다수의 사용자에게 배포됩니다.
    • Ad Hoc: App Store를 거치지 않고, 최대 100대의 등록된 기기에 테스트용으로 앱을 배포할 때 사용됩니다. QA팀이나 베타 테스터에게 앱을 전달하는 일반적인 방법입니다.
    • Enterprise: (Apple Developer Enterprise Program 전용) 특정 기업의 직원들에게만 내부적으로 앱을 배포할 때 사용됩니다.

핵심은 개발용 인증서디버깅을 허용하고, 배포용 인증서디버깅을 허용하지 않는다는 점입니다. 이것이 모든 문제의 시작점입니다.

2. 앱 ID (App Identifiers): "내 앱은 무엇인가?"를 정의하는 주민등록번호

앱 ID는 말 그대로 앱의 고유한 식별자입니다. Apple 생태계 내에서 당신의 앱을 다른 모든 앱과 구분하는 역할을 합니다. 보통 'com.companyname.appname'과 같은 역-도메인(reverse-domain) 형식을 사용하며, 프로젝트의 'Bundle Identifier'와 정확히 일치해야 합니다. 앱 ID는 또한 푸시 알림, iCloud, Apple로 로그인, 인앱 결제와 같은 특정 서비스(Capabilities)를 앱에서 사용할 수 있도록 활성화하는 역할도 합니다.

  • Explicit App ID (명시적 앱 ID): `com.mycompany.amazingapp`처럼 하나의 앱에만 정확히 대응되는 ID입니다. 푸시 알림과 같이 특정 앱에 종속적인 서비스를 사용하려면 반드시 명시적 앱 ID를 사용해야 합니다.
  • Wildcard App ID (와일드카드 앱 ID): `com.mycompany.*`처럼 여러 앱에 두루 사용될 수 있는 ID입니다. 간단한 유틸리티 앱처럼 특별한 서비스가 필요 없는 경우에 유용하지만, 대부분의 현대적인 앱은 명시적 앱 ID를 필요로 합니다.

3. 기기 (Devices): "어디서 실행할 것인가?"를 명시하는 허가 목록

개발 및 Ad Hoc 배포 단계에서는 앱을 실행할 모든 기기(iPhone, iPad, Apple Watch 등)의 고유 식별자(UDID)를 Apple Developer 포털에 등록해야 합니다. 이것은 허가되지 않은 기기에서 개발 중인 앱이 무단으로 실행되는 것을 방지하기 위한 보안 조치입니다. 시뮬레이터는 UDID 등록이 필요 없지만, 실제 기기에서 테스트하려면 이 과정이 필수적입니다. App Store 배포 시에는 이 기기 목록이 필요 없습니다. Apple이 모든 사용자의 기기에 앱을 배포할 것이기 때문입니다.

4. 프로비저닝 프로파일 (Provisioning Profiles): 모든 것을 연결하는 '지휘자'

드디어 주인공이 등장했습니다. 프로비저닝 프로파일(`.mobileprovision` 파일)은 위에서 설명한 인증서, 앱 ID, 기기 목록 이 세 가지 요소를 하나로 묶어주는 '접착제'이자 '지휘자'입니다. 이 파일 안에는 다음과 같은 정보가 담겨 있습니다.

"이 앱(앱 ID)은, 이 개발자(인증서)가 만들었으며, 이 기기들(기기 목록)에서 특정 목적(개발/배포)으로 실행될 수 있도록 허가한다."

프로비저닝 프로파일은 그 목적에 따라 여러 종류로 나뉩니다.

  • Development Provisioning Profile (개발용 프로파일):
    • 무엇을 연결하는가? 개발용 인증서 + 앱 ID + 등록된 기기 목록
    • 목적은? 등록된 특정 기기에서 앱을 설치하고 디버깅하는 것.
    • 언제 사용되는가? 주로 Xcode의 'Debug' 빌드 구성에서 사용됩니다.
  • Ad Hoc Provisioning Profile (애드혹 배포용 프로파일):
    • 무엇을 연결하는가? 배포용 인증서 + 앱 ID + 등록된 기기 목록 (최대 100대)
    • 목적은? App Store를 통하지 않고 등록된 특정 기기에 테스트용으로 앱을 '배포'하는 것. 디버깅은 불가능합니다.
    • 언제 사용되는가? QA 테스트, 내부 베타 테스트 시 사용됩니다.
  • App Store Provisioning Profile (앱스토어 배포용 프로파일):
    • 무엇을 연결하는가? 배포용 인증서 + 앱 ID (기기 목록 없음!)
    • 목적은? 오직 App Store Connect에 앱을 업로드하기 위한 것. 이 프로파일로 서명된 빌드는 어떤 기기에도 직접 설치할 수 없습니다.
    • 언제 사용되는가? Xcode의 'Archive' 기능을 통해 최종 배포용 파일을 만들 때 사용됩니다.

이제 그림이 명확해집니다. 'Release' 구성으로 기기에서 직접 실행하려고 할 때, Xcode는 기본적으로 'App Store Provisioning Profile'을 사용하려고 합니다. 하지만 이 프로파일에는 당신의 아이폰 UDID 정보가 없으며, 디버깅 권한도 없습니다. 따라서 Xcode는 "이 실행 파일에 대한 유효한 프로비저닝 프로파일을 찾지 못했습니다"라고 외치는 것이 당연한 결과였던 것입니다.

단계별 해결 가이드: 오류를 잠재우는 실전 처방전

이론적 배경을 충분히 다졌으니, 이제 실전으로 들어갈 시간입니다. 대부분의 개발자가 겪는 상황을 중심으로, 가장 효과적이고 빠른 해결책부터 체계적인 해결책까지 단계별로 안내합니다.

해결책 1: 가장 빠르고 간단한 해결법 (릴리즈 빌드 구성의 서명 설정 변경)

이 방법은 '릴리즈 환경과 유사하게 기기에서 테스트하고 싶다'는 원래의 목적을 가장 간단하게 달성하는 방법입니다. 핵심은 릴리즈(Release) 빌드 구성에서도 디버깅이 가능한 '개발용(Development)' 프로비저닝 프로파일을 사용하도록 임시로 또는 영구적으로 지정하는 것입니다.

  1. 프로젝트 설정 열기: Xcode의 왼쪽 프로젝트 네비게이터에서 프로젝트 파일(파란색 아이콘)을 클릭합니다. 중앙 에디터 영역에 프로젝트와 타겟(Targets) 목록이 나타납니다.
  2. 타겟(Target) 선택: TARGETS 목록에서 당신의 앱 타겟을 선택합니다.
  3. Signing & Capabilities 탭 확인: 상단 탭에서 'Signing & Capabilities'를 선택합니다. 'Automatically manage signing'이 체크되어 있다면 Xcode가 많은 것을 자동으로 처리해주지만, 문제가 발생했을 때는 수동으로 제어하는 것이 원인 파악에 더 좋습니다. (만약 이 기능으로 문제가 계속된다면 잠시 체크를 해제하고 수동으로 설정하는 것을 권장합니다.)
  4. Build Settings 탭으로 이동: 이제 핵심 단계입니다. 상단 탭에서 'Build Settings'를 선택합니다. 이 곳에는 빌드와 관련된 수백 가지의 설정이 있습니다.
  5. 'Code Signing' 검색: 우측 상단의 검색창에 `Code Signing Identity`라고 입력하여 관련 설정만 필터링합니다.
  6. 릴리즈(Release) 설정 변경:
    • Code Signing Identity > Release: 이 항목을 펼쳐보면 'Any iOS SDK'라는 하위 항목이 보일 것입니다. 기본값은 아마 'Apple Distribution' 또는 'iOS Distribution'으로 되어 있을 것입니다. 이것이 문제의 원인입니다. 이 값을 클릭하고 목록에서 'Apple Development' 또는 'iOS Developer'로 변경합니다.

    • Code Signing Identity 설정 변경 (설명 이미지: Code Signing Identity의 Release 항목을 Apple Development로 변경하는 스크린샷)
  7. 'Provisioning Profile' 검색 및 변경:
    • 이제 검색창에 `Provisioning Profile`을 입력하여 관련 설정을 필터링합니다.
    • Provisioning Profile > Release: 이 항목의 값 역시 'Automatic'으로 되어 있거나 특정 배포용 프로파일이 지정되어 있을 수 있습니다. 이 값을 클릭하고, 당신의 앱 ID와 연결된 'Development'용 프로비저닝 프로파일을 명시적으로 선택해줍니다. (예: `iOS Team Provisioning Profile: com.mycompany.amazingapp`)

    • Provisioning Profile 설정 변경 (설명 이미지: Provisioning Profile의 Release 항목을 개발용 프로파일로 변경하는 스크린샷)
  8. 정리 및 재시도:
    • 메뉴 바에서 Product > Clean Build Folder (단축키: ⇧⌘K)를 실행하여 이전 빌드 아티팩트를 깨끗하게 정리합니다.
    • 이제 Xcode 상단의 빌드 스킴(Scheme)을 'Release'로 설정하고, 타겟 디바이스를 당신의 실제 아이폰으로 선택한 뒤 실행(Run, ⌘R) 버튼을 누릅니다.

이제 마법처럼 앱이 기기에 설치되고 실행될 것입니다. 왜냐하면 우리는 Xcode에게 "비록 'Release' 구성이지만, 지금은 'Development'용 서명과 프로파일을 사용해서 디버깅이 가능하도록 빌드해줘!" 라고 명확하게 지시했기 때문입니다.

해결책 2: 더 체계적이고 전문적인 접근법 (새로운 빌드 구성 추가)

해결책 1은 빠르고 효과적이지만, 원래의 'Release' 설정을 직접 수정하기 때문에 혼란을 야기할 수 있습니다. 특히 팀 단위로 작업하거나, CI/CD(지속적 통합/배포) 시스템을 사용할 경우, 원래의 'Release' 구성은 순수하게 배포용으로 남겨두는 것이 좋습니다. 이를 위한 더 전문적인 방법은 '릴리즈 테스트용' 빌드 구성을 새로 만드는 것입니다.

  1. 빌드 구성 복제:
    • 프로젝트 설정 > 'Info' 탭으로 갑니다.
    • 'Configurations' 섹션 아래에 'Debug'와 'Release'가 보일 것입니다.
    • 하단의 '+' 버튼을 누르고 'Duplicate "Release" Configuration'을 선택합니다.
    • 새로 생성된 'Release Copy'의 이름을 'Staging' 또는 'Release-Debug'와 같이 명확한 이름으로 변경합니다.
  2. 새로운 빌드 구성에 서명 설정 적용:
    • 'Build Settings' 탭으로 돌아갑니다.
    • 이제 'Code Signing Identity'와 'Provisioning Profile' 설정에 방금 만든 'Staging' (또는 'Release-Debug') 항목이 추가된 것을 볼 수 있습니다.
    • 이 새로운 구성에 대해서만, 'Code Signing Identity'를 'Apple Development'로, 'Provisioning Profile'을 개발용 프로파일로 설정합니다. (해결책 1의 6, 7번 단계와 동일)
  3. 빌드 스킴(Scheme) 수정:
    • Xcode 상단의 스킴 편집 메뉴로 이동합니다. (Product > Scheme > Edit Scheme...)
    • 왼쪽 목록에서 'Run' 액션을 선택합니다.
    • 오른쪽 'Info' 탭에서 'Build Configuration' 드롭다운 메뉴를 클릭하고, 방금 만든 'Staging' (또는 'Release-Debug')을 선택합니다.

이 방법을 사용하면, 평소에 ⌘R (Run)을 누를 때는 최적화 레벨은 릴리즈와 같지만 서명은 개발용인 'Staging' 구성으로 빌드되어 기기 테스트가 가능해집니다. 그리고 실제 배포를 위해 'Archive'를 할 때는 원래의 순수한 'Release' 구성이 사용되므로, 각 목적에 맞는 설정을 명확하게 분리하여 관리할 수 있습니다. 이는 장기적으로 훨씬 안전하고 확장성 있는 방법입니다.

해결책 3: 그 외 일반적인 문제 해결 체크리스트

위의 방법으로도 해결되지 않는다면, 코드 서명 시스템의 다른 부분에 문제가 있을 수 있습니다. 다음 항목들을 순서대로 점검해보세요.

  • 번들 ID 일치 확인: Xcode 프로젝트의 'Target' > 'General' 탭에 있는 'Bundle Identifier'가 Apple Developer 포털에 등록된 'App ID'와 정확히 일치하는지 다시 한 번 확인하세요. 오타 하나만 있어도 프로파일은 유효하지 않게 됩니다.
  • 인증서 및 프로파일 만료 여부 확인:
    • Apple Developer 포털: 'Certificates, Identifiers & Profiles' 섹션으로 이동하여 사용하려는 인증서와 프로비저닝 프로파일이 만료되지 않았는지(Active 상태인지) 확인하세요. 만료되었다면 새로 갱신해야 합니다.
    • Mac 키체인 접근(Keychain Access) 앱: '로그인' 키체인과 '시스템' 키체인 양쪽 모두에서 만료되거나 중복된 개발/배포 인증서가 있는지 확인하고, 있다면 삭제하세요. 오래된 인증서가 충돌을 일으키는 경우가 많습니다.
  • 기기 UDID 등록 확인: 테스트하려는 기기의 UDID가 사용하려는 'Development' 또는 'Ad Hoc' 프로비저닝 프로파일에 포함되어 있는지 확인하세요. 새로운 기기를 추가했다면, 프로파일을 다시 생성(Regenerate)하고 다운로드하여 Xcode에 다시 설치해야 합니다.
  • Xcode 캐시 청소: Xcode는 때때로 오래된 설정이나 캐시를 붙들고 문제를 일으킵니다.
    • Clean Build Folder: ⇧⌘K
    • Derived Data 삭제: Xcode 메뉴 > Settings (또는 Preferences) > Locations 탭으로 가서 Derived Data 경로 옆의 화살표를 클릭하여 Finder에서 엽니다. Xcode를 종료한 뒤, 해당 폴더 안의 모든 내용을 삭제하세요. 다음에 프로젝트를 열 때 Xcode가 모든 것을 새로 생성합니다.
  • 재시작의 마법: 위의 모든 방법이 통하지 않을 때 시도해볼 최후의 수단입니다. Xcode를 완전히 종료했다가 다시 실행하거나, 심지어 Mac을 재시작하는 것만으로도 꼬여있던 문제가 해결되는 경우가 드물지 않게 있습니다.

전문가를 위한 팁: 코드 서명 관리 자동화와 고급 전략

매번 Xcode의 GUI를 클릭하며 설정을 바꾸는 것은 번거롭고 실수를 유발할 수 있습니다. 더 큰 규모의 프로젝트나 팀에서는 코드 서명 관리를 자동화하는 것이 필수적입니다.

1. `xcconfig` 파일 활용하기

`.xcconfig` 파일은 빌드 설정을 텍스트 파일로 분리하여 관리할 수 있게 해주는 강력한 기능입니다. 각 빌드 구성(Debug, Staging, Release)에 대한 별도의 `xcconfig` 파일을 만들고, 코드 서명 관련 설정을 파일 안에 명시적으로 정의할 수 있습니다.

예를 들어, `Staging.xcconfig` 파일에 다음과 같이 작성할 수 있습니다.


// Staging.xcconfig

#include "Pods/Target Support Files/Pods-AmazingApp/Pods-AmazingApp.staging.xcconfig"

// Code Signing
CODE_SIGN_STYLE = Manual
CODE_SIGN_IDENTITY = Apple Development
PROVISIONING_PROFILE_SPECIFIER = MyStagingProfileName
DEVELOPMENT_TEAM = YOUR_TEAM_ID

이렇게 하면 Git과 같은 버전 관리 시스템을 통해 코드 서명 설정을 팀원들과 공유하고 변경 이력을 추적하기가 매우 용이해집니다.

2. Fastlane Match 사용하기

Fastlane은 iOS 및 Android 개발의 빌드, 테스트, 배포 과정을 자동화해주는 최고의 도구 모음입니다. 그 중 'Match'는 코드 서명 문제를 해결하는 데 특화된 기능입니다.

Match는 팀의 모든 인증서와 프로비저닝 프로파일을 비공개 Git 저장소에 중앙 집중식으로 저장하고 관리합니다. 새로운 팀원이 합류하거나 새로운 Mac에서 개발 환경을 설정할 때, 단 한 줄의 명령어(`fastlane match development`)만 실행하면 필요한 모든 서명 자산을 자동으로 다운로드하고 설치해줍니다. 이를 통해 "내 컴퓨터에서는 되는데, 네 컴퓨터에서는 왜 안돼?"와 같은 고질적인 문제를 원천적으로 차단할 수 있습니다.

결론: 오류 메시지는 적이 아니라 길잡이다

'A Valid Provisioning Profile for this Executable was not Found'라는 오류 메시지는 더 이상 두려움의 대상이 아닙니다. 이 오류는 우리에게 iOS 코드 서명 시스템이 어떻게 작동하는지, 그리고 현재 우리의 설정이 어떤 부분에서 그 규칙과 어긋나 있는지를 알려주는 친절한 길잡이입니다.

핵심을 다시 한 번 요약하자면, 이 문제는 대부분 '배포(Distribution)'를 목적으로 하는 프로파일을 가지고 '개발(Development)' 단계에서나 가능한 기기 테스트/디버깅을 시도했기 때문에 발생합니다. 따라서 해결책은 명확합니다. 릴리즈 설정을 테스트할 때는, 해당 구성의 코드 서명 주체를 '디버깅이 가능한 개발용 프로파일'로 지정해주면 됩니다.

단순히 문제를 해결하는 것을 넘어, 이 기회에 인증서, 앱 ID, 프로비저닝 프로파일의 역할과 상호 관계를 명확히 이해한다면, 앞으로 마주할 더 복잡한 배포 시나리오에서도 자신감을 가질 수 있을 것입니다. 이제는 오류 앞에서 좌절하는 대신, 차분히 원인을 분석하고 올바른 처방을 내리는 숙련된 iOS 개발자로 한 단계 더 성장할 시간입니다.