# App Store Connect 빌드 번호: 버전과 빌드 번호 차이

> 버전은 사용자가 보는 번호이고, 빌드 번호는 업로드마다 붙는 식별자예요. 두 값의 조합은 고유해야 하고, Expo에서는 EAS가 빌드 번호를 올려 줘요.

원본 페이지: [App Store Connect 빌드 번호: 버전과 빌드 번호 차이](https://devoria.fr/ko/blog/app-store-connect-build-number-version)
작성자: [Mehdi Azizi](https://devoria.fr/ko/mehdi-azizi)
게시일: 2026-11-04
최종 내용 수정: 2026-11-04


App Store Connect의 build number는 빌드 번호, 즉 업로드할 때마다 각 빌드를 식별하는 `CFBundleVersion` 키예요. 버전인 `CFBundleShortVersionString`은 사용자가 App Store에서 보는 번호고요. **Apple은 버전과 빌드 번호의 조합이 고유해야 한다고 요구해요. 같은 버전에서 빌드 번호는 한 번만 쓸 수 있어요.**

Expo에서는 버전은 직접 정하고, 빌드 번호는 프로덕션 빌드마다 EAS가 자동으로 올리게 할 수 있어요. 이 글에서는 두 번호의 차이, Apple의 규칙, ITMS-90062와 ITMS-90189 오류, 그리고 빌드가 안 보일 때 확인할 것들을 정리해요.

저는 Solys, TradaZen, Nolera 같은 iOS 앱을 Expo와 EAS로 출시하고 있어요. 아래에 나오는 설정은 이 앱들의 `eas.json` 파일에 실제로 들어 있는 거예요.

## 버전과 빌드 번호, 뭐가 다를까요?

앱을 식별하는 Info.plist 키는 두 개예요. [CFBundleShortVersionString에 대한 Apple 문서](https://developer.apple.com/documentation/bundleresources/information-property-list/cfbundleshortversionstring)는 이걸 사용자에게 보이는 버전이라고 설명해요. 10.14.1처럼 점으로 구분한 정수 세 개예요. [CFBundleVersion 문서](https://developer.apple.com/documentation/bundleresources/information-property-list/cfbundleversion)는 빌드 버전을 다뤄요. 정수 한 개에서 세 개까지, 숫자와 점만 쓸 수 있어요.

| 항목      | iOS 키                     | 누가 보나  | Expo 필드         |
| --------- | -------------------------- | ---------- | ----------------- |
| 버전      | CFBundleShortVersionString | 사용자     | `version`         |
| 빌드 번호 | CFBundleVersion            | 나와 Apple | `ios.buildNumber` |

가상의 예를 들어 볼게요. 버전 1.4.0으로 테스트하는 동안 빌드 12, 13, 14를 올리고, 그중 하나를 골라 심사에 제출해요. [App Store Connect 도움말](https://developer.apple.com/help/app-store-connect/manage-builds/upload-builds)이 이렇게 정리해요. 버전은 빌드를 해당 앱 페이지에 연결하고, 빌드 번호는 시스템 전체에서 그 빌드를 식별해요.

## Apple의 번호 증가 규칙

1. **조합이 고유해야 해요.** [Xcode Cloud 문서](https://developer.apple.com/documentation/xcode/setting-the-next-build-number-for-xcode-cloud-builds)에 따르면 App Store Connect는 버전과 빌드 번호의 조합이 고유하기를 요구해요. 그래서 iPhone 앱은 새 버전에서 빌드 번호를 1부터 다시 시작해도 돼요. Mac 앱은 안 돼요. 번호가 항상 올라가야 해요.
2. **승인된 버전은 닫혀요.** Apple이 1.4.0을 승인하면 그 버전에는 더 이상 빌드를 추가할 수 없어요. 다음 버전은 더 높은 번호여야 해요.
3. **각 숫자는 정수로 비교돼요.** 10이 9보다 크니까 1.10은 1.9 다음이에요. 1.20이 승인된 뒤에 1.9를 올리면 거부돼요.

제 조언은 이거예요. **빌드 번호는 1로 되돌리지 말고 계속 올라가는 정수로 유지하세요.** iPhone에서는 1로 다시 시작해도 되지만, 앱 수명 전체에서 고유한 번호를 쓰면 TestFlight에서 두 빌드를 헷갈릴 일이 없어요. 원격 모드로 돌리는 제 앱들도 그렇게 돼요. 버전이 바뀌어도 카운터가 계속 이어져요.

## Expo와 EAS로 버전과 빌드 관리하기

2026년 9월 25일에 업데이트된 [Expo의 버전 관련 페이지](https://docs.expo.dev/build-reference/app-versions/)는 역할을 나눠요. 버전(app.json의 `version`)은 직접 관리해요. 새 릴리스를 준비할 때 바꾸면 돼요. 빌드 번호(`ios.buildNumber`)는 EAS에 맡길 수 있어요. Expo도 빌드 번호를 안 올리는 실수를 업로드 거부의 흔한 원인으로 꼽아요.

설정은 전부 eas.json에서 해요.

```json
{
  "cli": {
    "appVersionSource": "remote"
  },
  "build": {
    "production": {
      "autoIncrement": true
    }
  }
}
```

- **`"remote"`**: EAS 서버가 빌드 번호를 보관해요. EAS CLI 12부터 권장되는 방식이에요. 카운터는 설정에 있는 값이나 1에서 시작하고, 그 뒤로 `ios.buildNumber`는 무시돼요.
- **`"local"`**: 내 설정 파일이 기준이에요. `autoIncrement`를 켜면 EAS가 파일의 `ios.buildNumber`를 수정하고, 빌드할 때마다 그 변경을 커밋해야 해요.
- **`autoIncrement`**: [eas.json 레퍼런스](https://docs.expo.dev/eas/json/)에 따르면 빌드 번호용으로 `true`나 `"buildNumber"`를, 버전의 마지막 숫자를 올리려면 `"version"`을 쓸 수 있어요. 원격 모드에서는 `"version"`이 지원되지 않는다고 Expo가 명시해요.

제 경우 TradaZen과 Nolera는 `remote`예요. Solys는 `local`로 남아 있어요. 빌드 번호가 app.json에 있고, 프로덕션 빌드를 할 때마다 파일 안에서 올라가요. **둘 다 잘 돌아가지만, 원격 모드는 커밋을 깜빡할 위험을 없애 줘요.**

명령어 두 개가 이걸 보완해요. `eas build:version:set`은 원격 카운터를 초기화해요. Apple에 마지막으로 올린 번호를 입력하세요. `eas build:version:sync`는 원격 값을 프로젝트로 복사해요. 언젠가 Xcode로 빌드할 때 유용해요. EAS Update를 쓴다면 원격 모드는 `nativeVersion` 정책과 함께 쓸 수 없어요. Expo는 `appVersion`을 권장해요.

## ITMS-90062: 이미 승인된 버전이에요

메시지는 이런 식이에요(번호는 가상).

```text
ERROR ITMS-90062: This bundle is invalid. The value for key
CFBundleShortVersionString [1.4.0] in the Info.plist file must
contain a higher version than that of the previously approved
version [1.4.0].
```

Apple이 이미 1.4.0을 승인했으니 여기에 빌드를 더 추가할 수 없어요. **app.json에서 버전을 예를 들어 1.4.1로 올리고 다시 빌드하세요.** 빌드 번호만 바꾸면 해결되지 않아요.

`version`을 올렸는데도 오류가 계속되면 `ios.version` 필드가 있는지 찾아보세요. [Expo 설정 레퍼런스](https://docs.expo.dev/versions/latest/config/app/)에 따르면 iOS에서는 이 값이 `version`보다 우선해요. 비슷한 오류인 ITMS-90186 "Invalid Pre-Release Train"도 해결법은 같아요. 새 빌드를 받을 수 없게 닫힌 버전이라는 뜻이에요.

## ITMS-90189: Redundant Binary Upload

이번엔 빌드 번호가 문제예요.

```text
ERROR ITMS-90189: Redundant Binary Upload. You've already uploaded
a build with build number '12' for version number '1.4.0'.
```

1.4.0 (12) 조합이 이미 Apple에 있어요. Expo에서는 원인이 보통 네 가지예요.

- **사용한 프로필에 `autoIncrement`가 없어요.** Nolera처럼 TestFlight용 프로필을 따로 만들었다면 거기에도 옵션을 넣으세요.
- **원격 카운터가 뒤처져 있어요.** 수동으로 업로드하다가 `remote`로 바꿨다면, Apple에 있는 마지막 번호로 `eas build:version:set`을 실행하세요.
- **로컬 모드에서 커밋을 깜빡했어요.** 다음 빌드가 예전 번호에서 다시 시작해요.
- **같은 바이너리를 다시 보내고 있어요.** `eas submit`에서 예전 빌드가 아니라 새 빌드를 고르세요.

**해결법은 늘 같아요. 더 높은 번호로 새 빌드를 만드는 거예요.**

## "No builds available": 빌드가 안 보여요

빌드는 올라갔는데 앱 페이지에서 선택할 수 없는 경우예요. 이 순서대로 확인하세요.

1. **아직 처리 중이에요.** Apple은 빌드를 표시하기 전에 처리하고, 끝나면 이메일을 보내요. [Expo](https://docs.expo.dev/submit/ios/)는 보통 10~15분이라고 해요. [Apple에 따르면](https://developer.apple.com/help/app-store-connect/manage-builds/view-builds-and-metadata) 처리 중 상태가 24시간을 넘으면 Feedback Assistant로 문의해야 해요.
2. **암호화 신고를 기다리고 있어요.** Missing Compliance 상태예요. 아래에서 자세히 설명해요.
3. **버전이 맞지 않아요.** 1.4.1 빌드는 App Store Connect에서 1.5.0으로 준비한 페이지 아래에 들어가지 않아요. 둘을 맞추세요.
4. **그사이에 버전이 출시됐어요.** [빌드 선택 도움말](https://developer.apple.com/help/app-store-connect/manage-builds/choose-a-build-to-submit)에 따르면 이 경우 목록에는 그 출시 이후에 올린 빌드만 보여요.
5. **테스터에게 안 보이는 거예요.** TestFlight 앱에서 "no builds available"은 빌드가 어떤 그룹에도 없거나, 베타 심사를 기다리거나, 만료됐다는 뜻인 경우가 많아요. 자세한 건 [TestFlight로 iPhone 앱 테스트하기](https://devoria.fr/ko/blog/testflight-iphone-app-beta-testing)에 있어요.

### 알아 둘 상태

빌드가 안 보이는 이유를 가장 자주 설명해 주는 상태들이에요. [Apple의 목록](https://developer.apple.com/help/app-store-connect/reference/app-build-statuses)을 기준으로 했어요. Processing과 Failed는 그 목록에 없어요. [빌드 추적 문서](https://developer.apple.com/help/app-store-connect/manage-builds/view-builds-and-metadata)에 나오는 업로드 상태예요.

| 상태               | 의미                    | 해결법                     |
| ------------------ | ----------------------- | -------------------------- |
| Processing         | Apple이 빌드를 처리 중  | 이메일 기다리기            |
| Failed             | 처리 중 오류            | 오류 확인 후 다시 업로드   |
| Missing Compliance | 암호화 미신고           | 질문에 답하거나 Info.plist |
| Invalid Binary     | 규격에 맞지 않는 업로드 | 수정 후 새 빌드            |
| Expired            | 90일 경과               | 새 빌드                    |
| Ready to Submit    | 테스트나 심사 준비 완료 | 그룹에 추가하기            |

### 암호화 신고는 한 번에 끝내기

`ITSAppUsesNonExemptEncryption` 키가 없으면 [Apple](https://developer.apple.com/documentation/bundleresources/information-property-list/itsappusesnonexemptencryption)은 새 버전마다 규정 준수 질문을 해요. Expo에서는 필드 이름이 `ios.config.usesNonExemptEncryption`이에요.

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

`false`는 암호화를 쓰지 않거나, 면제된 암호화만 쓴다는 뜻이에요. [Apple은](https://developer.apple.com/documentation/security/complying-with-encryption-export-regulations) HTTPS 연결처럼 시스템에 내장된 암호화는 보통 면제되고, 이 답변이 사용하는 라이브러리까지 포함한다고 설명해요. 제 앱 세 개는 모두 `false`로 신고해요. **내 앱에 정말 해당될 때만 `false`를 넣으세요. 신고 내용에 대한 책임은 나한테 있어요.**

## 이미 올린 빌드의 번호를 바꿀 수 있나요?

아니요. 번호는 서명된 바이너리 안에 들어 있어요. 고치려면 새 빌드가 필요해요.

바꿀 수 있는 건 버전에 연결된 빌드예요. Apple은 버전당 빌드 하나만 허용하지만, 심사에 제출하기 전까지는 [원하는 만큼 교체할 수 있어요](https://developer.apple.com/help/app-store-connect/manage-builds/choose-a-build-to-submit).

1. App Store Connect에서 버전을 열고 Build 섹션으로 가요.
2. 현재 빌드 위에 마우스를 올리고 삭제 버튼(마이너스 기호)을 클릭해요.
3. 추가 버튼(플러스 기호)을 클릭하고 올바른 빌드를 고른 다음 저장해요.

버전에서 빌드를 빼도 계정에서 삭제되지는 않아요. 버전이 이미 심사 중이라면 [먼저 제출을 철회하세요](https://developer.apple.com/help/app-store-connect/manage-submissions-to-app-review/remove-a-submission-from-review). 심사는 처음부터 다시 시작돼요.

## 다음 업로드 전에

빌드 번호는 업로드 때 확인하는 항목 중 하나일 뿐이에요. 빌드 이미지 때문에 [ITMS-90725](https://devoria.fr/ko/blog/itms-90725-sdk-version-issue-expo)가 날 수도 있고, 서명에도 나름의 함정이 있어요. [iOS 개발자 인증서와 provisioning profile](https://devoria.fr/ko/blog/ios-certificate-provisioning-profile-expo)에 자세히 정리했어요. 빌드부터 TestFlight까지 전체 흐름은 [Mac 없이 iOS 앱 출시하기](https://devoria.fr/ko/blog/publish-ios-app-without-mac-expo-eas)에, 심사 기간은 [App Store 심사 기간](https://devoria.fr/ko/blog/app-store-review-time-how-long)에 있어요. 모든 단계는 [App Store에 앱 출시하기](https://devoria.fr/ko/expertise/publish-app-on-app-store) 페이지에 모아 뒀어요.

첫 출시를 준비 중이라면 [무료 진단을 받아 보세요](https://devoria.fr/ko/diagnostic). 프로젝트에서 뭐가 막히는지 알려 주고, 제 Apple 리젝 방지 체크리스트도 보내 드려요. 앱을 만들고, 구독을 연결하고, 출시하는 과정은 [iOS & Android Kit](https://devoria.fr/ko/kits/ios)가 제 앱들의 Starter Code와 함께 네 단계로 안내해요. 내 속도에 맞춰 진행하면 돼요.

## 자주 묻는 질문

### App Store Connect에서 버전과 build number는 뭐가 다른가요?

버전은 1.4.0처럼 릴리스에 붙는 공개 번호예요. build number는 그 버전으로 Apple에 올린 특정 바이너리를 식별해요. 한 버전에 빌드를 여러 개 올릴 수 있고, 각각 고유한 번호를 가져요.

### 업로드할 때마다 빌드 번호를 바꿔야 하나요?

네, 같은 버전이라면요. Apple은 같은 버전과 빌드 번호 조합으로 두 번째 업로드를 하면 거부해요. 그게 ITMS-90189 오류예요. EAS에서는 `autoIncrement`가 프로덕션 빌드마다 알아서 처리해 줘요.

### 버전마다 빌드 번호를 1부터 다시 시작해야 하나요?

필수는 아니에요. iPhone에서는 조합만 고유하면 되니까 새 버전에서 더 낮은 번호도 받아 줘요. 그래도 계속 올라가는 카운터가 관리하기 더 쉬워요.

### App Store Connect에서 build number는 어떻게 바꾸나요?

이미 올린 빌드의 번호는 바꿀 수 없어요. 대신 심사 중이 아니라면 앱 페이지의 Build 섹션에서 버전에 연결된 빌드를 교체할 수 있어요. 새 번호가 필요하면 다시 빌드하세요.

### 왜 App Store Connect에 빌드가 안 보이나요?

대부분은 아직 처리 중이거나 암호화 신고를 기다리는 상태예요. 빌드의 버전이 앱 페이지의 버전과 같은지도 확인하세요. 처리 중 상태가 24시간을 넘으면 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단계 로드맵, 나에게 맞는 키트까지 알려드려요.
