Mac App Store (macOS)
Flutter macOS 앱을 Mac App Store 에 올리는 절차를 App Sandbox · 인증서 · flutter build macos · 서명과 패키징 · 업로드 · 심사 제출 순서로 안내하고, Developer ID 직접 배포(공증)와의 차이를 설명합니다.
목차
Flutter macOS 앱을 Mac App Store 로 내는 절차입니다. Apple 계정 하나로 App Store 와 Mac App Store 에 모두 올릴 수 있고, 스토어 등록정보 · 앱이 수집하는 개인정보 · 수출 규정 · 연령 등급 · 심사 제출 · 출시 방식은 App Store (iOS · iPadOS) 편의 10~14단계와 같습니다. 이 페이지는 Mac 에서 달라지는 부분 — App Sandbox, 인증서, 프로비저닝 프로필, .pkg 패키지, 업로드 — 에 집중합니다.
참고
Cocode IDE 로 만든 프로젝트도 Flutter 프로젝트라 같은 절차를 따릅니다. 다만 프로젝트에 macos/ 폴더가 있는지, 서명과 버전 설정을 CI 가 대신하는지는 프로젝트마다 다를 수 있으니 프로젝트의 README 와 CI 설정을 확인하세요.
주의
업로드 요건 · 인증서 이름 · 콘솔 메뉴 이름은 Apple 이 바꿀 수 있습니다. 이 페이지의 수치는 「마지막 확인」 날짜 기준이고, 다르면 Apple 의 공식 문서가 우선합니다. App Store Connect 화면은 로그인이 필요해 직접 확인하지 못했으므로, 메뉴와 버튼 이름 · 각 단계의 성공 판정(화면에 보이는 상태)은 Apple 도움말의 설명을 따랐습니다. 이름은 확인한 범위에서 한국어판 도움말의 표기를 「한글(영문)」으로 적었고, 확인하지 못한 이름은 영문으로 적었습니다(역할 이름은 영문으로 통일했습니다).
준비물
- 끝낸 공통 준비 — 개발자 계정, 식별자와 버전, 아이콘 · 스플래시 · 스크린샷(Mac 스크린샷은 16:10 비율의 규격 크기), 개인정보와 권한.
- Mac 과 Xcode — Flutter 3.47 이 지원하는 macOS 는 Monterey(12) 이상입니다(지원 플랫폼 표). Apple 의 업로드 요건 표는 iOS 앱과 macOS 앱의 Xcode 요건을 따로 적습니다(macOS 앱은 「Xcode 6 or later」). 2026-04-28 부터의 Xcode 26 요건 문장에는 macOS 가 나열되지 않습니다(2026-10-09 확인).
- Mac 에서 시험 — 릴리스
.app을 직접 실행해 네트워크 · 파일 접근이 샌드박스 안에서 되는지 확인합니다(제출 전 체크리스트). - (직접 서명할 때) 인증서와 프로필 — 아래 3단계를 보세요. Apple 도움말의 「필요한 역할」 기준으로 배포 인증서는 Account Holder 또는 Admin 이 만듭니다.
Developer ID 직접 배포와의 차이
Mac 앱은 Mac App Store 로 내거나, Developer ID 로 서명해 스토어 밖(웹사이트 등)에서 직접 배포할 수 있습니다. Flutter 문서도 두 경로를 모두 안내하며, 이 가이드는 Mac App Store 경로입니다. 둘의 차이는 다음과 같습니다.
| 항목 | Mac App Store (이 가이드) | Developer ID 직접 배포 |
|---|---|---|
| 배포와 업데이트 | Apple 이 호스팅하고 업데이트도 Mac App Store 로만 배포해야 합니다(심사 지침 2.4.5(vii)) | 개발자가 직접 관리합니다 |
| App Sandbox(샌드박스) | 필수(Required) | 권장(Recommended). 공증에는 Hardened Runtime 이 필수이고 샌드박스는 선택입니다 |
| 서명 인증서 | 앱은 「Apple 배포(Apple Distribution)」(인증서 목록에는 「Mac 앱 배포(Mac App Distribution)」도 있음), 설치 패키지는 「Mac 설치 프로그램 배포(Mac Installer Distribution)」 | 앱은 「Developer ID 애플리케이션(Developer ID Application)」, 설치 패키지는 「Developer ID 설치 프로그램(Developer ID Installer)」 |
| 검토 | App Review 심사 | 공증(notarization) — 악성 콘텐츠와 서명 문제를 자동 검사하며 App Review 가 아닙니다 |
| 공증 | 필요 없습니다. 스토어 제출 과정에 동등한 보안 점검이 있습니다 | 필요합니다(macOS 10.15 부터 2019-06-01 이후 빌드). xcrun notarytool submit 으로 올리고, 끝나면 티켓을 stapler 로 파일에 붙입니다 |
| 앱 내 구입 · Game Center | 사용할 수 있습니다 | 사용할 수 없습니다 |
| Xcode Organizer 의 배포 방식 | TestFlight & App Store, 또는 Custom → App Store Connect | Direct Distribution, 또는 Custom → Developer ID |
참고
두 경로를 함께 낼 때, codesign 이 적용하는 기본 designated requirement 로 서명한 두 변형(방법 B)은 개인정보 보호 리소스(마이크 등) 접근 권한을 서로 공유하지 못합니다. Xcode 는 서로 호환되는 designated requirement 로 서명해 이 한계를 피합니다. 직접 서명하면서 공유하려면 TN3127 의 방법을 따르세요.
프로젝트에서 바꿀 항목
아래 파일 위치와 기본값은 flutter create 로 만든 Flutter 3.47.6 기본 프로젝트에서 확인한 것입니다(2026-10-09). 프로젝트마다 다를 수 있으니 직접 열어 확인하세요.
| 항목 | 어디서 바꾸나 | 기본값과 메모 |
|---|---|---|
| 앱 이름 | macos/Runner/Configs/AppInfo.xcconfig 의 PRODUCT_NAME |
기본은 프로젝트 이름이며 .app 파일 이름과 기본 창 제목이 됩니다. App Store Connect 의 앱 「이름」과는 따로 입력합니다 |
| 번들 ID | 같은 파일의 PRODUCT_BUNDLE_IDENTIFIER |
기본은 com.example.<프로젝트 이름을 lowerCamelCase 로 바꾼 값> 입니다(예: my_app → com.example.myApp). App Store Connect 에 첫 빌드를 올린 뒤에는 번들 ID 를 바꿀 수 없으니 올리기 전에 정하세요. iOS 앱과 한 앱으로 판매하려면 ios/ 와 같은 번들 ID 를 씁니다 |
| 저작권 | 같은 파일의 PRODUCT_COPYRIGHT |
Info.plist 의 NSHumanReadableCopyright 가 받아 씁니다. macOS 앱은 업로드 전에 이 키를 설정해야 하고, 기본값은 com.example 이 들어간 자리표시자입니다 |
| 앱 카테고리 | Xcode 에서 Runner 타깃 → General → Identity → App Category | 기본 Info.plist 에는 없습니다. Flutter 문서는 「none」일 수 없다고 하고, App Store Connect 의 기본 카테고리와 같거나 가까운 것으로 고릅니다. Xcode 를 열 수 없는 CI 라면 macos/Runner/Info.plist 에 LSApplicationCategoryType 키를 직접 넣습니다 |
| 버전 · 빌드 번호 | pubspec.yaml 의 version: |
Mac 앱의 빌드 번호는 앱의 모든 버전에 걸쳐 계속 올라가야 합니다. 식별자와 버전 |
| 최소 macOS 버전 | Runner 타깃 → General → Deployment Info (프로젝트 파일에서는 MACOSX_DEPLOYMENT_TARGET) |
기본은 12.0 이고 Info.plist 의 LSMinimumSystemVersion 이 받아 씁니다 |
| 샌드박스 · entitlements | macos/Runner/Release.entitlements(릴리스) · macos/Runner/DebugProfile.entitlements(디버그 · 프로파일) |
기본 릴리스 파일에는 com.apple.security.app-sandbox 만 있고, 기본 DebugProfile.entitlements 에는 app-sandbox · cs.allow-jit · network.server 만 있습니다. 네트워크 요청을 하면 두 파일에 com.apple.security.network.client 를 똑같이 더해야 합니다 |
| 권한 사유 문구 | macos/Runner/Info.plist 의 NS…UsageDescription 키 |
기본 템플릿에는 없습니다. 카메라 · 마이크처럼 보호된 리소스는 사유 문구와 샌드박스 entitlement 가 모두 필요하고, 사용자가 대화 상자로 고르는 파일은 files.user-selected.* entitlement 를 씁니다. 개인정보와 권한 |
| 서명 · 팀 | Runner 타깃 → Signing & Capabilities → Automatically manage signing · Team | 기본은 자동 서명입니다 |
| 수출 규정 키 | macos/Runner/Info.plist 의 ITSAppUsesNonExemptEncryption |
기본 템플릿에는 없습니다. 앱이 암호화를 쓰지 않거나 면제되는 암호화만 쓸 때의 설정은 iOS 편 11단계를 보세요 |
| 아이콘 | macos/Runner/Assets.xcassets 의 AppIcon |
아이콘 · 스플래시 · 스크린샷 |
단계
앱 등록과 서명 준비
-
앱 레코드를 정합니다. 계약 상태 확인 · 번들 ID 등록 · 앱 레코드 만들기는 App Store (iOS · iPadOS) 편의 1~3단계와 같고, 플랫폼으로 macOS 를 고릅니다. iOS 앱과 한 번의 구입으로 함께 팔지에 따라 둘 중 하나를 고릅니다.
- iOS 앱과 한 앱으로 판매(유니버설 구입) — 기존 iOS 앱 레코드의 사이드바에서 「플랫폼 추가(Add Platform)」로 macOS 를 더합니다. Xcode 11.4 부터는 한 App ID 로 iOS · macOS 앱을 모두 빌드할 수 있습니다. macOS 앱은 같은 Apple ID · SKU · 번들 ID 를 쓰고,
macos/의 번들 ID 를 iOS 와 같게 맞춥니다. 버전 번호와 빌드 번호는 iOS 와 달라도 됩니다. 플랫폼을 추가하면 기존 플랫폼 버전의 메타데이터가 새 플랫폼 버전으로 옮겨지지만 홍보용 텍스트 · 설명 · 스크린샷은 옮겨지지 않습니다. 아직 앱 레코드가 없다면 「신규 앱」 대화창에서 iOS 와 macOS 를 함께 선택해 한 레코드로 만들 수도 있습니다. - macOS 만 새 앱 레코드 — iOS 편 3단계처럼 「신규 앱」에서 macOS 를 고릅니다.
주의
Apple 은 플랫폼별로 따로 만든 앱 레코드는 합칠 수 없다고 안내합니다. 또 App Review 가 두 플랫폼 버전을 승인하면 유니버설 구입이 되고, 그 뒤에는 앱 레코드에서 플랫폼 버전 하나만 뺄 수 없습니다. 레코드를 만들기 전에 정하세요.
성공 판정 — 앱 레코드에서 macOS 버전 페이지를 열 수 있습니다.
- iOS 앱과 한 앱으로 판매(유니버설 구입) — 기존 iOS 앱 레코드의 사이드바에서 「플랫폼 추가(Add Platform)」로 macOS 를 더합니다. Xcode 11.4 부터는 한 App ID 로 iOS · macOS 앱을 모두 빌드할 수 있습니다. macOS 앱은 같은 Apple ID · SKU · 번들 ID 를 쓰고,
-
샌드박스와 entitlements 를 맞춥니다. Mac App Store 로 내려면 App Sandbox 를 켜야 하고(심사 지침 2.4.5(i)), Flutter macOS 빌드는 기본으로 샌드박스가 적용됩니다. 샌드박스 앱은 네트워크 · 카메라 · 파일 접근 같은 권한을 entitlement 로 밝혀야 하며, 밝히지 않으면 시스템이 런타임에 막습니다. 그래서
macos/Runner/Release.entitlements와macos/Runner/DebugProfile.entitlements두 파일에 앱이 쓰는 권한을 똑같이 더합니다. Flutter 문서는 특별한 이유가 없으면 두 파일을 똑같이 고치라고 하며, 기본DebugProfile.entitlements에도network.client가 없어 디버그 실행에서도 네트워크 요청이 막힙니다(Flutter 3.47.6 에서 확인).<key>com.apple.security.network.client</key> <true/>com.apple.security.network.client는 밖으로 나가는 네트워크 연결을 열어 주며, Flutter 문서는 네트워크 요청을 하는 앱이라면 반드시 더하라고 합니다. 파일 선택기(file_selector)를 쓰면com.apple.security.files.user-selected.read-only나read-write가 필요합니다. 들어오는 연결을 받아야 하면com.apple.security.network.server를 릴리스 파일에도 더합니다(기본은 디버그 · 프로파일에만 켜져 있습니다). 파일을 고칠 때는 Xcode 의 capabilities 화면 대신 파일을 직접 편집하라고 Flutter 문서가 권합니다. 샌드박스의 임시 예외(temporary exception) entitlement 를 쓰는 앱은 그 entitlement 마다 정보를 Apple 에 제공해야 합니다(Apple 도움말 「App Sandbox 정보」). 성공 판정은 릴리스 빌드로 만든 앱에서 네트워크 요청과 파일 열기가 동작하는 것입니다. -
서명을 정합니다. Xcode 로 올린다면(아래 방법 A)
open macos/Runner.xcworkspace로 Runner 타깃의 Signing & Capabilities 에서 Automatically manage signing 을 켜고 Team 을 고르면 됩니다. Apple 은 자동 서명으로 올리면 Xcode 가 배포 프로비저닝 프로필을 관리한다고 안내합니다. 명령줄로 직접 서명한다면(방법 B) 아래를 준비합니다.준비할 것 이름과 만드는 곳 앱 서명 인증서 Apple 의 Mac 배포 서명 문서는 Mac App Store 앱에 「Apple Distribution」 서명 ID( Apple Distribution: <팀 이름> (<팀 ID>))를 쓰라고 합니다. 인증서 개요에는 「Mac App Distribution」(Mac App Store 에 제출하기 전에 Mac 앱에 서명)도 나열됩니다설치 패키지 서명 인증서 「Mac Installer Distribution」. 키체인 이름은 3rd Party Mac Developer Installer: <팀 ID>로 보입니다프로비저닝 프로필 Certificates, Identifiers & Profiles 의 Profiles → 추가 버튼(+) → Distribution 에서 「Mac App Store Connect」(Mac 앱용) → 번들 ID 와 일치하는 App ID → 배포 인증서 → 이름 → Generate → Download. 파일 확장자는 .provisionprofile입니다. 프로필에는 배포 인증서가 하나만 들어가니 앱 서명에 쓸 인증서(Apple Distribution 또는 Mac App Distribution)를 그대로 고르세요Apple 도움말의 「필요한 역할」은 Account Holder 또는 Admin 이고, 배포 인증서는 Developer ID 인증서를 뺀 종류마다 팀당 하나만 허용됩니다. 인증서를 만들 때 필요한 서명 요청(CSR)은 iOS 편 4단계와 같습니다. 성공 판정 — 방법 A 라면 Signing & Capabilities 에 서명 오류가 없습니다. 방법 B 라면 서명 인증서 둘과 프로필 파일(
.provisionprofile)이 준비됐습니다.
빌드와 업로드
-
flutter build macos로 릴리스 빌드를 만듭니다.flutter build macos --build-name=1.0.0 --build-number=1기본이 릴리스 모드이고, 결과 앱은
build/macos/Build/Products/Release/<앱 이름>.app에 생깁니다. 이 앱은 ad hoc 서명이라(Flutter 3.47.6 에서 확인) Mac App Store 에 내려면 Apple 이 요구하는 배포용 서명(distribution-signed)을 입혀야 합니다. 아래 방법 A 나 B 로 입힙니다. Dart 코드를 난독화하려면--obfuscate --split-debug-info=<심볼 폴더>를 함께 줍니다. 성공 판정은 명령이Built build/macos/Build/Products/Release/….app을 출력하는 것입니다. -
방법 A(권장) — Xcode 로 보관(Archive)하고 올립니다. Flutter 문서가 안내하는 경로입니다.
open macos/Runner.xcworkspace로 연 뒤 다음을 합니다.- Runner 타깃 General → Identity 에서 App Category · Bundle Identifier · 버전과 빌드 번호를 확인합니다.
- 메뉴 Product → Archive 로 아카이브를 만듭니다. Archives organizer 에 나타납니다.
- 아카이브를 골라 Validate App 으로 제출 전 자동 검증을 합니다. 문제가 있으면 고쳐 다시 빌드합니다.
- Distribute App 에서 「TestFlight & App Store」(기본 권장 설정)를 고르거나, Custom 에서 「App Store Connect」를 고르고 대상(destination)으로 업로드를 고릅니다. Xcode 가 처리 · 패키징 · 업로드를 시작합니다.
Mac 앱에는 Distribute App 의 Release Testing 과 Enterprise 방식은 쓸 수 없습니다. 성공 판정은 Xcode 가 업로드를 마치고 App Store Connect 앱의 빌드 목록에 빌드가 나타나는 것입니다.
-
방법 B — 명령줄로 서명하고
.pkg를 만들어 올립니다. CI 처럼 Xcode 화면을 쓸 수 없을 때의 경로입니다. Mac App Store 는 앱을 설치 패키지(.pkg) 로 받습니다.주의
이 경로는 서명 · entitlements · 프로파일을 직접 책임집니다. Apple 이 Flutter 앱용으로 완성된 명령 한 벌을 주지는 않아서, 아래는 Apple 문서의 규칙을 순서대로 옮긴 것입니다. 같은 일을 하는 CI 예시는 Flutter 문서의 「Create a build archive with Codemagic CLI tools」 절에 있습니다(서드파티 도구를 씁니다). 막히면 방법 A 를 쓰세요.
-
entitlements 파일을 준비합니다. 배포용
.app에 넣을 entitlements 를 만듭니다. Apple 은 Xcode 로 개발 서명한 앱에서codesign -d --entitlements - --xml <앱> | plutil -convert xml1 -o - -로 entitlements 를 출력해 배포용 파일의 바탕으로 쓸 수 있다고 안내하고, 디버거 연결을 허용하는com.apple.security.get-task-allow는 배포용에는 거의 쓰지 않는다고 합니다. Flutter 가 만든 릴리스.app에서 이렇게 뽑으면com.apple.security.app-sandbox와 함께com.apple.security.get-task-allow가 들어 있습니다(Flutter 3.47.6 에서 확인). 배포용 파일에서는 이 키를 빼는 쪽이 Apple 안내에 맞으니, 2단계에서 정한 앱 권한만 남기세요. 파일은 표준 XML 속성 목록(LF 줄바꿈, 주석 없음, BOM 없음)이어야 합니다. -
배포 프로비저닝 프로필을 앱 번들에 넣습니다. 3단계에서 받은 프로필을
<앱>.app/Contents/embedded.provisionprofile로 복사합니다. 앱 번들을 고치면 서명이 깨지므로 아래 서명 전에 합니다. TestFlight 대상이 되려면 프로비저닝 프로필에 application identifier 가 있어야 합니다. -
com.apple.quarantine확장 속성을 없앱니다. 프로필을 복사한 뒤, 서명과.pkg만들기 전에 합니다. macOS 에서cp·ditto로 복사하면 원본의com.apple.quarantine속성이 복사본에도 붙으므로(macOS 에서 확인) 내려받은 프로필의 속성이 앱 번들로 따라 들어올 수 있습니다.xattr -lr "<앱>.app"으로com.apple.quarantine이 있는지 보고, 있으면xattr -dr com.apple.quarantine "<앱>.app"로 지웁니다. Apple 은 2025-02-18 부터 앱 안의 모든 파일에서 이 속성을 지워야 App Store Connect 에 올릴 수 있다고 안내합니다..pkg를 만든 뒤에 지우면 이미 만든.pkg안에는 속성이 남으니(macOS 에서 확인) 그때는.pkg를 다시 만드세요. -
안쪽 코드부터 서명합니다. 번들 안의 프레임워크 등 모든 실행 코드를 안쪽부터 서명하고 마지막에
.app을 서명합니다. 이미 서명된 코드를 다시 서명하려면-f, 메인 실행 파일에는--entitlements를 더합니다.--deep은 쓰지 말라고 Apple 이 권고합니다. 빌드 산출물.app을 다른 폴더로 옮겨 서명한다면cp -R대신ditto를 쓰세요. ditto 는 Mac 프레임워크 구조에 중요한 심볼릭 링크를 보존합니다.codesign -s "Apple Distribution: <팀 이름> (<팀 ID>)" -f \ "<앱>.app/Contents/Frameworks/<프레임워크>.framework" codesign -s "Apple Distribution: <팀 이름> (<팀 ID>)" -f \ --entitlements "<배포용>.entitlements" "<앱>.app"예시의 서명 ID 이름은 Apple 문서의 표기입니다. 실제 이름은
security find-identity -v출력에서 그대로 복사하고, 같은 이름이 여러 개면 이름 대신 그 줄의 SHA-1 해시로 지정하세요. 성공 판정 —codesign --verify --deep --strict -vv "<앱>.app"가valid on disk와satisfies its Designated Requirement를 출력합니다(서명을 만들 때는--deep을 쓰지 말라는 것이지 검증에는 써도 됩니다). -
.pkg를 만듭니다. 앱 하나뿐이면productbuild의 가장 단순한 형태가 Mac App Store 제출에 충분하다고 Apple 이 안내합니다. Mac App Store 용 패키지는--component방식만 써야 합니다(man productbuild).productbuild --sign "3rd Party Mac Developer Installer: <팀 ID>" \ --component "<앱>.app" /Applications "<앱>.pkg"설치 패키지 서명 ID 는 코드 서명 ID 와 달라서
security find-identity -v로 찾아야 합니다(-p codesigning으로 거르면 나오지 않습니다). 성공 판정 —pkgutil --check-signature "<앱>.pkg"가 설치 패키지 서명 인증서를 보여 줍니다. -
업로드합니다. Apple 은 서명한 설치 패키지를
altool명령줄 도구나 Transporter 앱으로 제출하라고 안내합니다. Transporter 는 Mac App Store 에서 받는 macOS 앱입니다. 명령줄은 iOS 편 7단계와 같은 방식(API 키 또는 사용자 이름과 앱 암호)으로 인증하고, 형식은 다음과 같습니다.xcrun altool --upload-package "<앱>.pkg" \ --apple-id <앱의 Apple ID> --bundle-id <번들 ID> \ --bundle-short-version-string <버전> --bundle-version <빌드 번호> \ --apiKey <키 ID> --apiIssuer <발급자 ID>--upload-app형식의 deprecated 안내와 옵션 이름 확인은 iOS 편 7단계의 알림을 따르세요.-t(플랫폼)는 선택 사항이며(altool 가이드) 값 이름이 가이드(osx · ios · appletvos)와 Xcode 27.0 의altool --help(macos · ios · appletvos · visionos)에서 다르니 쓰려면 도움말로 확인하세요.
성공 판정 — 방법 B 의 각 명령이 오류 없이 끝나고, 업로드 도구가 끝난 뒤 7단계에서 빌드가 나타납니다.
-
시험과 출시
- 처리를 기다리고 TestFlight 로 시험합니다. 처리가 끝나면 이메일이 오고 빌드가 나타납니다. TestFlight 는 Mac 앱도 지원하며, Mac 용 TestFlight 를 쓰려면 macOS 앱을 Xcode 13 이상으로 빌드하라고 Apple 이 안내합니다. 빌드가 TestFlight 대상이 되려면 프로비저닝 프로필 안에 application identifier 가 있어야 합니다. 내부 · 외부 테스트 방법은 iOS 편 8~9단계와 같습니다. App Store 로 내기 전에 Apple 이 공증한 빌드를 직접 나눠 줘 시험할 수도 있습니다. 성공 판정 — 빌드가 앱의 TestFlight 탭에 나타나고 테스터가 설치해 실행합니다.
- 심사에 제출하고 출시합니다. iOS 편 10~14단계와 같은 항목을 채우고 빌드를 골라 제출합니다. 이름 · 연령 등급처럼 플랫폼이 함께 쓰는 앱 정보는 앱 레코드에 한 번만 채우고, 지원 URL · 저작권 · 앱 심사 정보 · 버전 출시 설정 같은 버전 정보는 macOS 버전 페이지에서 채웁니다(Apple 의 필수 속성 표). 플랫폼마다 앱 버전을 따로 제출하고, 한 플랫폼 버전의 상태가 다른 플랫폼 버전의 상태에 영향을 주지 않습니다. 수동 출시를 골랐다면 macOS 버전도 따로 「이 버전 출시」를 눌러야 합니다. 성공 판정 — macOS 버전의 상태가 「심사 대기 중」으로 바뀝니다.
확인
- 샌드박스: 릴리스
.app에서codesign -d --entitlements - <앱>출력에com.apple.security.app-sandbox가true로 있습니다. 앱을 실행한 뒤 Activity Monitor 의 View → Columns → Sandbox 열에서 앱이 「Yes」입니다. - 권한: 릴리스 빌드에서 네트워크 요청 · 파일 열기 같은 기능이 동작합니다.
- 업로드: 앱의 빌드 목록(TestFlight 탭)에 macOS 빌드가 나타나고 빌드 번호가 방금 올린 값과 같습니다.
- 제출: macOS 버전의 상태가 「심사 대기 중」으로 바뀌었습니다. 심사가 시작되면 「심사 중」이 됩니다.
- 출시: 상태가 「배포 준비됨(Ready for Distribution)」이고 Mac App Store 에서 앱 제품 페이지가 열립니다.
자주 겪는 문제
네트워크 요청이 「Operation not permitted」 오류로 실패합니다
샌드박스 앱은 com.apple.security.network.client entitlement 가 없으면 SocketException: Connection failed (OS Error: Operation not permitted, errno = 1) 같은 메시지로 요청이 막힌다고 Flutter 문서가 예시합니다. 기본 템플릿은 DebugProfile.entitlements 에도 이 키가 없어 디버그 실행에서도 같은 오류가 납니다(Flutter 3.47.6 에서 확인). 릴리스 빌드에서만 실패한다면 DebugProfile.entitlements 에만 키를 더하고 Release.entitlements 는 놓친 경우입니다. 두 파일에 위 2단계의 키를 똑같이 더하세요. Flutter 문서 본문은 파일 이름을 Runner-Release.entitlements 처럼 적지만 Flutter 3.47.6 기본 템플릿의 이름은 Release.entitlements 입니다. 프로젝트의 macos/Runner/ 폴더에서 실제 *.entitlements 이름을 확인하세요.
업로드가 quarantine 속성 때문에 거부됩니다
Apple 은 macOS 앱에 com.apple.quarantine 확장 파일 속성이 있으면 안 되고, 2025-02-18 부터 앱 안의 모든 파일에서 이 속성을 지워야 App Store Connect 에 올릴 수 있다고 안내합니다. 인터넷에서 받은 파일(예: 내려받은 프로비저닝 프로필)이 앱 번들에 섞였는지 확인하세요. macOS 에 포함된 xattr 도움말 기준으로 xattr -lr <앱>.app 은 확장 속성을 나열하고, xattr -dr com.apple.quarantine <앱>.app 은 그 속성을 지웁니다. 속성을 지운 뒤에는 .pkg 를 다시 만들어 올리세요. 이미 만든 .pkg 안의 앱에는 속성이 남아 있습니다(macOS 에서 확인).
앱 카테고리는 어디서 정하나요?
Mac 앱은 App Store Connect 의 카테고리와 별도로 Xcode 프로젝트에서도 카테고리를 정합니다. Runner 타깃의 General → Identity → App Category 에서 App Store Connect 의 기본 카테고리와 같거나 가까운 것으로 고르세요. Flutter 문서는 이 값이 none 일 수 없다고 하고, 보관된(retired) Apple 문서는 Mac App Store 에 제출하려면 Info.plist 최상위에 LSApplicationCategoryType 키로 카테고리를 정의해야 한다고 안내합니다(값은 public.app-category.business 같은 UTI). Xcode 를 열 수 없는 CI 라면 macos/Runner/Info.plist 에 이 키를 직접 넣습니다.
TestFlight 에서 빌드를 쓸 수 없다고 나옵니다
프로비저닝 프로필에 application identifier 가 빠진 빌드는 TestFlight 에서 쓸 수 없고 「테스트할 버전이 준비되지 않음(Not Available for Testing)」으로 보입니다. 식별자가 포함된 새 빌드를 올려야 합니다. 자동 서명이면 Xcode 가 배포 프로비저닝 프로필을 관리해 주고, 수동 서명이면 위 방법 B 의 2번처럼 직접 넣습니다.
심사에서 2.4.5 (Mac App Store 요구 사항) 로 거절됐습니다
Mac App Store 앱에는 심사 지침 2.4.5 의 추가 요구 사항이 있습니다.
- (i) 적절히 샌드박스되어야 하고 macOS 파일 시스템 문서를 따라야 합니다.
- (ii) Xcode 가 제공하는 기술로 패키징 · 제출해야 하고, 서드파티 설치 프로그램은 쓸 수 없습니다. 독립적인 단일 앱 설치 번들이어야 하고 공유 위치에 코드나 리소스를 설치할 수 없습니다.
- (iii) 동의 없이 시동 · 로그인 때 자동 실행되거나 코드를 돌리면 안 되고, 사용자가 앱을 종료한 뒤에도 동의 없이 계속 실행되는 프로세스를 만들면 안 됩니다. 또 Dock 에 아이콘을 자동으로 추가하거나 데스크탑에 바로 가기를 남기지 않아야 합니다.
- (iv) 심사 때 본 것과 달리 기능을 바꾸는 독립 앱 · kext · 추가 코드 · 리소스를 내려받아 설치하면 안 됩니다.
- (v) 루트 권한 상승을 요청하거나 setuid 속성을 쓰면 안 됩니다.
- (vi) 실행 시 사용권 화면을 보이거나 라이선스 키를 요구하거나 자체 복사 방지를 구현하면 안 됩니다.
- (vii) 업데이트는 Mac App Store 로만 배포해야 합니다. 다른 업데이트 방식은 허용되지 않습니다.
- (viii) 현재 출시된 OS 에서 실행되어야 하고, deprecated 되었거나 선택 설치되는 기술(예: Java)을 쓰면 안 됩니다.
- (ix) 모든 언어와 현지화를 하나의 앱 번들 안에 담아야 합니다.
그 밖의 거절 사유(2.1 · 4.x · 5.1.1)와 답하는 방법은 App Store (iOS · iPadOS) 편의 「자주 겪는 문제」와 같습니다. 스토어별 사유와 번호, 재제출 방법은 심사 거절 대응에도 모았습니다.
한 앱 레코드로 합칠 수 있나요? 이미 iOS 와 macOS 를 따로 냈습니다
Apple 은 플랫폼별로 따로 만든 앱 레코드는 합칠 수 없다고 안내합니다. 유니버설 구입을 하려면 한 레코드만 남기고 나머지를 판매 중단한 뒤 그 레코드에 플랫폼을 더해야 하는데, 판매 중단한 앱의 원래 제품 페이지는 쓸 수 없게 되고 기존 사용자에게 업데이트를 줄 수 없으며 평점과 리뷰도 옮겨지지 않는다고 Apple 이 설명합니다.
Intel Mac 지원을 끊어도 되나요?
Apple 은 2026-09-09 소식에서 macOS 26 이 Intel Mac 과 Rosetta 를 지원하는 마지막 릴리스이고 macOS 27 은 Apple silicon 전용이라고 밝혔습니다. Apple silicon 만 지원하려면 Xcode 의 빌드 아키텍처를 arm64 전용으로 하고 다시 빌드해 제출하라고 안내합니다. App Store Connect 릴리스 노트(2026-06-18)는 최소 시스템 버전이 13 이상인 유니버설 macOS 앱이 x86_64 아키텍처를 빼고 Intel Mac 지원을 중단한 채 Mac App Store 에 올릴 수 있다고 알립니다. Flutter 3.47.6 기본 템플릿의 최소 macOS 는 12.0 이므로 arm64 전용으로 줄이려면 13 이상으로 올려야 할 수 있습니다. Flutter 도 Intel(x64) 지원을 단계적으로 줄이는 중이라고 지원 플랫폼 표에서 알립니다. Flutter 3.47.6 의 flutter build macos 는 기본으로 x86_64 와 arm64 를 함께 담은 universal 앱을 만듭니다. Apple silicon 전용으로 만들려면 flutter config --enable-macos-arm64-only 를 켠 뒤 다시 빌드하세요(Flutter 도구의 안내이며 기본값은 앞으로 바뀔 수 있습니다). 업로드 요건으로 못 박은 문장은 확인하지 못했으니, 지원 대상 Mac 은 직접 정하세요.
다음 단계
Mac 앱까지 준비됐다면 제출 직전에 제출 전 체크리스트의 Mac App Store 구역을 훑으세요. iPhone · iPad 앱은 App Store (iOS · iPadOS) 편에서, 다른 스토어는 스토어별 안내에서 고릅니다. 출시한 뒤의 업데이트와 거절 대응은 출시 후 운영에서 다룹니다.
출처
- developer.apple.com/macos/distribution
- developer.apple.com/app-store/review/guidelines
- developer.apple.com/documentation/xcode/preparing-your-app-for-distribution
- developer.apple.com/documentation/xcode/configuring-the-macos-app-sandbox
- developer.apple.com/documentation/bundleresources/entitlements/com.apple.security.app-sandbox
- developer.apple.com/documentation/bundleresources/entitlements/com.apple.security.network.client
- developer.apple.com/documentation/bundleresources/entitlements/com.apple.security.files.user-selected.read-write
- developer.apple.com/help/app-store-connect/reference/app-uploads/app-sandbox-information
- developer.apple.com/help/account/certificates/certificates-overview
- developer.apple.com/help/account/provisioning-profiles/create-an-app-store-provisioning-profile
- developer.apple.com/help/account/identifiers/register-an-app-id
- developer.apple.com/documentation/xcode/creating-distribution-signed-code-for-the-mac
- developer.apple.com/documentation/xcode/packaging-mac-software-for-distribution
- developer.apple.com/documentation/xcode/distributing-your-app-for-beta-testing-and-releases
- developer.apple.com/help/app-store-connect/create-an-app-record/add-platforms
- developer.apple.com/help/app-store-connect/manage-builds/upload-builds
- help.apple.com/asc/appsaltool/en.lproj/static.html
- help.apple.com/itc/transporteruserguide/en.lproj/static.html
- developer.apple.com/help/app-store-connect/test-a-beta-version/testflight-overview
- developer.apple.com/documentation/bundleresources/information-property-list/cfbundleversion
- developer.apple.com/news/upcoming-requirements
- developer.apple.com/news/?id=k1mtkt1k
- developer.apple.com/help/app-store-connect/release-notes
- developer.apple.com/documentation/security/notarizing-macos-software-before-distribution
- developer.apple.com/library/archive/releasenotes/General/SubmittingToMacAppStore/index.html
- docs.flutter.dev/deployment/macos
- docs.flutter.dev/platform-integration/macos/building
- docs.flutter.dev/reference/supported-platforms
- docs.flutter.dev/deployment/obfuscate
- developer.apple.com/programs/whats-included
- developer.apple.com/documentation/security/customizing-the-notarization-workflow
- developer.apple.com/documentation/technotes/tn3127-inside-code-signing-requirements
- developer.apple.com/documentation/bundleresources/information-property-list/lsapplicationcategorytype
- developer.apple.com/help/app-store-connect/create-an-app-record/add-a-new-app
- developer.apple.com/help/app-store-connect/manage-submissions-to-app-review/overview-of-submitting-for-review
- developer.apple.com/help/app-store-connect/manage-your-apps-availability/select-an-app-store-version-release-option
- developer.apple.com/help/app-store-connect/reference/app-uploads/app-build-statuses