iOS 배포(Signing) 단계에서 갑자기 Provisioning profile doesn’t include … 또는 Code signing is required for product type 같은 메시지가 뜨면, 인증서/프로비저닝만 의심하기 쉽습니다. 그런데 Cordova에서는 플러그인이 추가한 Entitlements(권한) 때문에 프로비저닝과 실제 앱 서명이 서로 안 맞는 경우가 꽤 많습니다.

Signing mismatch metaphor with certificate tag and locked envelope

로그에서 “누가 어떤 Entitlement를 요구했는지”부터 잡아내면, 불필요한 재발급을 줄일 수 있어요.

1) 빌드 로그에서 먼저 확인할 핵심 에러 패턴

아래는 Signing/Entitlements 충돌에서 자주 보이는 로그 형태입니다. 한 줄만 보지 말고, 그 주변(바로 위/아래)에서 어떤 capability/entitlement 키를 말하는지 찾는 게 핵심입니다.

  • Provisioning profile "..." doesn't include the ... entitlement (예: aps-environment, com.apple.developer.associated-domains 등)
  • Code Signing Error: ... requires a provisioning profile with the ... feature
  • Signing for "..." requires a development team (팀 설정이 바뀌었거나, 서명 대상이 늘어난 경우)
  • Entitlements file "..." was modified during the build (빌드 단계에서 entitlements가 덮어써지는 경우)
  • No profiles for '...' were found (번들 ID/팀/프로파일 매칭 실패지만, 근본 원인이 번들 ID 변경 또는 플러그인으로 타깃이 추가된 경우도 있음)

팁: Xcode에서 Archive 실패 시 Report navigator에서 해당 실패 구간을 펼쳐보면, entitlement 키가 더 명확히 보일 때가 많습니다.

2) 흔한 원인: 플러그인이 Entitlements를 “추가”했는데 프로필이 못 따라오는 경우

Cordova 플러그인은 plugin.xml 훅으로 Xcode 프로젝트 설정(Capabilities/Entitlements/Info.plist)을 건드립니다. 릴리즈 아카이브 시점에 아래 케이스가 겹치면 “어제까지 되던 Signing이 오늘 깨지는” 느낌이 납니다.

  • Push 관련(aps-environment): 푸시 플러그인/SDK가 aps-environment entitlement를 요구하지만, 현재 프로비저닝이 Push capability를 포함하지 않음
  • Associated Domains: universal links/앱링크 플러그인이 associated-domains를 넣었는데, 프로비저닝 또는 App ID에 capability가 활성화되지 않음
  • Sign In with Apple: 관련 플러그인 도입 후 capability가 켜져야 하는데 팀/번들 설정이 그대로임
  • Keychain Sharing/App Groups: 어떤 SDK(로그인/인증/공유/보안)가 그룹 entitlement를 넣어버려서, 프로필에 없는 그룹이 요구됨
  • Notification Service Extension 등 타깃 추가: 플러그인이 extension 타깃을 만들거나 빌드 설정을 추가했는데, 해당 타깃까지 서명 설정이 일관되지 않음

Abstract build log panel with warning markers and arrows

정리하면, “증상은 프로비저닝 에러”지만 “원인은 플러그인의 entitlement 요구”인 흐름이 많습니다.

3) 빠른 좁히기: 어떤 Entitlements가 실제로 들어갔는지 확인

해결의 출발점은 “현재 빌드 산출물(또는 프로젝트 설정)에 어떤 Entitlements가 들어갔는지”를 확인하는 겁니다. 확인해야 할 대상은 크게 3군데입니다.

  • 앱 타깃의 Signing & Capabilities: Xcode에서 실제로 어떤 capability가 켜져 있는지
  • 생성/적용되는 .entitlements 파일: 프로젝트에 파일이 생겼거나, 빌드 과정에서 자동 생성되는지
  • Cordova 플러그인 훅: plugin.xml 또는 설치 스크립트가 entitlement를 추가했는지

실무 팁: 최근에 추가/업데이트한 플러그인이 있다면, 그 플러그인이 “iOS capability를 요구하는 기능(Push, Universal Links, Keychain, App Groups 등)”을 포함하는지부터 의심해보는 게 빠릅니다.

4) 해결 단계(권장 순서): 플러그인 요구사항 → Apple Developer 설정 → Xcode 서명 정리

아래 순서로 진행하면 불필요한 재시도(클린/재설치/재발급)를 줄일 수 있습니다.

  • 1) 로그에서 entitlement 키를 1개로 특정: “profile doesn’t include …” 뒤에 붙은 키/기능명을 적어둡니다.
  • 2) 그 entitlement를 누가 요구하는지 찾기: 최근 변경 플러그인, 해당 기능(Push/Associated Domains/App Groups 등)과 연결되는 플러그인부터 확인합니다.
  • 3) Apple Developer의 App ID(Identifier)에서 capability 활성화: 해당 번들 ID(App ID)에 기능이 켜져 있어야 프로비저닝에 반영됩니다.
  • 4) 프로비저닝 프로파일 재생성/재다운로드: capability 변경은 기존 프로파일에 자동 반영되지 않는 경우가 많아, 새로 만들거나 갱신이 안전합니다.
  • 5) Xcode에서 Team/Signing 일관성 맞추기: 앱 타깃(및 extension 타깃이 있다면 그것까지) 모두 동일 Team과 올바른 프로파일로 맞춥니다.
  • 6) Cordova iOS 플랫폼 정리 후 재빌드: plugin hook이 설정을 다시 주입하므로, 필요하면 platform 재추가/재설치로 설정이 일관되게 적용되게 합니다.

중요: capability를 켰는데도 계속 실패한다면, “프로파일 문제”라기보다 entitlements가 중복/상충해서 빌드 단계에서 다른 파일로 덮어쓰는지(“modified during the build”)를 같이 봐야 합니다.

5) 플러그인 충돌 패턴 3가지: 중복 Entitlements, 타깃 분리, Debug/Release 불일치

권한 이슈가 “한 번만 고치면 끝”이 아닌 이유는, 플러그인들이 각자 방식으로 프로젝트를 건드리기 때문입니다. 아래 3가지는 특히 많이 만납니다.

  • 중복/경합: A 플러그인과 B 플러그인이 각각 entitlements를 생성/수정하면서 서로 덮어씀(빌드 시점마다 결과가 달라지기도 함)
  • 타깃 분리 누락: extension 타깃이 생겼는데, 그 타깃만 Signing이 비어있거나 다른 Team을 바라봄
  • Debug/Release 불일치: Debug에서는 자동 서명으로 돌아가는데, Archive(Release)에서만 수동/다른 프로파일을 쓰게 되어 충돌이 폭발

Capabilities toggles connected to an app tile and shields

이럴 때는 “지금은 어떻게든 아카이브만 성공”보다, 어떤 플러그인이 어떤 설정을 넣는지(install hook 포함) 한 번 정리해두는 게 다음 배포 때 훨씬 편합니다.

6) 배포 전 체크리스트(재발 방지용)

  • 최근 추가/업데이트 플러그인이 Push/Universal Links/App Groups/Keychain 등 capability를 요구하는지 확인
  • Apple Developer App ID에서 필요한 capability가 실제로 ON인지 확인
  • 프로비저닝 프로파일을 capability 변경 이후 새로 생성/갱신했는지 확인
  • Xcode 모든 타깃(앱 + extension 등)에 Team/Signing 설정이 일관적인지 확인
  • Release(Archive) 기준으로 빌드/서명 설정을 점검했는지 확인(Debug 성공만 믿지 않기)
  • Entitlements가 빌드 중 수정된다는 로그가 있으면, 플러그인 훅/스크립트에서 덮어쓰는 지점을 우선 의심

마무리

Signing 에러가 뜨면 인증서와 프로비저닝부터 만지게 되지만, Cordova에서는 플러그인이 추가한 Entitlements가 “진짜 원인”인 경우가 많습니다. 로그에서 entitlement 키를 특정하고, 그 기능을 요구한 플러그인을 찾는 순서로 가면 해결이 빨라집니다.

특히 Archive(Release)에서만 터지는 문제는 Debug와 설정이 달라서 생기는 경우가 많으니, 배포 직전엔 Release 기준으로 한 번 더 점검해두는 걸 추천합니다.