# ITMS-90034 오류 해결: Missing or invalid signature

> ITMS-90034는 빌드가 유효한 배포 인증서로 서명되지 않았다는 뜻이에요. codesign으로 서명을 확인하고 EAS로 스토어 빌드를 다시 만드세요.

원본 페이지: [ITMS-90034 오류 해결: Missing or invalid signature](https://devoria.fr/ko/blog/itms-90034-missing-invalid-signature-fix)
작성자: [Mehdi Azizi](https://devoria.fr/ko/mehdi-azizi)
게시일: 2026-11-04
최종 내용 수정: 2026-11-04


ITMS-90034는 빌드를 App Store Connect로 보낼 때 나타나요. 앱이나 앱 구성 요소 중 하나가 Apple 제출 인증서, 즉 유효한 배포 인증서로 서명되지 않았다는 뜻이에요. **해결 방법은 어느 번들이 왜 잘못 서명됐는지 찾은 다음, App Store용으로 서명된 빌드를 다시 만드는 거예요.**

이 글은 오류 자체에만 집중해요. 인증서와 프로파일이라는 말이 아직 낯설다면 먼저 [iOS 개발자 인증서와 provisioning profile](https://devoria.fr/ko/blog/ios-certificate-provisioning-profile-expo)을 읽어 보세요. 여기서는 읽어야 할 메시지, 판단 트리, IPA를 검사하는 명령어, EAS가 관리하는 자격 증명으로 고치는 방법을 다뤄요. EAS 부분은 인증서를 고르는 EAS CLI 24.10.0 코드를 직접 읽고 썼어요.

## ITMS-90034 오류는 무슨 뜻인가요?

전형적인 형태는 이래요. 이름은 예시예요.

> ITMS-90034: Missing or invalid signature. The bundle 'com.example.myapp' at bundle path 'Payload/MyApp.app' is not signed using an Apple submission certificate.

2026년 Apple 포럼에서는 "Validation failed (409) Missing or invalid signature" 형태로도 나오고, 그 뒤에 같은 문구와 "(ID: 90034)"가 붙어요.

"제출 인증서"는 배포 인증서를 말해요. [인증서에 대한 Apple 도움말](https://developer.apple.com/help/account/certificates/certificates-overview)에 따르면 개발 인증서는 내 기기에서 앱을 실행할 때 쓰고, 배포 인증서는 앱을 배포하거나 App Store Connect로 보낼 때 써요.

**메시지에 나온 경로를 읽으세요. 그게 문제 있는 번들이에요.** `Payload/MyApp.app`은 앱 자체를 가리켜요. `.appex`로 끝나는 경로는 위젯 같은 익스텐션을 가리키고, `.framework`로 끝나면 포함된 라이브러리를 가리켜요.

리뷰어의 리젝이 아니에요. 검증은 업로드할 때나 빌드 처리 중에, TestFlight 전에 실패해요. 이 빌드는 테스터에게 절대 도달하지 못해요.

## 판단 트리: 메시지에서 해결까지

각 행은 메시지, 다음 섹션의 명령어, 또는 EAS 로그에서 읽을 수 있는 단서예요. 순서대로 확인하세요. 처음 일치하는 행이 원인이에요.

| 보이는 것                 | 예상 원인          | 해결                |
| ------------------------- | ------------------ | ------------------- |
| `.appex`로 끝나는 경로    | 익스텐션 서명 오류 | 익스텐션 선언       |
| `Signature=adhoc`         | 서명되지 않은 빌드 | store 프로필로 빌드 |
| `Apple Development`       | 개발 빌드          | store 프로필로 빌드 |
| `ProvisionedDevices` 있음 | 내부 빌드(ad hoc)  | store 프로필로 빌드 |
| `sealed resource`         | 빌드 후 수정된 IPA | 빌드 다시 만들기    |
| EAS: "no longer valid"    | 폐기된 인증서      | 새 인증서           |
| 모두 유효함               | Apple 측 문제      | 재전송 후 신고      |

## 명령어 네 개로 IPA 검사하기

expo.dev의 빌드 페이지에서 IPA를 내려받고, Mac에서 터미널을 여세요.

**1. 누가 앱에 서명했나요?**

```bash
unzip -q MyApp.ipa -d ipa
codesign -dv --verbose=4 ipa/Payload/*.app 2>&1 | grep -E "^(Identifier|Authority|Signature|TeamIdentifier)="
```

`codesign`은 표준 에러로 출력하기 때문에 `2>&1`이 필요해요. [Apple 기술 노트 TN3161](https://developer.apple.com/documentation/technotes/tn3161-inside-code-signing-certificates)에 따르면 `Authority` 줄 하나하나가 신뢰 체인의 고리예요. 첫 줄은 `Apple Distribution:` 또는 `iPhone Distribution:`으로 시작하고 그 뒤에 팀 이름이 와야 해요. 두 번째 라벨은 예전 iOS Distribution 유형이에요. 코드를 보면 EAS CLI 24.10.0은 아직 이 유형의 인증서를 만들어요. `Apple Development:`가 보이면 개발 빌드예요. `Authority` 줄 없이 `Signature=adhoc`만 보이면 바이너리가 어떤 인증서로도 서명되지 않은 거예요.

**2. 서명 후에 앱이 수정됐나요?**

```bash
codesign --verify --deep --strict -vv ipa/Payload/*.app
```

`valid on disk`, 그다음 `satisfies its Designated Requirement`가 나와야 해요. TN3161은 이 검사가 보장하는 것을 설명해요. 예상한 파일이 모두 있고, 추가된 파일도 수정된 파일도 없다는 거예요. 제가 서명한 뒤 손댄 테스트 번들에서는 `a sealed resource is missing or invalid`, 이어서 `file modified:`와 바뀐 파일이 나왔어요. 여기서 `--deep` 옵션은 검증용일 뿐, 서명에는 절대 쓰지 마세요. Apple 포럼에서 지원팀 엔지니어도 서명에 쓰지 말라고 권해요.

**3. 어떤 프로파일이 들어 있나요?**

```bash
security cms -D -i ipa/Payload/*.app/embedded.mobileprovision -o profile.plist
plutil -extract ProvisionedDevices xml1 -o - profile.plist
plutil -extract ExpirationDate raw profile.plist
```

[프로파일에 관한 TN3125 노트](https://developer.apple.com/documentation/technotes/tn3125-inside-code-signing-provisioning-profiles)에 나오는 명령어예요. App Store 프로파일에는 기기 목록이 없어요. 그래서 두 번째 줄은 `Could not extract value`를 출력해야 해요. 기기 식별자가 보이면 ad hoc 프로파일, 즉 내부 빌드용이에요. 세 번째 줄은 프로파일 만료일을 보여 줘요.

**4. 익스텐션과 프레임워크도 똑같이 서명됐나요?**

```bash
find ipa/Payload/*.app \( -name "*.appex" -o -name "*.framework" \) \
  -exec sh -c 'echo "$1"; codesign -dvv "$1" 2>&1 | grep -m1 "^Authority="' _ {} \;
```

모든 구성 요소가 앱과 같은 `Authority` 줄을 보여야 해요. 다른 게 하나 있다면, 메시지가 가리키는 게 바로 그거예요.

업로드 전에 확인하고 싶다면 TN3161은 `altool`을 권해요. Xcode의 Validate App 버튼과 같은 검사예요. App Store Connect API 키가 필요하고, `AuthKey_<KEY_ID>.p8` 파일은 `~/.appstoreconnect/private_keys`에 두면 돼요.

```bash
xcrun altool --validate-app -f MyApp.ipa -t ios --api-key <KEY_ID> --api-issuer <ISSUER_ID>
```

## EAS로 원인별로 고치기

### 내부 빌드나 개발 빌드를 Apple에 보낸 경우

[eas.json에 관한 Expo 문서](https://docs.expo.dev/build/eas-json/)에 따르면 `"distribution": "internal"` 빌드는 스토어용으로 서명되지 않고 ad hoc 프로파일을 써요. 기본값인 `store` 배포 프로필만 업로드 가능한 빌드를 만들어요. **가장 안전한 방법은 직접 고르지 말고 방금 만든 빌드를 그대로 보내는 거예요.**

```bash
eas build --platform ios --profile production --auto-submit
```

`eas submit --path`를 쓴다면 그 파일이 정말 최신 store 빌드인지 확인하세요. Apple 포럼에서 한 팀은 업로드 도구가 git에 커밋된 예전 IPA를 매번 보내고 있었다는 걸 알게 됐어요.

### 익스텐션을 빠뜨린 경우

익스텐션은 각각 별도의 번들이고, 자기 식별자와 자기 프로파일이 있어요. 네이티브 코드를 생성하는 Expo 프로젝트라면 [iOS 익스텐션에 관한 Expo 문서](https://docs.expo.dev/build-reference/app-extensions/)대로 `extra.eas.build.experimental.ios.appExtensions`에 선언해야 해요. 그러면 EAS CLI가 빌드 전에 익스텐션을 알고, 자격 증명을 만들거나 검증해요. 익스텐션을 추가하는 라이브러리 대부분은 플러그인으로 이 선언을 대신 써 줘요.

미니게임 알람 앱인 Solys에는 익스텐션이 네 개 있어요. 위젯 하나와 스크린 타임 익스텐션 세 개예요. 네 개 모두 설정에 선언돼 있고, EAS가 각각의 프로파일을 갖고 있어요. **이 선언 없이 Xcode에서 손으로 추가한 익스텐션은** 메시지에 `.appex` 경로가 나올 때 **가장 유력한 범인이에요.**

### 인증서가 폐기됐거나 만료된 경우

[인증서에 관한 Apple 페이지](https://developer.apple.com/support/certificates/)는 분명하게 말해요. 만료되거나 폐기된 인증서로 서명된 빌드는 더 이상 업로드할 수 없어요. 이미 업로드했지만 아직 제출하지 않은 빌드도 인증서가 폐기되면 Invalid Binary 상태가 될 수 있어요.

EAS CLI 24.10.0 코드를 보면 이 문제가 언제 눈에 띄지 않고 넘어가는지 알 수 있어요.

- **Apple에 로그인한 대화형 빌드**: EAS가 인증서를 Apple에 아직 유효한 인증서들과 비교해요. 없으면 "Current distribution certificate is no longer valid in Apple Dev Portal"을 표시하고 인증서를 고르거나 새로 만들게 해요.
- **로그인하지 않은 대화형 빌드**: EAS는 날짜만 확인하고 Apple 쪽 검증을 건너뛴다고 알려요.
- **CI에서 돌리는 비대화형 빌드**: EAS는 "Distribution Certificate is not validated for non-interactive builds"를 표시하고 그대로 서명해요.

**CI에서는 EAS가 인증서 자체를 다시 확인하지 않아요. 그래서 폐기 사실이 업로드할 때에야 드러날 수 있어요.** 해결 방법은 Apple 계정에 로그인한 대화형 빌드를 돌리거나, `eas credentials --platform ios`에서 Build Credentials 메뉴로 가서 "Distribution Certificate: Add a new one to your account"를 고르는 거예요. 예전 인증서가 들어 있던 프로파일은 무효가 돼요. EAS가 다음 빌드 때 확인하고 다시 만들어요. 인증서 개수에 대한 Apple의 제한은 [iOS 개발자 인증서 가이드](https://devoria.fr/ko/blog/ios-certificate-provisioning-profile-expo)에 자세히 있어요.

### 서명 후 바이너리를 수정한 경우

[Apple 기술 노트 TN3126](https://developer.apple.com/documentation/technotes/tn3126-inside-code-signing-hashes)에서 설명하듯, 서명은 코드, 리소스, 메타데이터를 해시로 봉인해요. IPA 압축을 풀어 파일을 바꾸고 다시 압축하면 이 봉인이 깨져요. **수정은 설정에서 하고 빌드를 다시 만드세요.** EAS가 만든 IPA에는 절대 손대지 마세요.

`.zip` 압축 파일 안처럼 엉뚱한 위치에 둔 코드도 마찬가지예요. App Store가 다시 서명할 수 없어요. 허용되는 위치는 Apple의 [번들 콘텐츠](https://developer.apple.com/documentation/bundleresources/placing-content-in-a-bundle) 페이지에 나와 있어요.

### 로컬 자격 증명을 쓰는 경우

EAS 프로필이 `"credentialsSource": "local"`을 쓴다면 `credentials.json` 파일이 `.p12` 인증서와 `.mobileprovision` 프로파일을 가리켜요. 3단계 명령어로 프로파일을 확인하세요. App Store 유형이어야 하고, 현재 배포 인증서가 들어 있어야 해요. 그리고 이 파일들은 [Expo 앱의 API 키](https://devoria.fr/ko/blog/expo-app-secret-api-key-security)처럼 저장소 밖에 두세요.

### 모두 유효한 경우

답답한 경우가 하나 남아요. Apple 포럼에서는 아무것도 바꾸지 않고 같은 빌드를 다시 보냈더니 오류가 사라졌다는 개발자들이 있어요. 2026년 8월과 9월에는 반대 사례를 다룬 스레드가 두 개 있었어요. 인증서와 프로파일을 새로 만들고 서명도 확인했는데 계속 실패했다는 거예요. 그중 한 스레드에서 Apple 엔지니어는 IPA, 서명 분석 결과, Transporter 로그를 첨부해 버그 리포트를 보내고 App Store Connect에 문의하라고 권했어요.

그러니 새 빌드 번호로 한 번 다시 보내 보세요. 네 가지 명령어 결과가 깨끗한데도 오류가 다시 나오면 이 자료를 첨부해 Apple에 신고하세요. **반사적으로 인증서를 폐기하지 마세요.** 더 해결되는 건 없고 프로파일만 무효가 돼요.

## 낭패 없이 빌드 보내기

서명은 업로드 전에 2분이면 확인할 수 있어요. 다른 자동 검사도 똑같이 꼼꼼하게 챙겨야 해요. Xcode 버전에 관한 [ITMS-90725](https://devoria.fr/ko/blog/itms-90725-sdk-version-issue-expo), 권한 설명 문구에 관한 [ITMS-90683](https://devoria.fr/ko/blog/itms-90683-missing-purpose-string-expo)이 그래요. Mac 없이 빌드부터 업로드까지 하는 전체 과정은 [Mac 없이 iOS 앱 출시하기](https://devoria.fr/ko/blog/publish-ios-app-without-mac-expo-eas)에 있어요.

리뷰어의 리젝은 좀 더 한 발 물러서서 봐야 해요. 대응 방법은 [Apple에 앱이 리젝됐을 때](https://devoria.fr/ko/expertise/app-rejected-by-apple) 페이지에, 가장 흔한 사유는 [Apple이 앱을 리젝하는 이유](https://devoria.fr/ko/blog/app-store-rejection-reasons-real-cases)에 정리해 뒀어요.

업로드 전에 준비 상태를 점검하고 싶다면 [Review Kit](https://devoria.fr/ko/kits/app-review)에 제 체크리스트와 프로젝트를 검토해 주는 Claude Code 스킬을 모아 뒀어요. 업로드가 막혀서 사람의 눈이 필요하다면 [저와 한 시간 예약하세요](https://devoria.fr/ko/coaching). 화상으로 화면을 보면서 프로젝트를 함께 살펴봐요. 첫 출시를 준비 중이라면 [무료 진단을 받아 보세요](https://devoria.fr/ko/diagnostic). 단계를 순서대로 정리해 주고 Apple 리젝 방지 체크리스트도 보내 드려요.

## 자주 묻는 질문

### ITMS-90034는 App Review 리젝인가요?

아니요. 빌드를 보낼 때, TestFlight와 모든 심사 전에 이뤄지는 자동 검증이에요. 아무도 앱을 열어 보지 않았어요. Apple은 서명이 유효한 배포 인증서에서 온 게 아니라는 것만 확인했어요.

### ITMS-90034를 고치려면 배포 인증서를 폐기해야 하나요?

인증서가 유출됐거나 이미 무효인 경우에만요. 잘 작동하는 인증서를 폐기하면 원인은 그대로인 채 프로파일만 무효가 돼요. 먼저 `codesign`으로 IPA 서명을 읽고, 판단 트리가 가리키는 문제를 고치세요.

### 원격 업데이트로 ITMS-90034를 고칠 수 있나요?

아니요. 서명은 바이너리의 일부이고, 거부된 빌드는 절대 쓸 수 없어요. 제대로 서명된 새 바이너리를 만들어 다시 보내야 해요.

### 왜 오류가 앱이 아니라 위젯을 가리키나요?

위젯은 자기 프로파일로 서명되는 별도의 번들이기 때문이에요. EAS에 선언되지 않았거나 다른 방식으로 서명됐다면 업로드 전체가 실패해요. 설정에 익스텐션을 선언하고 빌드를 다시 만드세요.

### codesign이 모두 유효하다고 하면 어떻게 하나요?

포함된 프로파일과 각 익스텐션도 확인하세요. 모두 깨끗하다면 새 빌드 번호로 한 번 다시 보내세요. 그래도 오류가 계속되면 IPA, `codesign` 출력, 업로드 로그를 첨부해 Apple에 리포트를 보내세요.


## 내 프로젝트

[Review Kit](https://devoria.fr/ko/kits/app-review): 제 App Store 심사 체크리스트, 수정해서 통과한 Apple 리젝 사례, Google Play 체크리스트, Claude Code 스킬 3개를 담았어요. ₩73,000.

[iOS & Android Kit](https://devoria.fr/ko/kits/ios): Claude Code로 iPhone·Android 앱을 만들어 보세요. 제 앱들의 시작 코드, 스토어 출시까지의 과정, 모든 키트를 담았어요. ₩148,000.

[진단: 내 아이폰 앱까지 남은 거리](https://devoria.fr/ko/diagnostic): 7개 질문, 60초. 아이폰 앱 출시를 진짜 가로막는 게 뭔지, 4단계 로드맵, 나에게 맞는 키트까지 알려드려요.
