# iOS 출시

마치면 앱이 App Store 에서 **판매 준비됨** 상태가 돼요. 빌드 처리에 10~30분, 심사에 보통 1~3일 걸려요. 하나만 빠져도(유료 앱 계약, 개인정보 처리방침 주소, 스크린샷) 심사에서 멈추니 아래 순서대로 해요.

```mermaid
flowchart TD
  A[번들 id] --> B[App Store Connect 앱]
  B --> C[TestFlight 테스터] & D[빌드 올리기] & E[등록정보·스크린샷] & F[연령 등급] & G[앱 개인정보 — 법 문서 먼저]
  K[유료 앱 계약] -->|인앱이 있으면| S
  C & D & E & F & G --> S[심사 제출] --> Z([판매 준비됨])
```

## 시작하기 전에

- **Apple 개발자 계정과 App Store Connect 연결** — 같은 키로 번들 id·업로드·등록정보·심사를 다 해요([Apple 개발자 계정](/docs/journey-apple-dev)).
- **개인정보 처리방침·지원 페이지 주소** — 등록정보와 앱 개인정보에 들어가요([법 문서](/docs/journey-legal)).
- **유료 앱 계약** — 인앱 결제·구독이 있을 때만([App Store 돈 받기](/docs/journey-apple-payouts)).

allob 스토어 연동이 되면 allob 이 하고, 그 전까지는 에이전트가 해요. 운영자는 App Store Connect 로그인만 하면 돼요.


:::prompt
이 allob 사업 가이드를 읽고, 내 사업에 해당하는 할 일만 골라 진행해 줘: https://allob.app/docs/journey-ios.md
1. allob business view 와 allob path view --business 로 내 사업 모양(사업자 형태·돈 버는 방식·파는 나라)을 먼저 확인해.
2. 해당하지 않는 할 일은 왜 아닌지 한 줄로 알려 주고 allob step skip <id> --reason "…" 으로 넘겨.
3. 해당하는 할 일은 allob step view <id> 의 안내대로 하고, 끝나면 allob step done <id> --note "끝났다는 증거" 를 불러.
4. 본인 인증·서명·결제·약관 동의처럼 사람만 하는 곳에서는 멈추고 무엇을 누르면 되는지 알려 줘.
5. 되돌리기 어려운 답(과세 유형·계정 유형 등)은 내 폰으로 확인 요청이 와 — 명령이 보여 준 승인 링크를 알려 주고, 기다리는 동안 다른 할 일로 넘어가.
:::

## 번들 id 등록하기 {#ios.bundle-id}

앱의 고유 이름인 번들 id 를 Apple 개발자 계정에 등록하고, 쓸 기능만 켜요.

1. 도메인을 거꾸로 쓴 모양으로 정해요(예: `com.example.diary`). 브랜드·도메인과 맞춰요.
2. 기능(capability)은 실제로 쓸 것만 켜요(예: Apple 로그인, 푸시 알림).
3. iPhone 앱과 맥 앱을 한 구매로 묶어 팔 계획(유니버설 구매)이면 번들 id 를 함께 쓸지 지금 정해요([macOS 출시](/docs/journey-mac)).

⚠ 번들 id 는 스토어에 앱을 만든 뒤 바꿀 수 없어요. 앱 이름은 나중에 바꿔도 돼요.

:::tip 끝났는지 확인
Apple 개발자 계정의 Identifiers 에 번들 id 가 있고 필요한 기능만 켜져 있어요. 증거는 번들 id 와 켠 기능을 적은 메모예요.
:::

에이전트가 끝까지 해요. 등록한 번들 id 는 이 할 일의 메모와 Apple 개발자 계정의 Identifiers 에서 봐요.
## App Store Connect 에 앱 만들기 {#ios.app-record}

App Store Connect 에 이 앱(앱 레코드)을 만들어요. 앱 목록에 보이면 allob 이 끝남으로 바꿔요.

1. 웹에서 **앱 → + → 신규 앱**을 눌러요.
2. 플랫폼 iOS, 이름, 기본 언어, 번들 id, SKU(내부용 이름, 예: `diary-ios`)를 넣어요. 다른 앱이 쓰는 이름은 못 써요.
3. 가격·판매 국가는 나중에 정해도 돼요.

:::tip 끝났는지 확인
App Store Connect 연결의 앱 목록에 이 번들 id 의 앱이 보이면 allob 이 끝남으로 바꿔요.
:::

App Store Connect 로그인만 해 주세요. 나머지 값은 에이전트가 채워요.
## TestFlight 테스터 넣기 {#ios.testflight}

운영자를 TestFlight 내부 테스터로 넣어 새 빌드를 바로 폰에서 받아 봐요.

1. TestFlight → 내부 테스트 그룹을 만들고 운영자를 넣어요. 내부 테스터는 App Store Connect 사용자여야 해요.
2. 그룹에서 **새 빌드 자동 배포**를 켜요. 빌드 처리가 끝나면 폰에 바로 와요.

팀 밖 사람(외부 테스터)은 버전마다 베타 심사를 거쳐요. 처음엔 내부 그룹으로 충분해요.

:::tip 끝났는지 확인
내부 그룹에 운영자가 있고 자동 배포가 켜져 있어요. 첫 빌드 뒤 운영자가 TestFlight 앱에서 그 빌드를 받았으면 더 좋아요.
:::

에이전트가 끝까지 해요. 초대 메일이 오면 운영자 폰의 TestFlight 앱에서 받아요.
## 빌드 올리기 {#ios.build}

앱을 서명해 빌드하고 App Store Connect 에 올려 VALID 빌드를 만들어요.

먼저 빌드할 곳을 골라요.

| 빌드할 곳 | 비용 | 주의 |
|---|---|---|
| 내 맥(Xcode) | 무료(맥 필요) | 처음 환경 설정이 번거로워요 |
| Expo 앱이면 EAS Build | 무료 플랜은 한 달 횟수 제한([가격](https://expo.dev/pricing)) | 횟수를 다 쓰면 다음 달까지 못 빌드해요 |
| CI 의 맥 러너(예: GitHub Actions) | macOS 시간은 비싸요 | 손으로 실행할 때만 돌려요 |
| 클라우드 맥(예: AWS EC2 Mac) | 전용 호스트 시간당, 최소 24시간([조건](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-mac-instances.html)) | 직접 반납해야 과금이 멈춰요 |

그다음 이렇게 올려요.

1. 빌드 번호를 1 올려요. 같은 번호는 다시 못 올려요.
2. 표준 HTTPS 만 쓰는 앱이면 암호화 수출 질문을 건너뛰게 설정해요.
3. 서명해서 올려요 — Xcode 자동 서명, 빌드 도구의 서명 관리(예: EAS), App Store Connect API 키로 하는 클라우드 배포 서명 중 하나예요.
4. 테스트 광고가 섞였거나 OTA 가 시험 채널을 보는 빌드는 올리지 않아요.
5. 올린 뒤 릴리스 빌드를 한 번 켜서 결제·광고와 아이콘을 확인해요.

⚠ App Store Connect API 키(`.p8`)는 한 번만 내려받을 수 있어요. 받자마자 안전한 곳에 둬요.

:::tip 끝났는지 확인
App Store Connect 에 이 버전의 빌드가 VALID 로 처리됐어요. 증거는 버전·빌드 번호를 적은 메모예요.
:::

에이전트가 끝까지 해요. 처리된 빌드는 TestFlight 에서 받아 결제·광고·아이콘을 봐요.
## 등록정보 쓰기 {#ios.listing}

App Store 제품 페이지에 보일 글과 심사에 필요한 정보를 넣어요.

1. 이름·부제·설명·키워드·카테고리를 써요. 언어마다 따로, 그 나라 검색어로 써요.
2. 키워드는 쉼표로만 나누고, 공백 없이 100자를 채워요.
3. 설명엔 앱 소개만 써요. 이모지와 일부 기호는 저장이 안 돼요.
4. 지원 URL·개인정보 처리방침 URL·심사 연락처(전화·메일)를 넣어요.
5. 심사 메모에 로그인 필요 여부, 인앱 상품 위치, 계정 삭제 경로를 적어요. 로그인이 필요하면 심사용 계정도 넣어요.

:::tip 끝났는지 확인
언어마다 이름·부제·설명·키워드가 들어갔고, 지원·개인정보 처리방침 URL 이 캐시 없이 열려요. 증거는 언어 목록과 확인한 URL 을 적은 메모예요.
:::

에이전트가 끝까지 해요. 결과는 App Store Connect 의 앱 버전 페이지에서 봐요.
## 스크린샷 올리기 {#ios.screenshots}

제품 페이지에 보일 스크린샷을 만들어 언어마다 올려요.

1. 앱을 폰 크기로 띄워 장면을 찍고 틀(배경·큰 제목·폰 테두리)에 넣어요. 검색 결과에 먼저 보이는 첫 장이 가장 강해야 해요.
2. iPhone 6.9" 크기로 만들어요. iPad 를 지원하면 iPad 13" 도 필요해요([사양](https://developer.apple.com/help/app-store-connect/reference/screenshot-specifications)).
3. 투명한 부분(알파 채널) 없는 PNG 로 저장해요.
4. 언어마다 화면 속 글도 그 언어로 만들어 올려요.

2027년 4월부터 새 iPhone 화면 크기 스크린샷이 필수라는 2차 자료가 있어요 — **확인 필요**.

:::tip 끝났는지 확인
지원하는 기기·언어마다 스크린샷이 올라갔어요. 증거는 기기·언어별 장수를 적은 메모예요.
:::

에이전트가 끝까지 해요. 결과는 App Store Connect 의 앱 버전 스크린샷에서 봐요.
## 크리에이티브 애셋 올리기(선택) {#ios.creative-assets}

App Store 검색 결과와 제품 페이지 맨 위에 보이는 큰 그림·동영상을 올려요. 안 해도 출시할 수 있어요.

iOS 27·iPadOS 27 이상에서 제품 페이지 헤더와 검색 결과에 보여요. 검색 결과에서 가장 먼저 보이는 그림이에요.

1. 16:9 한 장을 만들면 헤더와 검색 결과 두 자리에 같이 쓸 수 있어요. 크기·길이는 [사양](https://developer.apple.com/help/app-store-connect/reference/app-information/creative-assets-specifications)을 따라요.
2. 가격·할인·웹 주소·다른 플랫폼 로고는 넣지 않아요. 연령 등급에 맞게 만들어요.
3. `store/media/app-store/all/product-page-header/`·`search-results/` 에 파일 하나씩 넣고 `allob store media push` 로 확인한 뒤 `--apply` 로 모든 언어에 올려요. 언어마다 다르게 하려면 `app-store/<언어>/` 에 따로 둬요. App Store Connect → 앱 → **Asset Library**(자산 보관함)에서 손으로 올려도 돼요.
4. 애셋만 따로 심사에 낼 수 있어요([애셋 관리](https://developer.apple.com/help/app-store-connect/manage-app-information/manage-your-app-store-assets/)).

:::tip 끝났는지 확인
쓰려는 자리(헤더·검색 결과)에 언어마다 애셋이 붙었고, 미리보기로 기기별 모습을 확인했어요. 증거는 자리·언어 목록 메모예요.
:::

에이전트가 끝까지 해요. 결과는 App Store Connect 의 Asset Library 미리보기에서 봐요.
## 추적 여부 정하기(ATT) {#ios.att}

앱이 사용자를 추적하는지 정하고, 추적하면 추적 전에 Apple 의 허락 창(ATT)을 띄워요.

추적은 내 앱의 사용자·기기 데이터를 **다른 회사** 데이터와 연결해 광고에 쓰거나 데이터 브로커에게 넘기는 거예요. 앱에 넣은 SDK 가 하는 일도 포함돼요([Apple 정의](https://developer.apple.com/app-store/user-privacy-and-data-use/)).

- **보통 추적이에요** — AdMob 맞춤 광고, 광고 미디에이션 SDK, Meta·TikTok 앱 SDK 로 설치 광고 측정.
- **추적이 아니에요** — 내 서버로만 보내는 자체 분석, 같은 회사 앱끼리의 기기 ID, 사기 방지·보안 용도, 기기 안에서만 쓰는 데이터.

추적한다면 이렇게 해요.

1. 창에 보일 설명 문구를 한 문장으로 써요(예: "더 관련 있는 광고를 보여 주는 데 써요"). 지원하는 언어마다 번역해요.
2. 앱이 첫 화면을 보여 준 뒤 창을 띄워요. 허락 전엔 광고 ID 를 읽지 않고 광고·측정 SDK 도 추적 모드로 켜지 않아요.
3. 거절하면 추적하지 않아요. 기능을 막거나 허락에 보상을 주지 않아요([심사 가이드라인](https://developer.apple.com/app-store/review/guidelines/)). 창 앞의 설명 화면은 괜찮아요.
4. AdMob 을 쓰면 Google 동의 창을 먼저, ATT 를 그다음에 띄워요([AdMob 안내](https://developers.google.com/admob/ios/privacy/strategies)).
5. 앱 개인정보의 "추적에 사용" 답을 이 결정과 같게 맞춰요.
6. 심사 메모에 창이 어디서 뜨는지 적어요. 심사 기기에서 창이 안 보이면 반려돼요.

추적하지 않으면 ATT 창과 설명 문구를 둘 다 넣지 않아요. 넣어 두고 창을 안 띄우면 반려 이유가 돼요.

EU 에선 iOS 27.2 부터 "추가 정보" 단추가 있는 ATT 창이 생겼고, 몇 나라는 그 창만 써요([ATT 문서](https://developer.apple.com/documentation/apptrackingtransparency)). 최소 iOS 버전에 따라 어떻게 갈리는지는 **확인 필요**예요.

:::tip 끝났는지 확인
추적 여부를 정했고, 추적하면 설명 문구·ATT 창·허락 전 추적 막기를 개발 빌드에서 확인했어요(새로 설치하면 창이 뜨고, 거절하면 IDFA 가 0). 추적하지 않으면 해당 없음으로 닫아요. 증거는 추적 여부·근거 SDK·창이 뜨는 곳을 적은 메모예요.
:::

에이전트가 끝까지 해요. 추적 여부와 근거는 이 할 일의 메모에서 봐요.
## 앱 개인정보 답하기 {#ios.privacy-labels}

App Store "앱 개인정보"(개인정보 라벨) 설문에 답하고 게시해요.

1. 앱이 실제로 모으는 데이터만 답해요. 코드·개인정보 처리방침·결제·광고·로그인 설정을 보고, SDK 공식 데이터 안내에 있는 것까지 넣어요. 겁나서 넓게 답하지 않아요([앱 개인정보 세부사항](https://developer.apple.com/app-store/app-privacy-details/)).
2. 추적한다고 정했으면 그 데이터를 "추적에 사용"으로, 아니면 추적 답은 모두 아니요예요.
3. 로그인 계정에 붙는 데이터는 "신원에 연결됨"으로 답해요.
4. **게시**를 눌러야 반영돼요. 로그인·광고·결제를 바꾸면 다시 답해요.

:::tip 끝났는지 확인
앱 개인정보가 게시됐고 답이 처리방침과 같아요. 증거는 데이터 유형별 답 표를 요약한 메모예요.
:::

에이전트가 끝까지 해요. 답 표는 이 할 일의 메모에서, 게시된 답은 App Store Connect 의 앱 개인정보에서 봐요.
## 연령 등급 정하기 {#ios.age-rating}

연령 등급 설문에 답해 앱의 등급을 정해요.

1. 폭력·도박·사용자 생성 콘텐츠·웹 접근 같은 질문에 앱이 실제로 하는 대로 답해요.
2. 나온 등급이 스크린샷·크리에이티브 애셋 내용과 맞는지 봐요.

게임이면 한국 출시에서 이 설문이 등급분류를 대신해요.

:::tip 끝났는지 확인
연령 등급 설문이 저장됐고 등급이 보여요. 증거는 나온 등급을 적은 메모예요.
:::

에이전트가 끝까지 해요. 나온 등급은 App Store Connect 의 앱 정보에서 봐요.
## 심사 제출하기 {#ios.submit}

버전·빌드·(있으면) 첫 인앱 상품을 한 번에 심사에 내고, 판매 준비됨까지 지켜봐요.

1. **제출 전에 한 번 더 봐요** — 유료 앱 계약(인앱이 있으면), 빌드, 스크린샷, 개인정보 처리방침 URL, 약관(EULA) 링크(자동 갱신 구독이면 필수), 심사 메모. 무언가를 뺐다면 그 요구를 이제 무엇이 채우는지도 봐요.
2. **첫 인앱 상품은 앱 버전과 같은 제출로** 내요. 웹의 인앱 상품 화면에서 "심사에 추가"를 눌러요. 인앱 없이 내면 결제 화면이 비어 반려될 수 있어요.
3. 출시 방식을 골라요 — 승인 뒤 자동 또는 수동.
4. 반려되면 고친 뒤 **같은 제출**을 다시 내요. 새 제출을 만들지 않아요.

"심사 제출·출시까지 맡기기"가 꺼져 있으면 제출 앞에서 확인 요청이 오고, 운영자가 승인할 때까지 기다려요.

:::tip 끝났는지 확인
App Store 버전 상태가 "판매 준비됨"(Ready for Distribution)이에요. 증거는 버전·빌드와 상태를 적은 메모예요.
:::

맡기기가 꺼져 있으면 제품 › 스토어(또는 연결)의 승인 요청에서 \"제출\" 한 번만 누르면 돼요.

## 자주 걸리는 함정

| 증상 | 원인·해결 |
|---|---|
| API 로 앱 만들기 403 | 앱 만들기는 웹에서만 돼요 |
| 첫 인앱 제출 409 "cannot be reviewed" | 첫 인앱은 앱 버전과 같은 제출로(웹 "심사에 추가"). 유료 앱 계약이 활성인지도 봐요 |
| 등록정보를 넣었더니 출시 방식이 "승인 뒤 자동"으로 돌아감 | 수동 출시가 필요하면 넣은 뒤 다시 설정해요 |
| 업로드 "Invalid Signature … 서드파티 프레임워크" | 서명 없는 아카이브 안의 프레임워크 → 임시 서명 뒤 내보내기 |
| 올린 빌드에서 Apple 로그인이 바로 실패 | 서명 없는 아카이브에 앱 권한(entitlements)이 빠짐 → 권한 파일을 넣어 임시 서명 |
| 설명 저장 409 | 이모지·일부 기호를 못 넣어요 |
| 크리에이티브 애셋 업로드 실패 | 알파 채널, 크기·비율 오류 |
| 자동 갱신 구독 3.1.2 반려 | 약관(EULA) 링크가 빠졌어요 |
| 스토어 앱에 실제 광고 대신 테스트 광고(또는 반대) | 출시 빌드 검사를 건너뛰었어요 |

한국에서 게임을 팔면 연령 등급 설문이 게임물 등급분류를 대신해요. 스토어 밖(웹·미니앱 플랫폼)에서도 유통하면 따로 판단해요 — **확인 필요**.

:::details 나라·상황별로 달라지는 것
- **EU** — DSA 거래자 정보가 있어야 해요. 없으면 EU 에서 내려가요([Apple 개발자 계정](/docs/journey-apple-dev)).
- **일본** — 일본어 등록정보를 따로 쓰고, 일본어로 팔면 特商法 표기 페이지가 필요해요([법 문서](/docs/journey-legal)).
- **중국 본토** — ICP 신고번호(현지 법인·서버)와, 게임이면 판호가 필요해요. 보통 판매 국가에서 빼요.
- **팔지 않을 나라** — "가격 및 사용 가능 여부"에서 빼요. 판매 국가와 처리방침이 다루는 나라를 맞춰요.
- **나라별 가격** — 가격 등급으로 정해요. 약관엔 금액을 쓰지 않아요(가격을 바꿀 때마다 약관을 고치지 않게).
- **언어별 등록정보** — 번역만 하지 말고 그 나라 검색어로 써요.
:::

## 출처

공식 안내와 마지막으로 맞춰 본 날: 2026-10-18

- [Apple 스크린샷 사양](https://developer.apple.com/help/app-store-connect/reference/screenshot-specifications)
- [Apple 크리에이티브 애셋 사양](https://developer.apple.com/help/app-store-connect/reference/app-information/creative-assets-specifications)
- [Apple App Store 애셋 관리(Asset Library·단독 제출)](https://developer.apple.com/help/app-store-connect/manage-app-information/manage-your-app-store-assets/)
- [Apple 애셋 모범 사례](https://developer.apple.com/app-store/asset-best-practices/)
- [Apple API 로 애셋 배치](https://developer.apple.com/documentation/appstoreconnectapi/placing-assets-on-your-app-store-surfaces)
- [Apple WWDC26 세션](https://developer.apple.com/videos/play/wwdc2026/205/)
- [Adapty — App Store Asset Library(2차 자료)](https://adapty.io/blog/app-store-asset-library/)
- [ObjectGraph — iOS 27 헤더·검색 결과 애셋(2차 자료)](https://objectgraph.com/blog/ios-27-app-store-header-and-search-results-art/)
- [Apple 앱 개인정보 세부사항](https://developer.apple.com/app-store/app-privacy-details/)
- [Apple 사용자 개인정보와 데이터 사용(추적 정의·ATT)](https://developer.apple.com/app-store/user-privacy-and-data-use/)
- [Apple AppTrackingTransparency 문서](https://developer.apple.com/documentation/apptrackingtransparency)
- [Apple NSUserTrackingUsageDescription](https://developer.apple.com/documentation/bundleresources/information-property-list/nsusertrackingusagedescription)
- [Google AdMob iOS 개인정보 전략(UMP·ATT 순서)](https://developers.google.com/admob/ios/privacy/strategies)
- [Apple App Review 가이드라인](https://developer.apple.com/app-store/review/guidelines/)
- [Apple 앱·제출 상태](https://developer.apple.com/help/app-store-connect/reference/app-information/app-and-submission-statuses/)
- [Expo EAS 가격](https://expo.dev/pricing)
- [AWS EC2 Mac 인스턴스](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-mac-instances.html)
- [앱인토스 — 게임 등급분류(2차 자료)](https://toss.im/apps-in-toss/blog/game_rating_classification)
