사전 App Store Connect
구현체

App Store Connect

gabury1고친 사람 github-actions[bot]

App Store Connect 는 개발자가 만든 앱을 Apple 의 앱 스토어로 내보내 줍니다. 앱을 올리는 일부터 심사 신청과 공개 시점 결정까지 웹 브라우저에서 합니다. 출시한 뒤에는 판매와 사용자 반응도 여기서 봅니다.

쉽고 빠른 이해

무슨 일을 하나 — iPhone 앱을 앱 스토어에 내보내는 Apple 의 관리 화면입니다. 새로 만든 빌드를 올리면 목록에 뜹니다. 그중 하나를 골라 심사에 냅니다.

왜 이렇게 하나 — 앱 스토어에 나가는 앱은 Apple 이 먼저 살펴봅니다. 그래서 올리는 것과 공개하는 것 사이에 테스트와 심사와 출시 시점 고르기가 끼어 있습니다. 이 단계들이 한곳에 있어야 어느 빌드가 어디까지 갔는지 보입니다.

어떻게 도나

  1. 앱 항목을 만들고 빌드를 올립니다
  2. 테스터에게 먼저 나눠 줘서 써 보게 합니다
  3. 빌드 하나를 골라 심사에 냅니다
  4. 통과하면 미리 고른 방식대로 스토어에 나갑니다

안 거치는 경우 — 앱 스토어 밖으로 내보내는 빌드는 여기에 올리지 않습니다. Android 앱도 이 서비스와 무관합니다.

대가 — 앱을 가리키는 고유 이름은 빌드를 한 번 올린 뒤로 못 바꿉니다. 나간 버전을 옛 버전으로 되돌릴 수도 없습니다. 고친 새 버전을 다시 심사받아야 합니다.

상세

App Store Connect 가 맡는 범위는 앱 하나를 스토어까지 내보내는 과정 전부입니다. 아래에서 따라가는 것은 앱 하나가 이 서비스에 등록되어 스토어에 나가기까지입니다. 그 과정이 어떤 단위로 쪼개지는지, 어떤 상태를 지나는지, 어디까지가 이 서비스의 몫인지를 차례로 짚습니다.

Apple 이 운영하는 웹 서비스

App Store Connect 는 Apple 이 운영하는 웹 서비스입니다. 앱을 배포용으로 제출하고 관리합니다. 출시 전의 빌드를 테스터에게 나눠 주는 일도 합니다.

빌드는 소스 코드를 컴파일해 만든 설치 파일입니다. 테스터에게 나눠 주는 Apple 의 베타 테스트 기능을 TestFlight 라고 부릅니다.

돈과 계약에 관한 일도 맡습니다. Apple 과의 법적 계약에 동의합니다. 세금과 은행 정보도 넣습니다. 판매 추이와 재무 보고서도 봅니다. 이 일들은 App Store Connect API(Application Programming Interface, 프로그램이 부르는 인터페이스)로 자동화할 수도 있습니다.

처음에는 계정 소유자 한 사람만 로그인할 수 있습니다. Apple Developer Program 에 가입한 그 사람을 Account Holder 라고 부릅니다. 다른 팀원은 그 뒤에 초대를 받아 들어옵니다.

화면은 위쪽 메뉴로 나뉩니다. 사용자는 자기 역할에 딸린 기능만 씁니다.

화면 맡는 일
Apps 앱 추가 · 앱 정보 편집 · 새 버전 만들기 · 심사 제출. 인앱 결제(앱 안에서 파는 아이템과 구독)와 TestFlight 설정도 여기서
Trends 기간별 판매와 추이 보고서
Reports 월별 재무 보고서와 지급 내역
Business 계약 서명 · 세금 정보 · 수익을 받을 은행 정보
Users and Access 사용자 추가와 삭제 · 역할 변경 · API 키 관리

앱 레코드와 버전과 빌드

App Store Connect 는 앱 하나를 세 겹으로 나눠 다룹니다. 맨 위가 앱 레코드입니다. 앱 레코드는 이 서비스 안에서 앱 하나를 대표하는 항목입니다. 이름 · 키워드 · 설명 같은 앱 정보가 여기 모입니다.

앱 레코드는 번들 ID(bundle identifier, 번들 식별자)로 앱을 가립니다. 번들 ID 는 시스템 곳곳에서 앱을 가리키는 고유 이름입니다. 앱 레코드에 적은 번들 ID 는 Xcode 프로젝트에 적은 것과 같아야 합니다.

Xcode 는 Apple 기기용 앱을 짜고 빌드하는 Apple 의 개발 도구입니다.

빌드를 올리려면 앱 레코드부터 있어야 합니다. Xcode 에서 앱을 다 만들기 전에 레코드를 먼저 만들어 둬도 됩니다. 막 만든 레코드의 앱 상태는 Prepare for Submission(제출 준비 중)입니다.

레코드 아래에 버전이 매달립니다. 버전 아래에는 빌드가 매달립니다. 한 앱은 버전을 여럿 가질 수 있습니다. 한 버전도 빌드를 여럿 가질 수 있습니다. 심사에 낼 때는 그 버전의 빌드 가운데 하나를 고릅니다.

flowchart TD
    R["앱 레코드 · 번들 ID 하나"]
    R --> V1["버전 · 버전 번호"]
    R --> V2["다음 버전"]
    V1 --> B1["빌드 · 빌드 문자열"]
    V1 --> B2["빌드"]
    V2 --> B3["빌드"]
    V2 --> B4["빌드"]

버전과 빌드에는 번호가 하나씩 붙습니다. 둘은 앱 안의 정보 속성 목록(Information Property List)에 서로 다른 키로 적힙니다. 빌드 쪽 번호는 빌드 문자열이라고 부릅니다. 빌드 번호라고 부르는 것도 같은 값입니다.

버전 번호 빌드 문자열
속성 목록 키 CFBundleShortVersionString CFBundleVersion
누가 보나 앱 스토어 화면의 사용자 개발자와 App Store Connect
꼴 마침표로 가른 정수 셋. 예 10.14.1 마침표로 가른 정수 하나에서 셋
언제 늘리나 새 버전을 만들 때 새 빌드를 업로드하기 전

빌드는 번들 ID · 버전 번호 · 빌드 문자열 셋을 합쳐 시스템 전체에서 하나로 가려집니다. 빌드가 올라오면 번들 ID 와 버전 번호로 어느 앱의 어느 버전인지가 정해집니다. 빌드 문자열은 그 빌드를 같은 버전의 다른 빌드와 구분합니다.

여러 플랫폼용 앱을 한 번 구매로 팔려면 레코드 하나로 만듭니다. 그 플랫폼들은 번들 ID 를 같이 씁니다. 대신 버전은 플랫폼마다 따로 제출합니다. 한 플랫폼 버전의 상태는 다른 플랫폼에 영향을 주지 않습니다.

올리는 것과 내보내는 것

빌드를 올린다고 사용자에게 가지 않습니다. 올린 빌드는 처리 · 테스트 · 심사 · 출시를 차례로 지날 수 있습니다. 단계마다 상태 이름이 붙어 있어서, 지금 어디까지 왔는지가 화면에 뜹니다.

첫 단계는 업로드 처리입니다. 올린 빌드는 Apple 시스템에서 처리가 끝나야 App Store Connect 에 나타납니다. 처리가 끝나면 메일이 옵니다. 처리 결과는 Complete(완료)나 Failed(실패) 가운데 하나입니다.

처리가 끝난 빌드는 TestFlight 로 테스터에게 나눠 줄 수 있습니다. 그다음 버전에 빌드를 붙여 심사에 냅니다. 심사는 Apple 의 App Review 가 앱을 스토어에 내기 전에 살펴보는 일입니다. 심사는 앱의 모든 버전이 받습니다. 그 버전에 딸린 인앱 결제 상품도 함께 심사를 받습니다.

통과한 버전이 언제 나갈지는 버전마다 미리 고릅니다.

출시 방식 통과한 뒤
수동 출시 Pending Developer Release 로 멈춘다. 개발자가 출시해야 나간다
자동 출시 통과하자마자 나간다
날짜 지정 자동 출시 정한 날짜가 안 됐으면 Pending Developer Release 로 기다린다. 그 날짜에 자동으로 나간다

앱 상태는 앱이 심사와 출시 과정의 어디까지 왔는지를 나타냅니다. 플랫폼 버전마다 따로 매겨집니다. 심사에 낸 뒤로는 아래처럼 옮겨 갑니다.

stateDiagram-v2
    state "제출 준비 중 · Prepare for Submission" as P
    state "심사 대기 · Waiting for Review" as W
    state "심사 중 · In Review" as I
    state "반려 · Rejected" as X
    state "개발자 출시 대기 · Pending Developer Release" as D
    state "배포 가능 · Ready for Distribution" as R
    [*] --> P
    P --> W : 심사에 제출한다
    W --> I
    I --> X
    X --> W : 고쳐서 다시 제출한다
    I --> D : 수동 출시 또는 날짜 지정 출시(정한 날짜 전)
    I --> R : 자동 출시
    D --> R : 출시 버튼 또는 정한 날짜

Ready for Distribution 은 심사를 통과해 배포할 수 있게 된 상태입니다. 지금 스토어에 나가 있는 버전도 이 상태입니다.

업데이트 버전에는 단계적 출시를 걸 수도 있습니다. 자동 업데이트를 켠 사용자에게 여러 날에 걸쳐 나눠 내보냅니다. 그 사이에 출시를 멈출 수 있습니다. 비율과 일정은 단계적 출시 편이 다룹니다.

화면과 같은 일을 하는 API

App Store Connect API 는 이 서비스에서 사람이 하는 일을 자동화하는 REST(Representational State Transfer) 방식의 API 입니다. 주소마다 자원이 하나씩 있습니다. 다루는 영역은 아래와 같습니다.

영역 하는 일
TestFlight 베타 빌드 · 테스터 · 그룹 관리
App Metadata 새 버전 만들기 · 스토어 정보 관리 · 심사 제출
Provisioning 번들 ID · 서명 인증서 · 기기 · 프로비저닝 프로파일 관리
Users and Access 사용자 초대 · 접근 수준 조정 · 삭제
Reporting 판매와 재무 보고서 내려받기
인앱 결제와 구독 · 고객 리뷰 상품 관리 · 리뷰에 답하기

호출마다 JWT(JSON Web Token)를 실어야 합니다. JSON(JavaScript Object Notation)은 키와 값을 글자로 적는 데이터 형식입니다. JWT 는 그렇게 적은 내용에 서명을 붙인 짧은 토큰입니다.

토큰에 서명할 키는 App Store Connect 에서 API 키를 만들어 받습니다. API 키는 두 부분입니다. 공개 부분은 Apple 이 갖습니다. 비공개 키는 개발자가 내려받습니다. 토큰에 서명할 때 쓰는 것이 이 비공개 키입니다.

API 키를 만들 때 역할을 하나 붙입니다. 이 역할은 팀 사용자에게 붙는 역할과 같은 것입니다. 키로 할 수 있는 일의 범위를 이 역할이 정합니다.

API 호출은 개발과 배포에 실제로 쓰는 데이터를 바꿉니다. 화면에서 손으로 고치는 것과 같은 데이터입니다.

App Store Connect 를 거치지 않는 빌드

TestFlight 나 앱 스토어로 내보내는 앱은 App Store Connect 에 앱 레코드를 만들어야 합니다. 앱 스토어 밖으로 배포하는 빌드는 다른 길로 갑니다. Xcode 에서 빌드를 내보내고 App Store Connect 에는 올리지 않습니다.

Android 앱은 이 서비스와 무관합니다. Google Play 에 내는 앱은 Google 의 Play Console 에서 테스트와 출시를 합니다.

포기한 것

Apple 이 App Store Connect 에서 안 하기로 정한 것이 셋 있습니다. 앱과 빌드를 가리키는 값을 못 바꾸게 둔 것, 나간 버전을 되돌리는 길을 안 둔 것, 스토어 정보 대부분을 버전에 묶어 둔 것입니다. 셋마다 무엇을 못 하게 됐는지와 그 덕에 무엇이 지켜지는지를 짝으로 봅니다.

앱과 빌드를 가리키는 값

번들 ID 는 빌드를 한 번 올리고 나면 바꿀 수 없습니다.

SKU(Stock Keeping Unit, 재고 관리 단위)는 앱을 계정에 추가한 뒤로 바꿀 수 없습니다. SKU 는 고객에게 안 보이는 내부 추적용 식별자입니다.

Apple ID 는 앱을 계정에 추가할 때 Apple 이 자동으로 매기는 식별자입니다. 이 값은 아예 고칠 수 없습니다. 사람이 로그인에 쓰는 Apple 계정과는 다른 것입니다.

Xcode 쪽도 마찬가지입니다. 번들 ID 와 빌드 문자열 같은 배포 정보는 대부분 TestFlight 나 앱 스토어로 빌드를 내보낸 뒤에 못 고칩니다.

번호는 앞으로만 갑니다. 새 버전을 만들 때는 앞 버전보다 큰 버전 번호를 넣습니다. 새 빌드를 업로드하기 전에는 빌드 문자열을 늘립니다. Mac 앱의 빌드 문자열은 모든 버전에 걸쳐 커져야 합니다. 다른 플랫폼 앱은 새 버전에서 빌드 문자열을 1부터 다시 시작할 수 있습니다.

예외가 하나 있습니다. 업로드가 Failed 로 끝났을 때는 같은 빌드 문자열을 다음 업로드에 다시 써도 됩니다.

번호를 늘리는 일은 Xcode 에 맡길 수 있습니다. Xcode 가 배포용으로 묶은 앱을 아카이브라고 합니다. 새 아카이브를 올릴 때 Xcode 가 빌드 문자열을 고치게 하는 설정이 있습니다.

그 대신 이 값들은 시스템 전체에서 앱을 가리키는 식별자로 남습니다. 빌드는 번들 ID · 버전 번호 · 빌드 문자열의 조합으로 가려집니다. 셋이 안 바뀌니 한 번 올린 빌드는 처음 붙은 앱과 버전을 계속 가리킵니다. 어느 빌드가 어느 버전의 것인지가 한참 뒤에 봐도 흔들리지 않습니다.

되돌리기가 없는 출시

스토어에 나간 앱에 문제가 생겨도 이전 버전으로 되돌릴 수 없습니다. 고친 새 버전을 만들어 다시 제출해야 합니다.

되돌리기 대신 쓸 수 있는 수단은 둘입니다. 어느 버전에 문제가 났는지에 따라 갈립니다.

하나는 이전 버전 내리기입니다. 이전 버전에 법적 문제나 쓰임새 문제가 있으면 그 버전을 스토어에서 내려 내려받지 못하게 합니다. 지금 나가 있는 버전(Ready for Distribution)에 그런 문제가 있으면 업데이트를 내야 합니다. 업데이트를 낼 수 없을 때만 앱 자체를 스토어에서 뺍니다.

다른 하나는 단계적 출시 멈춤입니다. 단계적 출시 중인 버전은 출시를 멈출 수 있습니다. 한 번에 30일까지 멈출 수 있습니다. 멈추는 횟수에는 제한이 없습니다. 멈추면 자동 업데이트로 더 나가는 것이 그동안 멈춥니다. 다만 단계적 출시 중인 버전은 누구나 스토어에서 손으로 받아 갈 수 있습니다.

앱을 판매에서 빼면 그 버전의 단계적 출시는 끝납니다. 그 버전에서는 다시 못 씁니다. 판매를 되살리면 그 버전은 도달했던 비율과 상관없이 모든 사용자에게 바로 열립니다.

flowchart TD
    Q["나간 앱에 문제가 생겼다"]
    Q --> N["고친 새 버전을 제출한다"]
    N --> V["심사를 다시 받는다"]
    Q --> O["이전 버전이면 그 버전을 내린다"]
    Q --> L["지금 나가 있는 버전이면 업데이트를 낸다"]
    L --> U["업데이트를 못 내면 앱을 스토어에서 뺀다"]
    Q --> S["단계적 출시 중이면 멈춘다"]

못 바꾸는 값을 치르고 얻는 것은 이것입니다. 사용자에게 가는 버전은 하나도 빠짐없이 심사를 거칩니다. 급하게 고친 버전도 새 버전이므로 심사를 다시 받습니다.

버전에 묶인 스토어 정보

스토어 화면에 보이는 정보 대부분은 새 버전을 낼 때만 고칠 수 있습니다. 아래 표가 언제 고칠 수 있는지를 가릅니다.

칸 언제 고치나
이름 첫 심사 제출 전까지는 언제든. 그 뒤에는 새 버전을 만들 때, 또는 버전 상태가 이 칸의 수정을 허용할 때
부제 · 주 카테고리 새 버전을 만들 때
지원 URL(Uniform Resource Locator) · 마케팅 URL 새 버전을 만들 때
이번 버전의 새 기능 · 출시 방식 새 버전을 만들 때
홍보 문구(Promotional Text) 언제든. 다시 제출하지 않는다. 170자까지
기본 언어 · 저작권 · 심사용 연락 정보 언제든

버전에 묶인 덕에 사용자가 스토어에서 읽는 설명도 심사를 거친 내용입니다. 심사에서 앱 정보만 반려되면 앱 상태가 Metadata Rejected 로 따로 뜹니다. 이때는 심사팀의 메시지를 읽고 정보를 고친 뒤 그 메시지에 답합니다.

예시

사람이 화면에서 하는 일을 코드로 부르면 어떻게 생기는지를 실물 셋으로 봅니다. API 요청 하나, fastlane 의 배포 스크립트 하나, Apple 의 Xcode Cloud 입니다. 셋마다 무엇을 실어 보내는지와 왜 그 길을 고르는지를 짚습니다.

App Store Connect API 요청 한 벌

API 를 부르려면 먼저 JWT 를 만듭니다. JWT 는 헤더와 페이로드 두 부분을 JSON 으로 적고 서명한 토큰입니다. 헤더는 이렇게 생겼습니다.

JSON
{
    "alg": "ES256",
    "kid": "2X9R4HXF34",
    "typ": "JWT"
}

alg 에 적는 ES256 은 서명에 쓸 방식의 이름입니다. 이 API 의 토큰은 전부 이 방식으로 서명해야 합니다. kid 는 App Store Connect 에서 받은 비공개 키의 ID 입니다. 상세에서 본 그 비공개 키입니다.

페이로드는 누가 언제 무엇을 하려는지 적습니다.

JSON
{
    "iss": "57246542-96fe-1a63-e053-0824d011072a",
    "iat": 1528407600,
    "exp": 1528408800,
    "aud": "appstoreconnect-v1",
    "scope": [
        "GET /v1/apps?filter[platform]=IOS"
    ]
}

iss 는 App Store Connect 의 API Keys 화면에 나오는 발급자 ID 입니다. aud 에는 appstoreconnect-v1 을 적습니다. iat 와 exp 는 발급 시각과 만료 시각입니다. 1970년 1월 1일부터 센 초로 적습니다.

이 예에서 두 시각의 차이는 1200초, 곧 20분입니다. 대부분의 요청은 수명이 20분을 넘는 토큰을 거절합니다. scope 는 이 토큰으로 허용할 요청의 목록입니다. 넣지 않아도 됩니다. scope 를 넣었다면, 거기 맞는 항목이 없는 요청은 거절당합니다.

서명한 토큰은 요청 헤더의 Authorization 에 Bearer 토큰으로 싣습니다.

터미널
curl -v -H 'Authorization: Bearer [signed token]' \
  "https://api.appstoreconnect.apple.com/v1/apps"

토큰은 요청마다 새로 만들 필요가 없습니다. 만료될 때까지 같은 토큰을 여러 요청에 다시 쓰면 성능이 더 낫습니다.

fastlane 이 API 키로 인증하는 lane

fastlane 은 Apple 서비스와 통신하는 작업들을 액션으로 묶어 부르는 배포 자동화 도구입니다. 액션을 이어 붙인 단위를 lane 이라고 부릅니다. 아래 lane 은 API 키로 인증 정보를 만들어 다음 액션에 넘깁니다.

Ruby
lane :release do
  api_key = app_store_connect_api_key(
    key_id: "D383SF739",
    issuer_id: "6053b7fe-68a8-4acb-89be-165aa6465141",
    key_filepath: "./AuthKey_D383SF739.p8",
    duration: 1200, # optional (maximum 1200)
    in_house: false # optional but may be required if using match/sigh
  )
  pilot(api_key: api_key)
end

key_id 와 issuer_id 는 앞 소절 JWT 의 kid 와 iss 에 들어갈 값입니다. key_filepath 는 App Store Connect 에서 내려받은 .p8 비공개 키 파일입니다. duration 은 토큰 수명을 초로 적습니다. 최대 1200초라서 앞 소절의 20분 상한과 맞습니다. 마지막 줄의 pilot 이 그 인증 정보를 받아 쓰는 다음 액션입니다. pilot 이 무슨 일을 하는 액션인지는 자료에 없습니다(미확인).

fastlane 은 Apple 계정의 아이디와 비밀번호로 쿠키 기반 웹 세션을 열어 인증해 왔습니다. 비공식 API 를 쓰는 쪽은 지금도 그 세션을 씁니다. 그런데 App Store Connect 는 로그인에 2단계 인증을 요구합니다. CI(Continuous Integration, 지속적 통합) 기계는 2단계 인증 코드를 물어도 답할 사람이 없습니다.

세션을 미리 만들어 두는 길도 있습니다. 다만 그 세션의 수명은 하루에서 한 달 사이로 들쭉날쭉합니다. 대개 빌드가 실패하기 시작해야 만료를 압니다. 그래서 fastlane 은 쓸 수 있을 때는 API 키 인증을 권합니다. 2단계 인증이 필요 없다는 것, 성능이 더 낫다는 것, 문서화된 API 라는 것, 더 안정적이라는 것이 그 이유입니다.

Xcode Cloud

Xcode Cloud 는 Apple 의 CI/CD(Continuous Integration and Continuous Delivery, 지속적 통합과 지속적 배포) 시스템입니다. Xcode · TestFlight · App Store Connect 를 하나로 묶습니다. 코드 변경을 검증하고 나면 새 빌드를 TestFlight 의 내부 테스터에게 자동으로 보낼 수 있습니다.

외부 테스트용 빌드와 심사 제출용 빌드에 앱 서명을 붙이는 일도 Xcode Cloud 가 해 줄 수 있습니다. 여기서 말하는 서명은 빌드에 하는 서명입니다. 앞 소절의 토큰 서명과는 다릅니다. 앱 서명 자체는 코드 서명 편이 다룹니다.

결과는 메일로 옵니다. Xcode 나 App Store Connect 에서도 봅니다. Xcode Cloud 가 읽을 소스 코드의 접근 권한은 App Store Connect 의 Users and Access 화면에서 관리합니다.

한 가지는 손으로 합니다. Xcode Cloud 가 만든 빌드는 App Store Connect 에서 테스터 그룹에 직접 넣어야 합니다.

맞물림

App Store Connect 는 Apple 의 다른 물건 넷과 붙어서 돕니다. 앞쪽에는 Apple 개발자 사이트와 Xcode 가 섭니다. 뒤쪽에는 TestFlight 앱과 앱 스토어가 섭니다. 넷이 App Store Connect 에 무엇을 건네고 무엇을 받는지, 그 이음매에서 무엇이 걸리는지를 봅니다.

flowchart TD
    D["Apple 개발자 사이트"] -->|App ID · 프로비저닝 프로파일| X["Xcode"]
    X -->|빌드 업로드| A["App Store Connect"]
    A -->|테스트할 빌드| T["TestFlight 앱"]
    T -->|피드백 · 충돌 기록| A
    A -->|심사를 통과한 버전| S["앱 스토어"]

Apple 개발자 사이트와 번들 ID

Apple 개발자 사이트는 앱의 신원을 등록하는 Apple 의 또 다른 웹 화면입니다. 이 사이트에서 App ID 를 등록합니다.

App ID 는 한 개발 팀의 앱 하나 또는 여럿을 가리키는 두 부분짜리 문자열입니다. 프로비저닝 프로파일 안에서 앱을 가리키는 값이 이 App ID 입니다.

프로비저닝 프로파일은 빌드에 함께 들어가는 파일입니다. 그 안에 App ID 가 있어서 빌드가 어느 앱의 것인지 가려집니다. 프로파일이 무엇을 더 담는지는 프로비저닝 프로파일 편이 다룹니다.

한 앱만 가리키는 App ID 를 만들 때는 그 앱의 번들 ID 를 적습니다. 그래서 같은 번들 ID 가 세 곳에 적힙니다. 개발자 사이트의 App ID, Xcode 프로젝트, App Store Connect 의 앱 레코드입니다. 셋을 맞추는 기준은 두 가지로 갈립니다. 앱 레코드의 번들 ID 는 Xcode 프로젝트의 것과 반드시 같아야 합니다. 개발자 사이트의 App ID 는 Xcode 의 번들 ID 와 같게 두는 것이 좋습니다.

빌드가 어느 앱의 어느 버전에 붙는지는 빌드 안에 적힌 번들 ID 와 버전 번호가 정합니다. 개발자 사이트의 App ID 는 이 연결에 끼지 않습니다.

App ID 가 걸리는 데는 다른 쪽입니다. App ID 에 켠 앱 기능은 그 앱이 쓸 수 있는 기능의 허용 목록이 됩니다. 프로비저닝 프로파일에 App ID 가 빠진 빌드는 TestFlight 에 못 씁니다. 그 빌드의 상태가 Not Available for Testing 으로 뜹니다.

Xcode 와 업로드 도구

빌드를 App Store Connect 로 보내는 쪽은 업로드 도구입니다. 길이 넷 있습니다. Xcode, Swift Playground, 명령줄 도구 altool, macOS 앱 Transporter 입니다. altool 은 Xcode 에 들어 있는 xcrun 으로 부릅니다.

API 로 일을 자동화한다면 Transporter 의 명령줄 도구로 올릴 수 있습니다. 이때 API 에 쓰는 JWT 를 업로드 인증에도 같이 씁니다.

받은 쪽은 빌드를 처리합니다. 처리가 끝나면 메일로 알립니다. 처리가 끝나기 전에는 빌드가 목록에 안 뜹니다. 그래서 테스터에게도 심사에도 못 보냅니다.

TestFlight 앱과 테스터

처리가 끝난 빌드는 App Store Connect 에서 테스터 그룹에 배정합니다. 테스터는 자기 기기에 무료 TestFlight 앱을 깝니다. 초대 메일이나 공개 링크로 초대를 받아 빌드를 설치합니다.

테스터는 두 무리로 갈립니다.

내부 테스터 외부 테스터
누구인가 이 앱에 접근할 수 있는 App Store Connect 사용자 App Store Connect 사용자가 아닌 사람
빌드 배정 자동이나 수동 외부 그룹에 넣고 초대
베타 심사 없다 첫 빌드는 TestFlight App Review 의 전체 심사를 받는다. 같은 버전의 뒤 빌드는 전체 심사를 안 받을 수 있다

외부 그룹을 만들려면 내부 그룹부터 있어야 합니다. Xcode 나 Xcode Cloud 에서 내부 테스트 전용으로 올린 빌드는 내부 그룹에만 넣을 수 있습니다.

반대 방향도 있습니다. 테스터가 남긴 피드백이 App Store Connect 로 돌아옵니다. TestFlight 2.3 이후 판을 쓰는 테스터가 TestFlight 앱이나 베타 앱 안의 화면 캡처로 보낸 것이 여기 뜹니다. 피드백에는 화면 캡처와 충돌에 관한 글이 담깁니다. 새 피드백이 올 때마다 개발자의 웹 서버로 웹훅 알림을 받을 수도 있습니다.

Google Play 쪽 얼개도 비슷합니다. Play Console 은 프로덕션 출시 전에 내부 테스트 · 비공개 테스트 · 공개 테스트 세 트랙을 둡니다.

앱 스토어와 출시

앱 스토어로 나가는 것은 심사를 통과한 버전입니다. 그 전에 App Store Connect 에서 심사에 낼 빌드를 고릅니다. 가격과 세금 분류도 정합니다. 판매 지역은 기본이 모든 App Store 지역입니다. 필요하면 골라 좁힙니다.

통과한 뒤에는 출시 전에 나눠 줄 프로모션 코드를 요청할 수 있습니다. 빌드를 만료시키지 않고 앱 스토어에 냈다면, 초대받은 테스터는 스토어에 나간 뒤에도 그 빌드를 계속 테스트할 수 있습니다.

배포하려면 Apple 과의 계약이 유효해야 합니다. 계약이 끊기면 심사를 통과한 버전도 못 나갑니다.

운영

App Store Connect 를 CI 에 붙여 굴리면 기한과 상한에 걸립니다. 걸리는 데가 넷입니다. TestFlight 빌드, 처리와 심사 대기, API 키와 토큰, 팀 계정입니다. 넷을 숫자로 적습니다.

TestFlight 의 기한과 인원

항목 값
빌드를 테스트할 수 있는 기간 90일. 지나면 빌드 상태가 Expired 가 된다
내부 테스터 최대 100명
외부 테스터 앱마다 최대 10,000명
베타 심사 제출 24시간에 최대 6빌드
한 버전에서 베타 심사 중인 빌드 한 번에 하나. 통과해야 다음 빌드를 낸다
충돌 보고서 내려받기 120일

그룹에서 빌드를 빼도 그 빌드를 쓰던 테스터는 다른 빌드로 바꾸기 전까지 계속 씁니다.

처리와 심사를 기다리는 시간

이름이 비슷한 두 상태가 있습니다. Processing 은 업로드한 빌드에 붙는 상태입니다. Processing for Distribution 은 앱에 붙는 상태입니다.

상황 값
빌드가 Processing 에 머무는 시간 24시간을 넘기면 문제가 있을 수 있다
앱 상태가 Processing for Distribution 인 동안 24시간 안에 배포 가능 상태가 된다
통과나 출시 뒤 스토어에 보이기까지 최대 24시간
Pending Developer Release 로 둔 기간 30일을 넘기면 Apple 이 알림 메일을 보낸다
심사 순서 제출한 순서대로 심사한다는 보장이 없다
한 플랫폼에서 동시에 심사 중인 제출 최대 둘. 앱 버전이 든 제출 하나와 버전 없는 제출 하나

버전 없는 제출은 인앱 이벤트나 커스텀 제품 페이지처럼 앱 버전 없이 낼 수 있는 항목만 담은 제출입니다.

올릴 수 있는 앱 크기에도 상한이 있습니다. iOS 와 iPadOS 앱은 압축을 푼 크기가 4GB 까지입니다. 실행 파일은 __TEXT 섹션을 모두 합쳐 500MB 까지입니다.

API 키와 토큰

API 키와 비공개 키가 무엇인지는 상세에서 봤습니다. 굴릴 때 걸리는 것은 키를 잃는 일과 토큰 수명과 호출 상한입니다.

비공개 키는 한 번만 내려받을 수 있습니다. Apple 은 그 사본을 갖지 않습니다.

키에는 두 종류가 있습니다.

팀 키 개인용 키
접근 범위 모든 앱. 고른 역할에 따라 수준이 갈린다 그 키에 묶인 사용자의 접근 범위와 역할
못 하는 일 — Provisioning 호출 · 판매와 재무 정보 · notaryTool
토큰 페이로드 iss 를 쓴다 iss 대신 주체 키 sub 를 쓴다

팀 키를 만들려면 Admin 역할의 사용자여야 합니다.

비공개 키는 비밀번호처럼 다룹니다. 코드 저장소나 클라이언트 코드에 두지 않습니다. 새었다고 의심되면 바로 폐기합니다. 폐기한 키는 되살릴 수 없습니다. 폐기한 키는 API Keys 화면의 Revoked 아래에 30일 동안 보입니다.

토큰 수명은 대부분의 요청에서 20분까지입니다. 예외로 GET 요청만 담은 scope 를 단 토큰은 일부 자원에서 최대 6개월까지 받아 줍니다.

호출 수에도 상한이 있습니다. 상한은 같은 API 키로 보낸 요청을 기준으로 지난 60분 동안 굴러가며 셉니다. 모든 응답의 X-Rate-Limit 헤더에 지금 값이 실립니다.

user-hour-lim:3500;user-hour-rem:500;

이 예에서 상한은 시간당 3500회입니다. 남은 횟수는 500회입니다. 상한은 경우마다 다를 수 있습니다. 넘으면 HTTP(HyperText Transfer Protocol) 429 응답과 RATE_LIMIT_EXCEEDED 오류 코드가 옵니다.

역할과 계약

팀원은 역할로 권한을 나눠 받습니다. 대개 한 역할을 여러 사람에게 줄 수 있습니다. 한 사람이 역할을 여럿 가질 수도 있습니다.

역할 맡는 일
Account Holder 모든 기능. 법적 계약 서명 · 멤버십 갱신 · API 접근 신청은 이 사람만 한다. 한 명뿐
Admin Account Holder 다음 연락처. 모든 앱에 접근
App Manager 앱의 모든 것. 가격 · 스토어 정보 · 개발과 배포
Developer 앱의 개발과 배포
Finance 재무 정보. 보고서 내려받기 · 세금 서류 올리기

개인으로 가입한 계정은 사용자를 50명까지 더 들일 수 있습니다. 조직으로 가입한 계정은 제한이 없습니다. 로그인하려면 누구나 2단계 인증을 켜야 합니다.

계약은 Account Holder 한 사람에게 묶입니다. 무료 앱은 개발자 프로그램 가입만으로 낼 수 있습니다. 유료 앱이나 인앱 결제를 팔려면 Account Holder 가 유료 앱 계약(Paid Apps Agreement)에 서명해야 합니다. 한 번 동의한 계약은 취소할 수 없습니다. 멤버십이 끊긴 뒤 갱신하면 유료 앱 계약에 다시 동의해야 합니다.

유료 앱 계약의 새 판이 나오면 App Store Connect 에 알림이 뜹니다. Account Holder 가 동의하기 전까지는 새 앱도 새 인앱 결제 상품도 못 만듭니다. 이 한 사람의 동의가 늦으면 팀 전체의 새 앱 등록이 멈춥니다.

관련 항목

App Store Connect 가 속하는 상위 분류

앱 스토어 · 모바일 개발 · 배포 · 릴리스 관리 · 서비스형 소프트웨어

App Store Connect 로 앱이 나가는 운영체제

iOS · iPadOS · macOS · watchOS · tvOS · visionOS

App Store Connect 와 맞물려 도는 Apple 도구

Apple · Xcode · TestFlight · Xcode Cloud · Transporter · altool · Swift Playground · Apple Developer Program

App Store Connect 가 앱과 빌드를 가리는 식별자

번들 ID · SKU · App ID · 빌드 · CFBundleVersion · CFBundleShortVersionString · 시맨틱 버저닝

App Store Connect 에 올리기 전에 거치는 서명 단계

코드 서명 · 인증서 · 프로비저닝 프로파일 · 개발자 계정 · 비공개 키

App Store Connect 가 관리하는 출시 단계

베타 테스트 · 앱 심사 · App Review Guidelines · 단계적 출시 · 자동 업데이트 · 롤백 · 되돌리기 · 샌드박스 테스터

App Store Connect 에서 등록하는 상품과 스토어 페이지 구성 요소

인앱 결제 · 구독 · 프로모션 코드 · 스토어 등재정보 · 커스텀 제품 페이지 · 제품 페이지 최적화 · 인앱 이벤트 · App Clip · Game Center

App Store Connect 에서 보는 판매 지표와 정산 문서

앱 분석 · Sales and Trends · 재무 보고서 · 유료 앱 계약

App Store Connect 계정에 적용되는 접근 규칙

역할 기반 접근 제어 · 최소 권한 원칙 · API 키 · 2단계 인증 · 다중 인증 · AWS IAM

App Store Connect 를 자동화하는 인터페이스와 도구

App Store Connect API · REST API · JWT · ES256 · fastlane · 지속적 통합 · 지속적 배포 · 웹훅 · 속도 제한 · HTTP 429 · App Store Server Notifications

App Store Connect 와 같은 역할을 다른 생태계에서 맡는 배포 서비스

Google Play Console · Firebase App Distribution · Microsoft Partner Center · Steamworks · npm

다른 이름: 앱스토어 커넥트 · 앱 스토어 커넥트 · iTunes Connect