Flutter 앱을 App Store에 출시하는 과정

Flutter 앱을 App Store에 처음 올릴 때 거치는 과정을 Developer Program 가입부터 심사 제출까지 순서대로 정리했어요.


1. Apple Developer Program 등록

왜 필요한가요?

Apple은 App Store에 앱을 올리려는 개발자에게 Apple Developer Program 가입을 요구해요. 이것은 Apple이 앱의 품질과 보안을 관리하고, 개발자의 신원을 확인하기 위한 절차예요. 가입하지 않으면 앱을 App Store에 올릴 수 없어요.

비용

  • 연간 $99 (USD), 매년 갱신해야 해요.
  • 갱신하지 않으면 앱이 App Store에서 내려가요.

등록 절차

1단계: Apple ID 준비

이미 Apple ID가 있다면 그것을 사용하면 돼요. 없다면 Apple ID 생성 페이지에서 만드세요.

[주의] 개인 Apple ID와 개발용 Apple ID를 따로 쓰는 분들도 있어요. 하지만 처음이라면 기존 Apple ID를 그대로 사용해도 문제없어요.

2단계: Apple Developer 웹사이트 접속

Apple Developer Programs 에 접속하여 "Enroll" 버튼을 클릭해요.

3단계: 본인 인증 (2단계 인증 필수)

Apple은 보안을 위해 2단계 인증(Two-Factor Authentication)이 활성화된 Apple ID만 Developer Program에 가입할 수 있게 해요. 아직 활성화하지 않았다면:

  1. iPhone 또는 Mac에서 설정 > [내 이름] > 로그인 및 보안 > 이중 인증으로 이동해요.
  2. 이중 인증을 켜요.
  3. 신뢰할 수 있는 전화번호를 등록해요.

4단계: 개인 또는 조직 선택

  • 개인(Individual): 혼자 개발하는 경우. 본인 이름이 App Store에 "판매자"로 표시돼요.
  • 조직(Organization): 회사나 단체 명의로 출시하는 경우. D-U-N-S 번호가 필요해요.

개인 개발자라면 "Individual"을 선택하세요. 조직으로 등록하려면 법인이어야 하고 D-U-N-S 번호가 필요해서 시간이 더 걸려요.

5단계: 신원 확인

개인 등록의 경우, Apple이 본인 확인을 요청할 수 있어요. 최근에는 iPhone 또는 iPad의 Apple Developer 앱을 통해 본인 인증을 진행하는 경우가 많아요.

  1. App Store에서 "Apple Developer" 앱을 설치해요.
  2. Apple ID로 로그인해요.
  3. 앱 내에서 등록 절차를 진행하면 신분증 촬영 등의 본인 인증이 진행돼요.

6단계: 결제

본인 인증이 완료되면 $99를 결제해요. Apple ID에 등록된 결제 수단(신용카드 등)으로 결제돼요.

7단계: 가입 완료 확인

결제가 완료되면 보통 최대 48시간 이내에 계정이 활성화돼요. 활성화되면 App Store Connect에 로그인할 수 있게 돼요.

[팁] Developer Program 가입이 완료되었는지 확인하려면 Apple Developer Account 에 접속해서 "Membership" 섹션을 확인하세요. "Active"라고 표시되면 성공이에요.


2. App Store Connect에서 앱 등록

왜 필요한가요?

App Store Connect는 Apple이 제공하는 앱 관리 웹 포털이에요. 앱의 정보를 입력하고, 빌드를 관리하고, 심사를 제출하고, 매출을 확인하는 모든 작업이 여기서 이루어져요. 빌드를 업로드하기 전에 먼저 여기서 앱을 "등록"해두어야 해요.

번들 ID (Bundle Identifier) 이해하기

번들 ID는 앱의 고유한 식별자예요. 전 세계에서 유일해야 하며, 한 번 정하면 변경할 수 없어요.

  • 형식: 역방향 도메인 표기법 (예: com.yourcompany.yourapp)
  • 예시: com.example.justqr

[주의] 빌드를 올린 뒤에는 번들 ID를 바꿀 수 없어요. 보통 자신이 소유한 도메인을 역순으로 사용해요. 도메인이 없다면 com.본인이름.앱이름 형태로 지정해요.

앱 등록 절차

1단계: App Store Connect 접속

App Store Connect 에 로그인해요.

2단계: "앱" 메뉴에서 새 앱 생성

  1. 좌측 메뉴에서 "앱"을 클릭해요.
  2. 좌측 상단의 "+" 버튼 > "신규 앱"을 클릭해요.

3단계: 앱 기본 정보 입력

다음 정보를 입력해야 해요:

항목설명
플랫폼iOS 선택
이름App Store에 표시될 앱 이름 (최대 30자). 다른 앱과 중복 불가
기본 언어한국어 (Korean) 등 선택
번들 ID위에서 정한 번들 ID 선택 (먼저 Developer 포털에서 등록해야 목록에 나타남)
SKU내부 관리용 ID. 아무 영숫자 조합 가능 (예: justqr_v1)
사용자 액세스"전체 액세스" 선택

[팁] 앱 이름은 App Store 검색에 큰 영향을 줘요. 앱의 핵심 기능을 나타내는 이름을 짓되, 너무 일반적이거나 다른 앱과 겹치지 않도록 하세요.

4단계: 번들 ID를 Developer 포털에서 먼저 등록하기

App Store Connect에서 번들 ID를 선택하려면, 먼저 Apple Developer 포털에서 등록해야 해요:

  1. Apple Developer - Identifiers 에 접속해요.
  2. "+" 버튼을 클릭해요.
  3. "App IDs"를 선택하고 Continue를 눌러요.
  4. Type으로 "App"을 선택해요.
  5. Description에 앱 설명을 입력해요.
  6. Bundle ID에서 "Explicit"을 선택하고 번들 ID를 입력해요.
  7. 필요한 Capabilities(Push Notifications 등)를 체크해요.
  8. Continue > Register를 클릭해요.

이제 App Store Connect에서 앱을 생성할 때 이 번들 ID가 드롭다운 목록에 나타나요.


3. Xcode 서명 설정

왜 서명이 필요한가요?

iOS 앱은 코드 서명(Code Signing)이 되어야만 기기에서 실행될 수 있어요. 이것은 "이 앱은 검증된 개발자가 만들었고, 중간에 누군가 코드를 변조하지 않았다"는 것을 보증하는 역할을 해요. 서명이 없으면 앱 설치도, App Store 업로드도 불가능해요.

필수 개념 정리

서명 설정을 하기 전에, 몇 가지 개념을 이해하면 훨씬 수월해요:

  • 인증서 (Certificate): "나는 Apple이 인정한 개발자예요"를 증명하는 디지털 인증서예요. 개발용(Development)과 배포용(Distribution) 두 종류가 있어요.
  • Provisioning Profile: 인증서, 앱 ID, 그리고 (개발용의 경우) 테스트 기기 목록을 하나로 묶은 파일이에요.
  • Team: Developer Program에 가입한 개발자(또는 조직)를 의미해요.

Xcode에서 자동 서명 설정하기 (추천)

Flutter 프로젝트의 iOS 부분은 Xcode에서 설정해요. 자동 서명을 사용하면 Xcode가 인증서와 Provisioning Profile을 알아서 관리해줘요.

1단계: Xcode에서 iOS 프로젝트 열기

터미널에서 프로젝트 루트 디렉터리로 이동한 후:

Bash
open ios/Runner.xcworkspace

[주의] Runner.xcodeproj가 아니라 반드시 Runner.xcworkspace를 열어야 해요. .xcworkspace를 열어야 CocoaPods 등의 의존성이 제대로 로드돼요.

2단계: 프로젝트 설정으로 이동

  1. Xcode 좌측 파일 탐색기에서 "Runner" 프로젝트를 클릭해요 (가장 위의 파란색 아이콘).
  2. TARGETS 섹션에서 "Runner"를 선택해요.
  3. "Signing & Capabilities" 탭을 클릭해요.

3단계: Team 설정

  1. "Automatically manage signing" 체크박스가 체크되어 있는지 확인해요.
  2. Team 드롭다운에서 자신의 Apple Developer 계정을 선택해요.
    • 목록에 없다면: Xcode 메뉴 > Settings (또는 Preferences) > Accounts에서 Apple ID를 추가하세요.
  3. Team을 선택하면 Xcode가 자동으로 Provisioning Profile과 인증서를 생성/다운로드해요.

4단계: Bundle Identifier 확인

"General" 탭에서 Bundle Identifier가 App Store Connect에서 등록한 번들 ID와 정확히 일치하는지 확인해요.

iOS 번들 ID는 pubspec.yaml에 없고, Xcode 프로젝트 파일(ios/Runner.xcodeproj/project.pbxproj)에 저장돼요. General 탭에서 바꾸면 이 파일에 반영돼요.

5단계: 배포 서명 설정 확인

자동 서명을 쓰면 Build Settings의 Code Signing Identity는 "Apple Development"로 두면 돼요. App Store용 배포 서명은 Archive를 내보낼 때(flutter build ipa도 이 단계를 거쳐요) Xcode가 처리해요.

[주의] 서명 관련 오류가 나타나면 다음을 시도해보세요:

  • Xcode > Settings > Accounts에서 Apple ID를 제거했다가 다시 추가
  • Xcode를 완전히 종료했다가 다시 열기

4. flutter build ipa 릴리스 빌드

왜 릴리스 빌드가 필요한가요?

개발 중에는 Debug 모드로 앱을 실행해요. Debug 모드는 JIT 컴파일로 돌고 assertion과 디버깅 기능이 켜져 있어서 느리고 용량도 커요. App Store에는 AOT 컴파일로 최적화한 Release 빌드를 올려요.

빌드 전 체크리스트

빌드 전에 다음 사항을 확인하세요:

1. 앱 버전과 빌드 번호 확인

pubspec.yaml 파일에서 버전을 확인해요:

YAML
version: 1.0.0+1
  • 1.0.0 부분이 버전 이름 (Version)이에요. 사용자에게 보이는 버전이에요.
  • +1 부분이 빌드 번호 (Build Number)예요. 같은 버전 안에서 빌드마다 달라야 해요.

[주의] 같은 버전으로 한 번 업로드한 빌드 번호는 다시 쓸 수 없어요. 새 빌드를 올릴 때마다 빌드 번호를 올려요. 예: 1.0.0+1 -> 1.0.0+2 -> 1.0.1+3

2. 앱 아이콘 확인

App Store용 1024x1024 아이콘이 없으면 업로드 검증에서 막혀요. 아이콘은 ios/Runner/Assets.xcassets/AppIcon.appiconset/에 있어요. Xcode 14부터는 1024x1024 한 장만 넣고 나머지 크기를 Xcode가 만들게 할 수도 있고, flutter_launcher_icons 패키지로 만들어도 돼요.

3. iOS 최소 배포 버전 확인

ios/Podfile 파일 상단에서 최소 iOS 버전을 확인해요:

Ruby
platform :ios, '13.0'

최신 Flutter는 iOS 13.0 이상을 지원해요. 이보다 낮게 둘 수는 없고, 쓰는 플러그인이 더 높은 버전을 요구하면 그에 맞춰 올려요. 높일수록 지원하는 기기는 줄어들어요.

빌드 실행

터미널에서 다음 명령어를 실행해요:

Bash
flutter build ipa --release

이 명령어가 하는 일:

  1. Dart 코드를 Release 모드로 AOT 컴파일해요 (tree shaking 포함).
  2. Xcode 아카이브(build/ios/archive/Runner.xcarchive)를 만들어요.
  3. 아카이브에서 App Store용 .ipa 파일을 내보내요. 빌드가 성공하면 build/ios/ipa/에 생겨요.

특정 export 방식 지정하기

기본적으로 flutter build ipa는 App Store 배포용으로 빌드해요. 만약 export 옵션을 세밀하게 제어하고 싶다면 export options plist 파일을 사용할 수 있어요:

Bash
flutter build ipa --release --export-options-plist=ios/ExportOptions.plist

하지만 처음이라면 기본 명령어만으로 충분해요.

빌드 오류가 발생할 때

자주 발생하는 오류와 해결법:

오류: "No signing certificate"

Bash
# Xcode에서 서명 설정을 다시 확인하세요.
# 또는 키체인 접근 앱에서 만료된 인증서를 삭제 후 Xcode에서 다시 생성

오류: "Module not found" (CocoaPods 관련)

Bash
cd ios
pod deintegrate
pod install --repo-update
cd ..
flutter clean
flutter build ipa --release

오류: "Minimum deployment target" 관련

Bash
# ios/Podfile에서 최소 iOS 버전을 올려주세요
# platform :ios, '13.0' 또는 그 이상

5. 빌드 업로드

왜 업로드가 필요한가요?

빌드한 .ipa 파일을 Apple 서버에 올려야 App Store Connect에서 이 빌드를 심사에 제출할 수 있어요. 업로드 방법은 크게 두 가지가 있어요.

방법 1: Xcode를 통한 업로드 (Distribute App)

이 방법은 Xcode가 설치되어 있다면 가장 직관적이에요.

절차

  1. Xcode에서 ios/Runner.xcworkspace를 열어요.

  2. 상단 메뉴에서 Product > Archive를 선택해요.

    • 이 메뉴가 비활성화되어 있다면, 빌드 대상을 "Any iOS Device"로 변경하세요 (시뮬레이터가 아닌 실제 기기).
  3. Archive가 완료되면 Organizer 창이 자동으로 열려요.

    • 열리지 않으면: Window > Organizer에서 수동으로 열 수 있어요.
  4. 방금 생성한 Archive를 선택하고 "Distribute App" 버튼을 클릭해요.

  5. 배포 방법으로 "App Store Connect"를 선택해요.

  6. "Upload"를 선택해요 (Export가 아님).

  7. 옵션을 확인해요:

    • "Include bitcode"는 Xcode 14부터 없어졌어요.
    • "Upload your app's symbols"은 체크해두는 것을 추천해요 (크래시 리포트 분석에 필요).
  8. 서명 옵션에서 "Automatically manage signing"을 선택해요.

  9. "Upload"를 클릭하고 완료될 때까지 기다려요.

업로드가 성공하면 "Upload Successful" 메시지가 나타나요.

[참고] flutter build ipa로 이미 .ipa 파일을 만들었다면 Xcode의 Archive 과정을 다시 할 필요 없이, Transporter를 사용하는 것이 더 간편할 수 있어요.

방법 2: Transporter 앱을 통한 업로드 (추천)

Transporter는 Apple이 제공하는 무료 앱으로, .ipa 파일을 드래그 앤 드롭으로 간편하게 업로드할 수 있어요.

절차

  1. Mac App Store에서 "Transporter"를 검색하여 설치해요.

  2. Transporter를 실행하고 Apple ID로 로그인해요.

  3. flutter build ipa로 생성된 .ipa 파일을 찾아요:

Bash
# 빌드 결과물 위치 확인
ls build/ios/ipa/
  1. .ipa 파일을 Transporter 창에 드래그 앤 드롭해요.

  2. Transporter가 파일을 검증(Verify)해요. 문제가 없으면 "Deliver" 버튼을 클릭해요.

  3. 업로드가 완료될 때까지 기다려요.

[팁] Transporter는 업로드 진행률을 보여주고, 오류가 있으면 에러 메시지를 알려줘요.

방법 3: 커맨드라인으로 업로드 (xcrun altool)

터미널에서 App Store Connect API 키로 직접 업로드하는 방법도 있어요. (notarytool은 macOS 앱 공증용이라 App Store 업로드에는 쓰지 않아요.)

Bash
xcrun altool --upload-app --type ios \
  --file build/ios/ipa/YourApp.ipa \
  --apiKey YOUR_API_KEY \
  --apiIssuer YOUR_ISSUER_ID

이 방법은 CI/CD 파이프라인에서 주로 사용하며, 처음 배포하는 분에게는 추천하지 않아요.

업로드 후 처리 과정

업로드가 완료되면 Apple 서버에서 자동 검증 (Processing)이 진행돼요. 이 과정은 보통 5분~30분 정도 걸려요. 처리가 완료되면 등록된 이메일로 결과가 와요.

  • 성공: App Store Connect의 "TestFlight" 탭에서 빌드가 나타나요.
  • 실패: 이메일로 구체적인 오류 사유가 전달돼요.

[주의] 업로드 직후에 App Store Connect에서 빌드가 안 보이는 것은 정상이에요. Processing이 완료될 때까지 기다려주세요.


6. App Store Connect에서 앱 정보 작성

왜 앱 정보가 중요한가요?

App Store에서 사용자가 보는 모든 정보(앱 이름, 설명, 스크린샷 등)는 여기서 입력해요. 이 정보도 심사 대상이에요. 부정확하거나 부적절한 정보는 심사 거절의 원인이 돼요.

앱 정보 작성 항목별 상세 안내

App Store Connect에서 앱을 선택하면 여러 섹션이 있어요. 하나씩 살펴볼게요.

1) 앱 이름과 부제

  • 앱 이름: 최대 30자. App Store에서 검색될 때 사용돼요.
  • 부제 (Subtitle): 최대 30자. 앱 이름 아래에 작게 표시돼요. 핵심 기능을 한 줄로 요약하세요.

2) 설명 (Description)

  • 최대 4,000자.
  • 앱이 무엇을 하는지, 왜 유용한지 명확하게 작성해요.
  • 첫 세 줄이 가장 중요해요 (미리보기에서 보이는 부분).

3) 키워드 (Keywords)

  • 최대 100자 (쉼표로 구분).
  • 사용자가 검색할 만한 단어를 입력해요.
  • 앱 이름에 이미 포함된 단어는 중복하여 넣지 않아도 돼요.

4) 스크린샷

스크린샷은 필수 항목이고, 규격이 정해져 있어요.

기기필요 여부해상도
iPhone 6.9인치 (iPhone 16 Pro Max 등)필수1320 x 2868, 1290 x 2796, 1260 x 2736 px
iPhone 6.5인치 (iPhone 11 Pro Max 등)6.9인치를 안 올리면 필수1284 x 2778, 1242 x 2688 px
iPad 13인치iPad에서 돌아가는 앱이면 필수2064 x 2752, 2048 x 2732 px

[참고] 스크린샷 규격은 Apple의 정책에 따라 변경될 수 있으므로, 항상 App Store Connect의 안내를 확인하세요. 화면 구성이 크기마다 같다면 가장 큰 크기만 올려도 돼요. 작은 기기에는 App Store Connect가 줄여서 써요.

스크린샷 준비 팁:

  • 기기 크기마다 1장부터 최대 10장까지 올릴 수 있어요. 투명도(알파 채널)가 있는 이미지는 안 돼요.
  • 시뮬레이터에서 스크린샷을 찍을 수 있어요: Cmd + S (Xcode 시뮬레이터에서).
  • 스크린샷에 설명 텍스트를 얹으려면 Figma, Canva 같은 도구를 써요.
  • 실제 앱 화면을 반영해야 해요. 앱과 관련 없는 이미지를 사용하면 리젝돼요.

5) 앱 미리보기 동영상 (선택사항)

15~30초 길이의 앱 사용 영상을 올릴 수 있어요. 필수는 아니지만, 앱의 핵심 기능을 효과적으로 보여줄 수 있어요.

6) 카테고리

앱의 주요 카테고리와 보조 카테고리를 선택해요:

  • 주요 카테고리: 앱의 핵심 기능에 맞는 것을 선택 (예: Utilities, Productivity 등)
  • 보조 카테고리: 선택사항이에요.

7) 개인정보처리방침 (Privacy Policy URL)

필수 항목이에요. Apple은 모든 앱에 개인정보처리방침 URL을 요구해요.

  • 웹페이지 형태로 만들어서 URL을 입력해야 해요.
  • 개인 정보를 수집하지 않는 앱이라도 "본 앱은 개인정보를 수집하지 않아요"라는 내용의 페이지가 필요해요.
  • GitHub Pages, Notion, 개인 블로그 등에 무료로 호스팅할 수 있어요.

[주의] 개인정보처리방침이 없으면 심사 제출 자체가 불가능해요. 반드시 미리 준비해두세요.

8) 연령 등급 (Age Rating)

Apple의 설문에 답하면 자동으로 연령 등급이 산정돼요. 질문 예시:

  • 폭력적인 콘텐츠가 있나요?
  • 성인 콘텐츠가 있나요?
  • 도박 요소가 있나요?
  • 사용자 생성 콘텐츠가 있나요?

대부분의 유틸리티 앱은 "4+" 등급을 받아요. 솔직하게 답변하세요. 거짓으로 답변하면 심사에서 거절될 수 있어요.

9) 가격 및 사용 가능 여부

  • 가격: 무료 또는 유료를 선택해요. 유료인 경우 가격대를 선택해요.
  • 사용 가능 여부: 앱을 출시할 국가/지역을 선택해요. 기본적으로 모든 국가가 선택되어 있어요.

10) 앱 심사 정보

  • 연락처 정보: 심사 과정에서 Apple이 연락할 수 있는 이름, 이메일, 전화번호를 입력해요.
  • 로그인 정보: 앱에 로그인이 필요한 경우, 심사팀이 사용할 수 있는 테스트 계정 정보를 제공해야 해요.
  • 메모: 심사팀에게 전달하고 싶은 메모를 남길 수 있어요. 예를 들어, 특정 기능의 사용법 등.

7. TestFlight 베타 테스트

왜 TestFlight를 사용하나요?

TestFlight는 Apple이 제공하는 공식 베타 테스트 도구예요. 앱을 App Store에 정식 출시하기 전에 소수의 테스터에게 먼저 배포하여 버그를 찾고 피드백을 받을 수 있어요.

TestFlight 테스트는 필수는 아니지만 추천해요. 이유는 다음과 같아요:

  • 심사 전에 실제 기기에서 문제가 없는지 확인할 수 있어요.
  • 다양한 iPhone/iPad 모델에서 테스트할 수 있어요.
  • 심사에서 리젝되면 수정 후 재제출하는 데 며칠이 걸리므로, 미리 테스트하는 것이 시간을 절약해요.

내부 테스트 vs 외부 테스트

구분내부 테스트외부 테스트
대상팀 멤버 (최대 100명)일반 사용자 (최대 10,000명)
Apple 심사불필요간단한 베타 심사 필요
초대 방법이메일이메일 또는 공개 링크
소요 시간처리 끝나면 바로베타 심사 통과 후

개인 개발자라면 내부 테스트로 충분해요.

TestFlight 사용 절차

1단계: 빌드 업로드

위의 5단계에서 이미 빌드를 업로드했다면, App Store Connect > TestFlight 탭에서 해당 빌드를 확인할 수 있어요.

2단계: 수출 규정 관련 질문 답변

빌드가 처리되면 수출 규정 준수(Export Compliance) 정보를 입력하라는 표시가 떠요. 미국 수출 규정 때문에 앱이 어떤 암호화를 쓰는지 묻는 질문이에요.

  • HTTPS처럼 iOS가 제공하는 암호화만 쓴다면 대부분 별도 서류가 필요 없는 면제 대상이에요.
  • 자체 구현했거나 표준이 아닌 암호화 알고리즘을 쓴다면 서류가 필요할 수 있어요.

이 질문에 답해야 TestFlight 배포가 활성화돼요.

[팁] 매번 이 질문에 답하는 것이 번거롭다면 ios/Runner/Info.plist에 다음을 추가하면 자동으로 처리돼요:

XML
<key>ITSAppUsesNonExemptEncryption</key>
<false/>

이 설정은 "앱이 면제 대상이 아닌 암호화를 사용하지 않는다"는 의미예요. HTTPS만 사용하는 일반적인 앱이라면 false로 설정해도 돼요.

3단계: 테스터 추가 (내부 테스트)

  1. TestFlight 탭에서 "내부 테스트" 섹션으로 이동해요.
  2. "+" 버튼으로 새 그룹을 만들어요.
  3. 테스터의 Apple ID 이메일을 추가해요.
  4. 테스터에게 초대 이메일이 발송돼요.

내부 테스터는 먼저 App Store Connect의 사용자 및 액세스에서 팀에 추가된 사람이어야 해요.

4단계: 테스터가 앱 설치

  1. 테스터는 App Store에서 "TestFlight" 앱을 설치해요.
  2. 초대 이메일의 링크를 탭하면 TestFlight 앱에서 해당 앱을 설치할 수 있어요.

5단계: 피드백 확인

TestFlight에서 테스터는 스크린샷과 함께 피드백을 보낼 수 있어요. App Store Connect에서 이 피드백을 확인할 수 있어요.


8. 심사 제출 및 주의사항

심사 제출 절차

모든 정보를 입력하고 빌드가 준비되었다면 심사를 제출해요.

1단계: 빌드 선택

App Store Connect > 앱 > 해당 버전 페이지에서:

  1. "빌드" 섹션 옆의 "+" 버튼을 클릭해요.
  2. 업로드한 빌드 중 하나를 선택해요.

2단계: 모든 필수 정보 확인

페이지 상단에 "이 버전을 제출하기 전에 다음 항목을 완료해야 해요"라는 메시지가 있다면, 해당 항목을 모두 완료하세요.

3단계: 심사 제출

모든 항목이 완료되면 "심사를 위해 제출" 버튼이 활성화돼요. 버튼을 클릭하면 심사가 시작돼요.

심사 소요 시간

  • Apple 안내로는 제출의 50% 이상이 24시간 안에, 90%가 48시간 안에 심사돼요.
  • 제출 정보가 빠져 있으면 더 걸리거나 통과하지 못해요.

심사 상태 의미

상태의미
Waiting for Review심사 대기 중
In Review심사 진행 중
Pending Developer Release심사 통과, 개발자가 출시 버튼을 눌러야 함
Ready for Distribution심사 통과, App Store에 공개됨
Rejected심사 거절

주요 리젝 사유와 대처법

자주 나오는 리젝 사유와 대처법이에요.

1) 버그 또는 크래시

사유: 앱이 심사 중에 크래시가 발생하거나 주요 기능이 작동하지 않는 경우.

대처: 다양한 기기와 iOS 버전에서 충분히 테스트하세요. TestFlight를 활용하면 좋아요.

2) 불완전한 앱 정보

사유: 스크린샷이 실제 앱과 다르거나, 설명이 부정확하거나, 개인정보처리방침 URL이 작동하지 않는 경우.

대처: 스크린샷은 최신 버전의 앱 화면을 사용하고, 개인정보처리방침 URL이 정상적으로 접근 가능한지 확인하세요.

3) 로그인 기능 관련

사유: 로그인이 필요한 앱인데 심사용 테스트 계정을 제공하지 않은 경우.

대처: App Store Connect의 "앱 심사 정보" 섹션에 테스트 계정 정보(ID/비밀번호)를 반드시 입력하세요.

4) 최소 기능 요건 (Guideline 4.2)

사유: 앱이 너무 단순하거나 웹사이트를 단순히 감싼 것에 불과한 경우.

대처: 앱이 네이티브 기능을 충분히 활용하고, 웹 페이지를 그대로 보여주는 것 이상의 가치를 제공해야 해요.

5) 개인정보 관련 (Guideline 5.1)

사유: 앱이 수집하는 개인정보에 대한 설명이 부족하거나, App Tracking Transparency 팝업이 없는 경우.

대처: 개인정보를 수집한다면 이유를 명확히 설명하고, 추적 기능을 사용한다면 ATT 프레임워크를 구현하세요.

6) 결제 관련 (Guideline 3.1)

사유: 앱 내 결제를 Apple의 인앱 결제 시스템을 우회하여 처리하는 경우.

대처: 디지털 콘텐츠의 구매는 반드시 Apple의 인앱 결제(StoreKit)를 사용해야 해요.

리젝되었을 때 해야 할 일

  1. 리젝 사유를 읽어요: App Store Connect에서 앱의 App Review 페이지를 열면 제출 내역과 어긴 가이드라인, 심사팀 메시지를 볼 수 있어요.
  2. 필요한 수정을 해요: 사유에 맞게 앱이나 메타데이터를 수정해요.
  3. 질문하거나 이의를 제기할 수 있어요: App Review 페이지에서 심사팀에게 메시지를 보낼 수 있어요. 심사가 잘못됐다고 생각하면 App Review Board에 이의 신청(appeal)을 할 수 있고, 제출 한 건당 한 번이에요.
  4. 수정 후 다시 제출해요: 새 빌드를 업로드하거나, 메타데이터만 수정한 경우 기존 빌드로 재제출할 수 있어요.

9. 자주 하는 실수 / FAQ

자주 하는 실수

실수 1: 빌드 번호를 올리지 않음

증상: "Redundant Binary Upload" 또는 "Build number already used" 오류

해결: pubspec.yaml에서 version: 1.0.0+1의 + 뒤 숫자를 올려주세요. 한 번 사용한 빌드 번호는 재사용할 수 없어요.

실수 2: 앱 아이콘 누락

증상: 업로드할 때 아이콘 누락 오류 (예: 1024x1024 아이콘 없음)

해결: 1024x1024 아이콘을 준비하세요. flutter_launcher_icons 패키지를 사용하면 자동으로 모든 크기를 생성해줘요.

YAML
# pubspec.yaml에 추가
dev_dependencies:
  flutter_launcher_icons: ^0.14.0

flutter_launcher_icons:
  android: true
  ios: true
  image_path: "assets/icon/app_icon.png"
Bash
dart run flutter_launcher_icons

실수 3: 개인정보처리방침 URL 누락 또는 접근 불가

증상: 심사 제출 버튼이 비활성화되거나 리젝됨

해결: 유효한 URL에 개인정보처리방침 페이지를 호스팅하세요. GitHub Pages를 이용하면 무료로 호스팅할 수 있어요.

실수 4: 스크린샷 규격 불일치

증상: 스크린샷을 올릴 때 크기가 맞지 않는다는 오류

해결: 위의 스크린샷 규격 표를 참고하여 정확한 해상도의 스크린샷을 준비하세요. 시뮬레이터에서 해당 기기 모델을 선택하여 스크린샷을 찍으면 정확한 크기로 생성돼요.

실수 5: Release 빌드 테스트 없이 제출

증상: Debug 모드에서는 잘 작동했지만 Release 빌드에서 크래시 발생

해결: Release 빌드는 Debug 빌드와 다르게 동작할 수 있어요 (Tree shaking, AOT 컴파일 등). 반드시 Release 빌드를 실제 기기에서 테스트하거나 TestFlight로 확인하세요.

실수 6: Info.plist 필수 권한 설명 누락

증상: 카메라, 사진 라이브러리 등의 권한을 쓰는데 사용 목적 문자열이 없어서 업로드 때 ITMS-90683 오류가 나거나, 권한을 요청하는 순간 앱이 종료됨

해결: ios/Runner/Info.plist에 권한별 사용 이유를 명시해야 해요:

XML
<!-- 카메라 사용 시 -->
<key>NSCameraUsageDescription</key>
<string>QR 코드를 스캔하기 위해 카메라 접근 권한이 필요합니다.</string>

<!-- 사진 라이브러리 접근 시 -->
<key>NSPhotoLibraryUsageDescription</key>
<string>QR 코드 이미지를 저장하기 위해 사진 라이브러리 접근 권한이 필요합니다.</string>

<!-- 사진 라이브러리 추가 전용 접근 시 -->
<key>NSPhotoLibraryAddUsageDescription</key>
<string>생성된 QR 코드를 사진 앨범에 저장하기 위해 권한이 필요합니다.</string>

[주의] 권한 설명은 반드시 사용자가 이해할 수 있는 구체적인 이유를 적어야 해요. "이 앱에 필요해요" 같은 모호한 설명은 리젝 사유가 돼요.

FAQ

Q: Developer Program 비용 $99는 매년 내야 하나요?

A: 네, 매년 갱신해야 해요. 갱신하지 않으면 앱이 App Store에서 내려가고, 새로운 앱을 업로드할 수 없게 돼요. 이미 다운로드한 사용자는 계속 사용할 수 있지만 업데이트는 받을 수 없어요.

Q: Mac이 없으면 iOS 앱을 출시할 수 없나요?

A: 네, 현재로서는 Mac이 반드시 필요해요. Xcode는 macOS에서만 실행되며, iOS 앱 빌드와 서명에 Xcode가 필요해요. 임시 방편으로 클라우드 Mac 서비스(예: MacStadium, GitHub Actions의 macOS runner)를 사용하는 방법이 있지만, 처음이라면 실제 Mac을 사용하는 것을 추천해요.

Q: 앱 심사에 얼마나 걸리나요?

A: Apple 안내로는 제출의 90%가 48시간 안에 심사돼요. 추가 정보 요청이나 리젝이 있으면 더 걸려요.

Q: 리젝되면 처음부터 다시 해야 하나요?

A: 아니에요. 리젝 사유를 수정한 후 동일한 앱 버전에서 다시 심사를 제출할 수 있어요. 코드 수정이 필요한 경우에만 새 빌드를 업로드하면 돼요.

Q: 무료 앱인데도 $99를 내야 하나요?

A: 네, 무료 앱이든 유료 앱이든 Developer Program 가입비는 동일해요. 이 비용은 앱의 판매 여부와 관계없이 개발자 자격을 유지하기 위한 연회비예요.

Q: 앱을 업데이트할 때도 심사를 받아야 하나요?

A: 네, 모든 업데이트는 심사를 거쳐야 해요.

Q: TestFlight 테스트는 반드시 해야 하나요?

A: 필수는 아니에요. 하지만 심사 전에 실제 기기에서 Release 빌드를 테스트해보는 것은 매우 중요해요. TestFlight가 이를 위한 가장 쉬운 방법이에요.

Q: 시뮬레이터에서 정상 작동하면 실제 기기에서도 괜찮은 건가요?

A: 아니에요. 시뮬레이터에는 카메라처럼 없는 하드웨어가 있고, 위치는 시뮬레이션한 값으로만 테스트돼요. 성능도 실제 기기와 달라요. 실제 기기에서도 테스트하세요.

Q: 앱이 승인된 후 바로 App Store에 공개되나요?

A: 앱 제출 시 출시 방식을 고를 수 있어요. 자동 출시는 심사 통과 즉시 App Store에 공개돼요. 수동 출시는 심사 통과 후 개발자가 직접 "출시" 버튼을 눌러야 공개돼요. 특정 날짜 이후에 자동 출시되도록 날짜를 지정할 수도 있어요.


전체 흐름 요약

아래는 Flutter 앱을 App Store에 출시하는 전체 과정을 한눈에 정리한 거예요:

TEXT
1. Apple Developer Program 가입 ($99/년)
   |
2. Apple Developer 포털에서 App ID (번들 ID) 등록
   |
3. App Store Connect에서 새 앱 생성
   |
4. Xcode에서 서명 설정 (Team, Bundle ID 확인)
   |
5. flutter build ipa --release 로 빌드
   |
6. Transporter 또는 Xcode로 .ipa 파일 업로드
   |
7. App Store Connect에서 앱 정보 작성
   (스크린샷, 설명, 개인정보처리방침 등)
   |
8. (선택) TestFlight로 베타 테스트
   |
9. 심사 제출
   |
10. 심사 통과 -> App Store 출시

업데이트할 때는 pubspec.yaml의 버전과 빌드 번호를 올린 뒤 5~7번(빌드, 업로드, 새로운 기능 문구 작성)과 9번을 반복해요.