# EAS Submit iOS: Expo 앱 App Store 출시 방법

> EAS Submit은 iOS 빌드를 App Store Connect로 보내 TestFlight에 올려요. 심사 제출은 App Store Connect에서 직접 해야 해요.

원본 페이지: [EAS Submit iOS: Expo 앱 App Store 출시 방법](https://devoria.fr/ko/blog/eas-submit-ios-publish-expo-app-store)
작성자: [Mehdi Azizi](https://devoria.fr/ko/mehdi-azizi)
게시일: 2026-10-25
최종 내용 수정: 2026-10-25


`eas submit --platform ios`는 iOS 빌드를 App Store Connect로 보내고, Apple의 처리가 끝나면 빌드가 TestFlight에 나타나요. **이 명령어는 앱을 Apple 심사에 제출하지 않아요. 빌드 선택과 심사 제출은 App Store Connect에서 직접 해야 해요.** 자동화하려면 앱 레코드 번호(`ascAppId`)와 App Store Connect API 키가 필요해요.

저는 Solys, TradaZen, Nolera 같은 iOS 앱을 Expo, EAS Build, EAS Submit으로 출시하고 있어요. 이 가이드는 [Expo의 iOS 제출 문서](https://docs.expo.dev/submit/ios/)를 따르고, 2026년 10월 25일에 다시 확인했어요. Mac이 없다면 전체 과정은 [Mac 없이 iOS 앱 출시하기](https://devoria.fr/ko/blog/publish-ios-app-without-mac-expo-eas)에 있어요. 여기서는 제출에만 집중할게요.

## 첫 명령어 전에 준비할 것

Expo가 제시하는 사전 조건은 세 가지예요.

- **유료 Apple Developer 계정.** 가격과 가입 방법은 [Apple 개발자 계정](https://devoria.fr/ko/blog/apple-developer-account-price-free-vs-99)에 있어요.
- **`ios.bundleIdentifier`에 넣을 번들 ID.** [Expo 설정 레퍼런스](https://docs.expo.dev/versions/latest/config/app/)에 따르면 직접 정하면 되지만, App Store 전체에서 고유해야 해요.
- **EAS CLI 설치** 후 Expo 계정으로 `eas login`.

서명된 프로덕션 빌드도 필요해요. iOS 인증서와 프로비저닝 프로파일에서 설명했듯이, EAS Build가 대신 관리하는 인증서와 프로파일로 빌드를 만들어 줘요.

### App Store Connect 앱 레코드: 직접 만들까, EAS에 맡길까?

EAS Submit은 App Store Connect에 이미 존재하는 앱으로 바이너리를 보내요.

**직접 만들 수 있어요.** [Apple 도움말](https://developer.apple.com/help/app-store-connect/create-an-app-record/add-a-new-app)에 New App 창이 설명되어 있어요. 플랫폼, 이름, 기본 언어, 번들 ID, SKU, 사용자 접근 권한을 입력해요. Account Holder, Admin, App Manager 역할이 필요해요.

**EAS가 첫 제출 때 만들어 줄 수도 있어요.** [Expo의 TestFlight 페이지](https://docs.expo.dev/submit/testflight/)에 따르면, 첫 빌드를 보낼 때 `eas submit`이 앱 레코드를 만들어요. [eas.json 레퍼런스](https://docs.expo.dev/eas/json/)에 따르면 `ascAppId`를 입력하면 이 단계를 건너뛰어요. 이름은 `appName`에서, 없으면 설정의 `name`에서 가져와요. 기본 언어는 `language`에서 가져오고, 기본값은 `en-US`예요. **앱을 프랑스어로 먼저 출시한다면 첫 제출 전에 `language`를 입력하세요.**

그다음 앱 레코드 번호를 `ascAppId`에 옮겨 적으세요. Expo가 위치를 알려 줘요. App Store Connect에서 앱을 열고 App Information으로 가세요. General Information 아래의 Apple ID 필드예요. **번들 ID가 아니라 숫자예요.**

## Apple ID 대신 API 키를 쓰는 이유

EAS Submit은 Apple ID 또는 App Store Connect API 키로 Apple에 연결해요.

Apple ID는 이중 인증에 막혀요. [Apple은](https://developer.apple.com/support/authentication/) 모든 App Store Connect 사용자에게 이중 인증을 요구하기 때문에, 사람이 직접 로그인을 확인해야 해요. `EXPO_APPLE_APP_SPECIFIC_PASSWORD`로 넘기는 앱 암호를 쓰면 이 단계를 피할 수 있지만, [Expo는 이 방법이](https://github.com/expo/fyi/blob/main/apple-app-specific-password.md) 기본값이자 권장 방법인 API 키보다 덜 안전하다고 봐요. **API 키는 아무런 상호작용 없이 인증할 수 있어서 제출을 자동화할 수 있어요.**

키를 얻는 방법은 두 가지예요.

- **EAS에 관리를 맡기기.** `eas credentials --platform ios`를 실행하고 `production` 프로필을 고른 뒤, Apple 계정에 로그인하고 "App Store Connect: Manage your API Key"를 선택하세요.
- **직접 만든 키 쓰기.** App Store Connect에서 Users and Access, Integrations 탭, App Store Connect API, Team Keys, 그리고 Generate API Key로 가세요. Admin 계정이 필요하고, [Expo 가이드](https://github.com/expo/fyi/blob/main/creating-asc-api-key.md)는 키에 Admin 역할을 줘요.

두 번째 방법이라면 활성 키 목록에 표시되는 Key ID와 [Integrations 페이지 상단](https://developer.apple.com/documentation/appstoreconnectapi/generating-tokens-for-api-requests)에 있는 Issuer ID를 적어 두세요. 무엇보다 `.p8` 파일을 잘 보관하세요. [딱 한 번만 다운로드할 수 있고](https://developer.apple.com/documentation/appstoreconnectapi/creating-api-keys-for-app-store-connect-api), Apple은 사본을 보관하지 않아요.

> Apple에 따르면 Admin 키는 계정의 사용자를 만들고 삭제할 수 있어요. Apple은 키를 절대 코드 저장소에 넣지 말라고 해요.

## 복사해서 쓰는 최소 eas.json

모든 값은 가짜예요. 본인 값으로 바꾸세요.

```json
{
  "cli": {
    "appVersionSource": "remote"
  },
  "build": {
    "production": {
      "autoIncrement": true
    }
  },
  "submit": {
    "production": {
      "ios": {
        "ascAppId": "1234567890",
        "appleTeamId": "ABCDE12345",
        "ascApiKeyPath": "./keys/AuthKey_XXXXXXXXXX.p8",
        "ascApiKeyIssuerId": "your-issuer-id",
        "ascApiKeyId": "XXXXXXXXXX"
      }
    }
  }
}
```

- **`appVersionSource`와 `autoIncrement`**: EAS 서버가 빌드 번호를 보관하고 프로덕션 빌드마다 올려요. EAS CLI 12부터 [Expo는 이 원격 방식을 권장해요](https://docs.expo.dev/build-reference/app-versions/).
- **`ascAppId`**: 앱 레코드 번호예요. 없으면 비대화형 모드가 실패해요.
- **`appleTeamId`**: Apple Developer 팀 ID예요.
- **`ascApiKeyPath`, `ascApiKeyIssuerId`, `ascApiKeyId`**: API 키예요. 세 필드 모두 환경 변수를 받아요. `keys` 폴더는 `.gitignore`에 추가하세요.

`appleId` 필드는 Apple ID로 로그인할 때만 필요해요. EAS가 이미 키를 관리하고 있다면 `ascApiKey` 필드 세 개도 지우세요. 10월 25일에 확인해 보니, 제 앱 세 개의 프로덕션 제출 프로필에는 `ascAppId`만 있고 Solys에만 `appleTeamId`가 더 있어요. 파일 안에 키는 없어요.

## 빌드 후 제출하기

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

다른 옵션 없이 실행하면 `eas submit`이 보낼 빌드를 고르게 하고, 처음 실행할 때 Apple ID를 물어봐요. `production` 제출 프로필이 있으면 기본으로 쓰여요. [EAS CLI 레퍼런스](https://docs.expo.dev/eas/cli/)에 선택 과정을 건너뛰는 옵션이 나와 있어요.

| 옵션             | 하는 일              |
| ---------------- | -------------------- |
| `--latest`       | 최신 iOS 빌드 전송   |
| `--id`           | 특정 EAS 빌드 전송   |
| `--path`         | 로컬 .ipa 파일 전송  |
| `--url`          | 온라인 아카이브 전송 |
| `--groups`       | 내부 그룹에 추가     |
| `--what-to-test` | "What to test" 입력  |

한 번에 이어서 하려면 빌드 명령어에 `--auto-submit`을 붙이세요. [Expo의 자동 제출 페이지](https://docs.expo.dev/build/automate-submissions/)에 따르면, 빌드가 끝나면 빌드 프로필과 같은 이름의 제출 프로필로 EAS Submit에 넘어가요. 다른 프로필을 쓰려면 `--auto-submit-with-profile=이름`을 쓰세요. **빌드는 TestFlight로 가지, 심사로 가지 않아요.**

CI에서는 `--non-interactive`와 `EXPO_TOKEN` 토큰을 추가하세요. 이때 명령어는 아무것도 물어볼 수 없어요. 프로필에 `ascAppId`가 있어야 하고, API 키도 필요해요. EAS가 앱에 연결해 둔 키든, `ascApiKey` 필드 세 개에 넣은 본인 키든 상관없어요.

## 제출 후에 일어나는 일

**1. Apple이 빌드를 처리해요.** 이 처리를 거쳐야 App Store Connect에 나타나고, 끝나면 [Apple이 이메일을 보내 줘요](https://developer.apple.com/help/app-store-connect/manage-builds/upload-builds). Expo는 TestFlight에서 보이기까지 보통 10~15분 걸린다고 해요.

**2. 수출 규정 준수.** Missing Compliance 상태는 암호화 관련 신고가 빠졌다는 뜻이에요. Info.plist에 이미 답이 없으면 App Store Connect는 새 버전마다 이 질문을 해요. Expo에서는 키 이름이 `ios.config.usesNonExemptEncryption`이에요.

```json
{
  "expo": {
    "ios": {
      "config": {
        "usesNonExemptEncryption": false
      }
    }
  }
}
```

[Apple](https://developer.apple.com/documentation/security/complying-with-encryption-export-regulations)에 따르면, 라이브러리를 포함해 앱이 암호화를 전혀 쓰지 않거나 면제된 암호화만 쓴다면 `false`가 맞아요. URLSession을 통한 HTTPS 같은 시스템 암호화는 보통 면제돼요. **앱에 실제로 해당될 때만 `false`로 신고하세요. 신고 내용에 대한 책임은 본인에게 있어요.** Info.plist의 다른 키처럼 새 빌드가 필요해요.

**3. TestFlight.** [Apple에 따르면](https://developer.apple.com/help/app-store-connect/reference/app-build-statuses) Ready to Submit 상태가 되면 빌드를 내부 테스터에게 배포하거나, 외부 테스터용 베타 심사를 받거나, App Store 심사로 보낼 수 있어요. 프로필의 `groups` 필드를 쓰면 내부 그룹에 추가돼요. 나머지는 모두 [TestFlight로 앱 테스트하기](https://devoria.fr/ko/blog/testflight-iphone-app-beta-testing)에 있어요.

## 제출(업로드)은 심사 제출이 아니에요

[Expo도 명시하고 있어요](https://docs.expo.dev/submit/introduction/). TestFlight 빌드는 App Store에 자동으로 출시되지 않아요. EAS Submit은 앱 정보도, 스크린샷도 채워 주지 않아요. App Store Connect에서 할 일이 네 가지 남아 있고, [심사 제출에 관한 Apple 도움말](https://developer.apple.com/help/app-store-connect/manage-submissions-to-app-review/submit-an-app)에 설명되어 있어요.

1. 버전의 **필수 메타데이터를 채우세요.**
2. 버전의 Build 섹션에서 **빌드를 고르세요.**
3. **"Add for Review"를 클릭하세요.** 버전이 Ready for Review로 바뀌지만, 아직 심사로 간 건 없어요.
4. **"Submit for Review"를 클릭하세요.** 심사가 시작되면 상태가 In Review로 바뀌어요.

## 자주 나는 오류와 해결 방법

| 표시되는 오류         | 원인                   | 해결                      |
| --------------------- | ---------------------- | ------------------------- |
| ITMS-90189            | 이미 쓴 빌드 번호      | `autoIncrement`           |
| ITMS-90062 또는 90186 | 이미 닫힌 버전         | `version` 올리기          |
| "Set ascAppId"        | CI에서 `ascAppId` 없음 | `ascAppId` 추가           |
| "API Keys cannot"     | 연결된 키 없음         | `eas credentials`         |
| ITMS-90683            | 권한 사용 설명 누락    | `ios.infoPlist`           |
| ITMS-91053            | 불완전한 매니페스트    | `ios.privacyManifests`    |
| ITMS-90725            | 너무 오래된 iOS SDK    | Expo SDK 올리기           |
| Missing Compliance    | 암호화 미신고          | `usesNonExemptEncryption` |

Expo에 따르면 이미 쓴 빌드 번호는 업로드 거절의 흔한 원인이에요. 자세한 내용은 빌드 번호와 버전에 있어요. 세 가지 오류는 별도 가이드가 있어요. [Expo에서 ITMS-90683](https://devoria.fr/ko/blog/itms-90683-missing-purpose-string-expo), [Expo에서 ITMS-91053](https://devoria.fr/ko/blog/itms-91053-missing-api-declaration-expo), ITMS-90725를 보세요.

따옴표 안의 두 메시지는 EAS에서 나오고, EAS 설정에서 고쳐요. Missing Compliance는 App Store Connect에서 질문에 답해도 해결돼요. **나머지 항목은 모두 바이너리를 고쳐야 해요. 다시 빌드하고 다시 보내세요.** 원격 업데이트로는 Info.plist도, 매니페스트도, 번호도 바뀌지 않아요.

## 헤매지 않고 첫 앱 제출하기

명령어는 한 단계일 뿐이에요. [iOS Kit](https://devoria.fr/ko/kits/ios)는 구독 기능까지 포함된 제 앱들의 시작 코드에서 출발해, 네 단계를 거쳐 App Store까지 본인 속도에 맞춰 진행해요.

첫 출시를 준비하고 있다면 [무료 진단을 받아 보세요](https://devoria.fr/ko/diagnostic). 정말로 무엇이 막고 있는지 알려 주고, Apple 리젝 방지 체크리스트도 보내 드려요. 앱 정보, 스크린샷, 심사 통과는 [App Store에 앱 출시하기](https://devoria.fr/ko/expertise/publish-app-on-app-store) 페이지에서 단계별로 다뤄요.

## 자주 묻는 질문

### Expo 앱을 App Store에 어떻게 출시하나요?

EAS Build로 프로덕션 빌드를 만든 뒤 `eas submit --platform ios`로 보내세요. Apple 처리가 끝나면 TestFlight에 나타나요. 그다음 App Store Connect에서 앱 정보를 채우고, 버전에서 이 빌드를 고른 뒤 "Add for Review"와 "Submit for Review"를 클릭하세요.

### EAS Submit이 앱을 Apple 심사에 제출하나요?

아니요. EAS Submit은 바이너리를 App Store Connect로 보내고, 빌드는 TestFlight에 도착해요. 심사 제출은 앱 정보를 채우고 빌드를 고른 뒤 App Store Connect에서 직접 해요.

### 앱의 ascAppId는 어디서 찾나요?

App Store Connect에서 앱을 열고 App Information으로 가세요. General Information 아래의 Apple ID 필드예요. 숫자이고, 번들 ID와 헷갈리면 안 돼요.

### eas submit을 쓰려면 Apple ID가 필요한가요?

처음 실행할 때 명령어가 Apple ID를 물어봐요. 그 뒤로는 프로필에 `ascAppId`가 있고 App Store Connect API 키가 있으면 CI에서도 상호작용 없이 돌아가요. API 키는 Expo의 기본값이자 권장 방법이에요.

### TestFlight에서 빌드가 보이기까지 얼마나 걸리나요?

Expo는 Apple 쪽 처리에 보통 10~15분 걸린다고 하고, 끝나면 Apple이 이메일을 보내 줘요. 빌드가 Missing Compliance 상태에 머물러 있다면 암호화 질문에 답하고, 다음 빌드부터는 설정에 신고해 두세요.


## 내 프로젝트

[Apple Review Kit](https://devoria.fr/ko/kits/review-apple): 제가 쓰는 App Store 심사 체크리스트, 수정한 Apple 리젝 사례, 심사자용 메모, 앱을 검토하는 Claude Code skill 두 개. 29 €.

[iOS Kit](https://devoria.fr/ko/kits/ios): Claude Code로 iPhone 앱을 만드세요. 제 앱들의 Starter Code, 작업을 검사하는 skill, Apple Review Kit, App Store Screenshots Kit, ASO Kit 포함. 129,99 €.
