문서 검색

Google Play (Android)

Play Console 에서 앱을 만들고, 업로드 키로 서명한 앱 번들을 올려 내부 · 비공개 테스트를 거쳐 프로덕션에 출시하는 순서를 안내합니다. 신규 개인 계정의 테스트 요건과 타깃 API · 16KB 메모리 페이지 크기 요건을 날짜와 함께 정리했습니다.

마지막 확인:
목차

Flutter 앱을 Google Play 에 올리는 순서를 안내합니다. Play Console 에서 앱을 만들고, 업로드 키로 서명한 앱 번들(.aab)을 올려 테스트한 뒤 프로덕션에 출시하는 흐름입니다. 새 앱은 앱 번들로 올립니다. Play Console 도움말은 2021년 8월 이전에 만든 기존 앱만 APK 도 쓸 수 있다고 안내합니다.

참고

이 페이지의 파일 위치는 Flutter 가 기본으로 만드는 프로젝트(android/) 기준입니다. Cocode IDE 로 만든 프로젝트도 Flutter 프로젝트라 같은 절차를 따르지만, android/ 폴더가 어떻게 있는지, 서명과 버전 설정을 CI 가 대신하는지는 프로젝트마다 다를 수 있으니 프로젝트의 README 와 CI 설정을 확인하세요.

주의

Google Play 의 요건은 자주 바뀝니다. 이 페이지의 날짜와 수치는 「마지막 확인」 날짜 기준이고, 다르면 Google 의 공식 문서가 우선합니다. Play Console 화면은 로그인이 필요해 직접 확인하지 못했으므로, 메뉴와 버튼 이름 · 각 단계의 성공 판정(화면에 보이는 상태)은 Play Console 도움말의 설명을 따랐습니다. 이름은 확인한 범위에서 한국어판 도움말의 표기를 「한글(영문)」으로 적었고, 확인하지 못한 이름은 영문으로 적었습니다(역할 이름은 영문으로 적었습니다). 한국어 도움말에는 AI 번역이 포함될 수 있다고 Google 이 안내합니다.

준비물

  • Play Console 개발자 계정 — 개인 또는 조직 계정을 만들고 신원 확인을 마친 상태입니다. 신원 확인은 Google 결제 프로필(Google Payments profile)로 하고, 프로필이 아직 확인되지 않았다면 개인은 정부가 발급한 신분증을, 조직은 D-U-N-S 번호(Google 이 알려진 정부 조직 · 기관으로 인정한 계정은 제외) · 신분증 · 조직 서류를 Play Console 에서 제출합니다. D-U-N-S 번호는 새로 신청하면 최대 30일이 걸릴 수 있다고 Google 이 안내하므로 조직 계정이면 가장 먼저 준비하세요. 계정 종류 · 서류 · 비용은 개발자 계정을 보세요.
  • (신규 개인 계정) 실기기 인증 — 새 개인 계정은 Play Console 모바일 앱으로 실제 Android 기기를 가졌는지 인증해야 앱을 Google Play 에 낼 수 있습니다. 웹 Play Console 홈의 「Android 휴대기기에 액세스할 수 있는지 확인(Verify that you have access to an Android mobile device)」 작업에서 QR 코드로 시작합니다. 루팅하지 않은 Android 10 이상의 실기기면 되고 1분 안에 끝난다고 Google 이 안내합니다. 계정을 만든 Google 계정(Account Owner)으로 로그인해야 합니다.
  • 정해 둔 식별자와 버전 — applicationId(패키지 이름)와 버전을 식별자와 버전에서 정해 둡니다. com.example… 기본값이 남아 있으면 안 됩니다.
  • 스토어 등록정보 자료 — 앱 아이콘 · 그래픽 이미지 · 스크린샷 · 간단한 설명을 아이콘 · 스플래시 · 스크린샷의 규격대로 준비합니다.
  • 개인정보 처리방침 주소와 데이터 목록 — 개인정보와 권한에서 정리한 방침 URL 과, 앱(SDK 포함)이 수집하는 데이터 목록입니다.
  • 개발 환경 — Flutter SDK 와 Android 도구(flutter doctor 로 점검)가 있어야 하고, 키를 만들 Java 의 keytool 이 필요합니다. keytool 은 Android Studio 와 함께 설치되는 Java 에 있고, PATH 에 없으면 flutter doctor -v 의 「Java binary at:」 경로에서 맨 끝의 java 를 keytool 로 바꿔 씁니다.
  • (로그인이 있는 앱) 심사용 계정 — 심사자가 앱의 모든 기능을 쓸 수 있는, 언제나 유효하고 재사용할 수 있는 계정입니다.
  • (신규 개인 계정) 테스터 12명 이상 — Google 계정이 있는 사람이어야 합니다. 아래 「신규 개인 계정의 비공개 테스트 요건」을 보세요.

신규 개인 계정의 비공개 테스트 요건

2023-11-13 이후에 만든 개인 계정은 프로덕션에 앱을 올리기 전에 비공개 테스트(Closed testing)를 거쳐야 합니다(2026-10-09 확인). 출시 일정에 가장 크게 영향을 주는 값이라 먼저 설명합니다. 이 요건은 위 계정에 적용됩니다. 다른 계정에도 Google 은 출시 전에 테스트 트랙을 쓰기를 권장합니다.

항목 내용
인원 비공개 테스트에 12명 이상이 참여(옵트인)한 상태여야 합니다
기간 그 테스터들이 연속 14일 이상 옵트인을 유지해야 합니다. 14일을 채우기 전에 옵트아웃한 테스터는 세지 않고, 나갔다가 다시 들어오면 그 14일이 연속이어야 합니다
요건을 채우기 전 프로덕션(테스트 및 출시 → 프로덕션)과 사전 등록 기능이 꺼져 있습니다. 공개 테스트는 프로덕션 액세스를 얻은 뒤에 쓸 수 있습니다
신청 방법 대시보드(Dashboard)의 「프로덕션 신청(Apply for production)」을 눌러 질문에 답합니다
검토 보통 7일 이하이고 가끔 더 걸립니다. 결과는 Account Owner 의 이메일로 옵니다. 테스터가 12명 미만이거나 참여가 부족하면 비공개 테스트를 더 이어 가라는 안내를 받을 수 있습니다

신청서는 세 부분입니다.

  • 비공개 테스트 정보(About your closed test) — 테스터를 모으기 쉬웠는지, 테스터가 모든 기능을 써 봤는지와 실제 사용과 같았는지, 받은 의견의 요약과 수집 방법을 적습니다.
  • 앱/게임 정보(About your app/game) — 타겟층, 앱이 사용자에게 주는 가치, 출시 첫해 예상 설치 범위를 적습니다. 이 답변은 Google Play 에 공개되지 않고 앱 공개 상태나 Play Console 기능 접근에 영향을 주지 않는다고 Google 이 안내합니다.
  • 프로덕션 준비 상태 정보(About your production readiness) — 테스트에서 알게 된 내용으로 앱을 어떻게 바꿨는지, 프로덕션 준비를 마쳤다고 판단한 근거를 적습니다.

각 부분 끝의 「다음(Next)」과 마지막 「적용(Apply)」을 누르지 않고 나가면 입력한 내용이 저장되지 않습니다.

팁

연속 14일이 걸리는 일정이므로 개발 막바지에 몰아서 하지 마세요. 비공개 테스트는 앱 설정(8~9단계)을 마쳐야 시작할 수 있으니, 첫 빌드가 나오면 6~9단계를 서둘러 끝내고 그동안 테스터 명단을 미리 모아 두세요. 일정은 비공개 테스트 버전의 검토(몇 시간에서 최대 7일, 예외적으로 더) → 연속 14일 → 프로덕션 신청 검토(보통 7일 이하) → 프로덕션 버전의 검토(몇 시간에서 최대 7일) 순으로 이어지니 출시일에서 거꾸로 세어 잡으세요. 테스터에게 「최소 14일은 옵트인을 유지해 달라」고 미리 알리고, 받은 의견은 신청서에 요약해야 하니 기록해 두세요. 이 값은 Google 이 바꿀 수 있으므로 공식 안내에서 현재 값을 확인합니다.

타깃 API 수준과 16KB 요건

스토어가 날짜를 정해 둔 빌드 요건 두 가지입니다. 값은 모두 2026-10-09 확인 기준입니다.

타깃 API 수준

  • 신규 앱과 앱 업데이트 — 2026-08-31 부터 Android 16(API 수준 36) 이상을 타깃해야 Google Play 에 제출할 수 있습니다(한국어 도움말은 「대상 API 수준」이라고 부릅니다). 앱 번들을 올릴 때도 이 요건을 충족해야 합니다.
  • 기존 앱 — 같은 날부터 Android 15(API 수준 35) 이상을 타깃해야 자기 타깃보다 높은 Android 버전을 쓰는 기기의 새 사용자에게 계속 보입니다. 그보다 낮게 타깃하면 앱의 타깃과 같거나 낮은 Android 버전의 기기에서만 제공됩니다. 이전에 Google Play 에서 앱을 설치한 사용자는 영향을 받지 않고, 앱이 지원하는 모든 Android 버전에서 다시 설치하고 쓸 수 있습니다.
  • 연장 — 이미 게시된 앱이 위 기준을 충족하지 못하면 Play Console 에 정책 경고와 알림이 옵니다. 앱을 더 높은 타깃으로 올릴 계획이면 정책 상태(Policy status) 페이지의 경고 상세에서 양식을 받아, 2026-11-01 까지 모든 사용자에게 계속 배포되도록 연장을 요청할 수 있다고 Google 이 안내합니다. 공식 문서는 기존 앱도 업데이트할 때는 API 수준 36 이상을 타깃하라고 적지만 연장 기간에 36 미만을 타깃한 업데이트를 받아 주는지는 분명히 밝히지 않으니, 새 앱과 업데이트는 36 이상으로 준비하는 것이 안전합니다.
  • 예외와 다른 기기 — 특정 조직 안에서만 쓰는 영구 비공개 앱은 예외입니다. Wear OS · Android TV · Android Automotive OS · Android XR 앱은 기준이 다르니 Google 의 도움말을 보세요.

Flutter 프로젝트의 타깃 SDK 는 android/app/build.gradle.kts 의 targetSdk = flutter.targetSdkVersion 처럼 Flutter 가 정하는 기본값입니다. flutter. 로 시작하는 값은 Flutter Gradle 플러그인에서 오고, Flutter 를 올리면 함께 바뀔 수 있습니다. 숫자로 고정했다면 요건에 맞게 직접 올려야 합니다. Flutter 3.47.6 의 기본값은 36 이고(아래 「프로젝트에서 바꿀 항목」), Flutter 3.35.0 릴리스 노트에는 프레임워크의 기본 TargetSdk 를 36 으로 올렸다는 항목이 있습니다. 어느 버전이든 프로젝트의 실제 값은 아래 5단계에서 빌드 결과로 확인합니다.

16KB 메모리 페이지 크기

Android 15 부터 메모리 페이지 크기가 16KB 로 설정된 기기가 지원됩니다. 네이티브(NDK) 코드를 직접 쓰거나 SDK 를 통해 쓰는 앱은 다시 빌드해야 이런 기기에서 동작합니다. Java 나 Kotlin 코드만 쓰는 앱은 이미 지원합니다.

  • 대상 — Android 15(API 수준 35) 이상을 타깃하는 모든 앱이 Google Play 에서 64비트 기기의 16KB 페이지 크기를 지원해야 합니다. Flutter 앱은 엔진이 네이티브 라이브러리(libflutter.so)이므로 확인 대상으로 보세요.
  • 시행일 — 2027-02-01 부터 16KB 를 지원하지 않는 앱 업데이트는 출시할 수 없습니다(Android 개발자 문서, 2026-09-16 갱신). Play Console 기술 품질 요건 문서는 네이티브 코드가 있는 앱의 16KB 지원을 이미 적용 중인 요건으로 올려 두었습니다. 문서마다 표현이 달라 보이므로 지금부터 지원하는 빌드만 올리는 것이 안전합니다.
  • 고치는 방법 — Android Gradle 플러그인(AGP) 8.5.1 이상과 NDK r28 이상, 16KB 호환 프리빌트 라이브러리를 쓰면 기본으로 호환된다고 Google 이 안내합니다. 직접 만든 네이티브 코드를 NDK r27 이하로 빌드한다면 링커 옵션 -Wl,-z,max-page-size=16384 와 -Wl,-z,common-page-size=16384 를 줘야 합니다.

어디를 보나 — Flutter · NDK · AGP 버전은 아래 위치에서 확인합니다.

확인 대상 어디서 보나 기준
Flutter 버전 flutter --version NDK · 타깃 SDK 같은 flutter. 기본값이 Flutter 버전마다 다르므로, Flutter 를 올린 뒤에는 아래 점검을 다시 합니다. Flutter 3.47.6 으로 만든 빈 앱의 arm64-v8a libflutter.so · libapp.so 는 LOAD 정렬이 2**16 이었고 zipalign 검사도 통과했습니다(2026-10-09 직접 확인)
NDK 버전 android/app/build.gradle.kts 의 ndkVersion = flutter.ndkVersion(Flutter 가 정하는 값). 설치된 버전은 Android SDK 의 ndk 폴더 아래 28.2.13676358 같은 숫자 이름 폴더 NDK 로 직접 컴파일하는 네이티브 코드에만 영향을 줍니다. r28 이상이면 16KB 정렬로 컴파일되고, Flutter 3.47.6 의 기본값은 28.2.13676358(r28)입니다. 미리 빌드되어 들어오는 .so(Flutter 엔진 · 플러그인과 SDK 가 싣는 것)는 이 설정이 아니라 Flutter · 플러그인 · SDK 버전에 달려 있습니다
AGP 버전 android/settings.gradle.kts 의 com.android.application 플러그인 버전(Flutter 3.47.6 템플릿은 9.1.0) 8.5.1 이상. 8.3~8.5 는 기본 정렬이 16KB 지만 bundletool 이 APK 를 zipalign 하지 않아, 로컬에서는 되는 듯해도 Play 에서 번들로 만든 APK 는 설치되지 않을 수 있다고 Android 문서가 안내합니다
네이티브 라이브러리를 싣는 플러그인 빌드한 APK 를 「Build → Analyze APK…」로 열었을 때 lib 폴더에 보이는 .so 와, 그것을 싣는 플러그인(다른 플러그인이 끌어오는 것 포함) 각 SDK 제공사가 16KB 지원 버전을 안내하는지 확인합니다
결과물 빌드한 APK 와 번들 아래 점검 명령으로 정렬 여부를 직접 확인합니다

결과물은 이렇게 점검합니다. 명령은 5단계에서 다시 나옵니다. zipalign 은 ZIP 안의 위치를, ELF 점검은 라이브러리 내부의 정렬을 보므로 서로 대신할 수 없습니다.

  • Android Studio — 「Build → Analyze APK…」로 APK 를 열고 lib 폴더의 .so 파일에 정렬(Alignment) 경고가 없는지 봅니다.
  • zipalign — zipalign -v -c -P 16 4 <APK 파일> 의 마지막 줄이 Verification successful 이어야 합니다(Android SDK Build-Tools 35.0.0 이상).
  • ELF 정렬 — APK 를 풀고(macOS · Linux 는 unzip <APK 파일> -d <폴더>, Windows PowerShell 은 Expand-Archive) lib 아래 arm64-v8a · x86_64 .so 파일마다 llvm-objdump -p <파일>.so | grep LOAD 를 실행합니다(Windows PowerShell 은 llvm-objdump.exe -p <파일>.so | Select-String -Pattern "LOAD"). 출력의 LOAD 줄이 모두 align 2**14 이상이어야 하고, 2**13 · 2**12 처럼 작으면 다시 빌드해야 합니다. llvm-objdump 는 NDK 의 toolchains/llvm/prebuilt/<호스트>/bin 폴더에 있습니다. Linux 와 macOS 에서는 Android 개발자 문서의 check_elf_alignment.sh 스크립트로 한 번에 볼 수 있습니다.
  • 번들 — bundletool dump config --bundle=<AAB 파일> 결과에 PAGE_ALIGNMENT_16K 가 보여야 합니다. PAGE_ALIGNMENT_4K 이면 4KB 정렬을 요청하는 번들입니다. bundletool은 공식 문서의 안내에 따라 따로 내려받는 도구입니다.
  • 기기 — 16KB 환경에서 앱을 직접 써 봅니다. 16KB 시스템 이미지를 쓰는 Android 에뮬레이터, 또는 일부 Pixel 기기(Pixel 8 · 8 Pro · 8a · 9 · 9 Pro · 9 Pro XL · 9a — 모델마다 OS 버전 조건이 있습니다)의 「Boot with 16KB page size」 개발자 옵션으로 16KB 환경을 만들고, adb shell getconf PAGE_SIZE 가 16384 인지 확인합니다. Flutter 문서는 릴리스 모드를 에뮬레이터에서 지원하지 않는다고 안내하니, 릴리스 빌드로 확인하려면 이런 실기기가 가장 확실합니다. 5단계의 app-arm64-v8a-release.apk 는 adb install <APK 파일> 로 기기에 올립니다.

그 밖에 예고된 요건

Google 이 2026-08-26 에 예고한 기술 품질 요건이 있습니다. 해당 여부와 기준값은 Play Console 기술 품질 요건에서 확인하세요.

  • 2027-02 — 메모리 사용량이 새 임계값(모바일 · 태블릿)을 넘지 않아야 하고, DEX 코드가 앱 10MB 를 넘으면 최소 25% 의 최적화 · 난독화 · 축소를 달성해야 합니다.
  • 2027-04 — 사용자 로그인을 지원하는 앱(모바일 · 태블릿)은 새 기기로 옮길 때 제로탭 로그인 복원(Restore Credentials)을 지원해야 합니다.

프로젝트에서 바꿀 항목

아래 파일 위치와 기본값은 flutter create --platforms=android 로 만든 Flutter 3.47.6 기본 프로젝트에서 확인한 것입니다(2026-10-09). 프로젝트마다 다를 수 있으니 직접 열어 확인하세요.

항목 어디서 바꾸나 기본값과 메모
애플리케이션 ID android/app/build.gradle.kts 의 defaultConfig 안 applicationId 기본은 com.example.<프로젝트 이름> 입니다(예: my_app → com.example.my_app). namespace 도 같은 값으로 들어 있습니다. com.example 기본값은 내 역도메인 이름으로 바꾸고, 첫 번들을 올린 뒤에는 바꿀 수 없습니다. namespace 도 바꾸면 android/app/src/main/kotlin/…/MainActivity.kt 의 package 줄과 폴더 위치도 새 이름에 맞춥니다
앱 이름 android/app/src/main/AndroidManifest.xml 의 application 태그 android:label 기본은 프로젝트 이름(my_app)입니다. 기기에 표시될 최종 이름으로 바꿉니다. Google Play 에 표시되는 이름은 Play Console 에서 따로 입력합니다
버전 pubspec.yaml 의 version: 1.0.0+1 build.gradle.kts 의 versionCode = flutter.versionCode · versionName = flutter.versionName 이 이 값을 받습니다. + 앞이 versionName, 뒤가 versionCode 입니다. 새 번들을 올릴 때마다 빌드 번호를 올리고 이미 쓴 값은 다시 올릴 수 없습니다. 분할 APK 에는 Flutter 가 ABI 번호 × 1000 을 더합니다
서명 설정 새 파일 android/key.properties 와 android/app/build.gradle.kts 의 signingConfigs · buildTypes 기본 템플릿은 release 빌드를 debug 키(signingConfigs.getByName("debug"))로 서명하므로 업로드 키로 바꿉니다(3단계). android/.gitignore 가 key.properties · *.jks · *.keystore 를 이미 제외하지만, android/ 밖에 키 파일을 두면 이 규칙이 닿지 않으니 공개 저장소에 올라가지 않게 직접 챙기세요
권한 android/app/src/main/AndroidManifest.xml 의 uses-permission main 매니페스트에는 uses-permission 이 없고 debug · profile 매니페스트에만 android.permission.INTERNET 이 있어, 릴리스 빌드에는 인터넷 권한이 없습니다. 인터넷을 쓰는 앱은 main 에 android.permission.INTERNET 을 더하고, 쓰지 않는 권한은 빼며, 민감한 권한은 Play Console 선언이 필요할 수 있습니다
최소 SDK android/app/build.gradle.kts 의 minSdk 기본은 flutter.minSdkVersion 이고 Flutter 3.47.6 에서는 24 입니다. 플러그인이 더 높은 값을 요구할 때만 올리고, 숫자로 고정하면 Flutter 를 올려도 따라 오르지 않습니다
타깃 SDK · 컴파일 SDK · NDK 같은 파일의 targetSdk · compileSdk · ndkVersion 기본은 flutter.targetSdkVersion(36) · flutter.compileSdkVersion(36) · flutter.ndkVersion(28.2.13676358, NDK r28)이고 값은 Flutter 3.47.6 도구 소스로 확인했습니다. 숫자로 고정했다면 Google Play 의 타깃 API 요건(36 이상)과 16KB 요건(NDK r28 이상)에 맞게 직접 올립니다
빌드 도구(AGP · Gradle) android/settings.gradle.kts 의 com.android.application 플러그인 버전, android/gradle/wrapper/gradle-wrapper.properties 의 distributionUrl 기본은 AGP 9.1.0 · Gradle 9.3.1 입니다. 16KB 요건은 AGP 8.5.1 이상입니다
아이콘 android/app/src/main/res/mipmap-* 폴더의 ic_launcher.png 와 매니페스트 application 태그의 android:icon 기본은 @mipmap/ic_launcher, Flutter 로고 아이콘입니다. 아이콘 · 스플래시 · 스크린샷을 보세요

테스트 트랙 한눈에

아래 6단계(내부 테스트) · 10단계(비공개 테스트) · 12단계(프로덕션)에서 쓰는 트랙입니다. Google 은 내부 테스트로 시작해 소규모 비공개 테스트로 넓혀 가기를 권장합니다.

트랙 참여자 찾는 방법 조건
내부 테스트(Internal testing) 이메일 목록으로 지정한 최대 100명 링크로만 받을 수 있고 Google Play 에서 검색되지 않습니다 앱 설정을 마치기 전에도 쓸 수 있습니다
비공개 테스트(Closed testing) 이메일 목록(최대 200개, 목록마다 2,000명) 또는 Google 그룹으로 지정한 사람 공개 테스트나 프로덕션 전에는 검색으로 찾을 수 없어 링크를 공유합니다 앱 설정을 마친 뒤 시작합니다
공개 테스트(Open testing) 링크를 가진 누구나(인원 제한 없음이 기본이고, 제한하려면 1,000명 이상) 아직 프로덕션에 낸 적 없는 앱의 공개 테스트도 Google Play 검색으로 찾을 수 있습니다 신규 개인 계정은 프로덕션 액세스를 얻은 뒤 쓸 수 있습니다
프로덕션(Production) 선택한 국가 · 지역의 모든 Google Play 사용자 Google Play 신규 개인 계정은 비공개 테스트 요건을 채워 승인받은 뒤 열립니다

공개 테스트는 누구나 앱을 보고 참여할 수 있으니 앱과 스토어 등록정보를 공개해도 되는 상태에서 시작하세요. 사용자가 내부 테스트에 옵트인하면 같은 앱의 비공개 · 공개 테스트를 받지 못합니다. 그 사용자는 내부 테스트에서 먼저 나온 뒤 다른 테스트에 옵트인해야 하므로, 내부 테스트 인원과 비공개 테스트 인원은 겹치지 않게 모으는 편이 안전합니다.

단계

  1. Play Console 에서 앱을 만듭니다. Play Console의 앱 목록 화면에서 「앱 만들기(Create app)」를 눌러 기본 언어, Google Play 에 표시할 앱 이름(나중에 바꿀 수 있습니다), 앱인지 게임인지, 무료인지 유료인지, 사용자가 연락할 이메일 주소를 입력합니다. 「선언」에서 개발자 프로그램 정책과 미국 수출 법규를 확인하고 Play 앱 서명 서비스 약관에 동의한 뒤 「앱 만들기」를 선택합니다. Android 개발자 인증 안내는 새 앱을 만들 때 Google Play 가 패키지 이름을 자동으로 등록해 계정에 연결한다고 적습니다. 앱 만들기 화면에는 이름 입력란이 없고, 첫 번들을 올리는 6단계에서 그 번들의 패키지 이름(applicationId)이 앱의 패키지 이름으로 고정됩니다. 다른 개발자가 이미 쓰는 이름이면 콘솔이 다른 이름을 고르라고 안내합니다.

    주의

    먼저 정해 둘 것이 셋 있습니다. 패키지 이름은 고유하고 영구적이며 삭제하거나 다시 쓸 수 없고, 첫 번째 파일(아티팩트)을 올리면 바꿀 수 없습니다. 한 번 무료로 제공한 앱은 유료로 바꿀 수 없습니다. 앱 서명 키는 공개 테스트나 프로덕션 트랙에 출시하기 전까지만 바꿀 수 있습니다(6단계).

    성공 판정 — 앱 목록에 새 앱이 보이고, 앱을 열면 왼쪽 메뉴에 「대시보드(Dashboard)」가 있으며 앱 이름 아래 게시 상태가 「초안(Draft)」입니다(한국어 도움말의 앱 상태 표는 같은 상태를 「임시」로 적습니다).

  2. 업로드 키를 만듭니다. 업로드 키는 앱 번들에 서명하는 키입니다. Play 앱 서명을 쓰면 사용자 기기에 배포되는 APK 는 Google 이 보관하는 앱 서명 키로 서명하고, 업로드 키를 잃으면 재설정을 요청할 수 있습니다. 업로드 키는 Java 키 저장소(.jks 또는 .keystore)에 둔 2048비트 이상 RSA 키여야 합니다. Flutter 문서의 명령으로 만듭니다.

    macOS · Linux:

    bash
    keytool -genkey -v -keystore ~/upload-keystore.jks -keyalg RSA \
            -storetype JKS -keysize 2048 -validity 10000 -alias upload
    

    Windows(PowerShell):

    powershell
    keytool -genkey -v -keystore $env:USERPROFILE\upload-keystore.jks `
            -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 `
            -alias upload
    

    Android Studio 의 「Build → Generate Signed Bundle/APK」로도 만들 수 있습니다. 유효 기간은 길게 잡으세요. Android 문서는 앱 업데이트에 같은 키를 쓸 수 있도록 25년 이상을 권장합니다. 키 저장소 파일과 비밀번호는 공개 저장소에 올리지 말고 잃어버리지 않게 따로 보관합니다.

    성공 판정 — 만든 파일에 keytool -list -v -keystore ~/upload-keystore.jks 를 실행하면(Windows 는 위에서 정한 경로) 별칭 upload 와 2048비트 RSA 키가 나옵니다.

  3. Flutter 프로젝트가 업로드 키로 서명하게 합니다. android/key.properties 파일을 만들어 키 저장소를 가리킵니다. 꺾쇠 괄호(< >)는 넣지 않고 값으로 바꿉니다.

    properties
    storePassword=<키 저장소 비밀번호>
    keyPassword=<키 비밀번호>
    keyAlias=upload
    storeFile=<키 저장소 파일 경로>
    

    Windows 에서는 경로의 역슬래시를 두 개(\\)로 씁니다. 다음으로 android/app/build.gradle.kts 를 고칩니다(Groovy 를 쓰는 프로젝트는 android/app/build.gradle 을 고치며, Flutter 문서의 Groovy 탭에 같은 설정이 있습니다). 파일 맨 위에 import 를 더하고, plugins 블록 뒤 android 블록 앞에서 key.properties 를 읽습니다.

    kotlin
    import java.util.Properties
    import java.io.FileInputStream
    
    // plugins { ... } 블록 뒤, android { ... } 블록 앞
    val keystoreProperties = Properties()
    val keystorePropertiesFile = rootProject.file("key.properties")
    if (keystorePropertiesFile.exists()) {
        keystoreProperties.load(FileInputStream(keystorePropertiesFile))
    }
    

    android 블록 안에서는 buildTypes 앞에 서명 설정을 더하고, release 빌드가 그 설정을 쓰게 바꿉니다.

    kotlin
    android {
        // ...
        signingConfigs {
            create("release") {
                keyAlias = keystoreProperties.getProperty("keyAlias")
                keyPassword = keystoreProperties.getProperty("keyPassword")
                storeFile = keystoreProperties.getProperty("storeFile")?.let { file(it) }
                storePassword = keystoreProperties.getProperty("storePassword")
            }
        }
        buildTypes {
            release {
                // 기본값은 signingConfigs.getByName("debug") 입니다
                signingConfig = signingConfigs.getByName("release")
            }
        }
    }
    

    Gradle 파일을 바꾼 뒤에는 flutter clean 이 필요할 수 있습니다. 이전 빌드 캐시가 서명에 영향을 주지 않게 하려는 것입니다.

    주의

    Flutter 기본 템플릿의 release 빌드는 flutter run --release 가 동작하도록 debug 키로 서명합니다. debug 인증서로 서명한 앱은 Google Play 를 포함한 대부분의 스토어가 받지 않으니 위 설정을 꼭 바꾸세요. key.properties 도 공개 저장소에 올리지 않습니다.

    성공 판정 — android/ 폴더에서 ./gradlew signingReport(Windows 는 gradlew.bat signingReport)를 실행하면 Variant: release 의 Store: 가 내 업로드 키 저장소 경로이고 Alias: 가 upload 입니다. ~/.android/debug.keystore 와 AndroidDebugKey 가 보이면 아직 debug 키로 서명하는 것입니다.

  4. 릴리스 앱 번들을 빌드합니다. flutter build 는 기본이 릴리스 빌드입니다.

    bash
    cd <프로젝트 폴더>
    flutter build appbundle
    

    결과는 build/app/outputs/bundle/release/ 폴더의 .aab 파일입니다. Flutter 문서는 한 곳에서는 파일 이름을 app.aab, 지속적 배포(CD) 안내에서는 app-release.aab 로 적었으니 빌드 끝에 출력되는 경로를 따르세요. 기본 번들에는 armeabi-v7a · arm64-v8a · x86-64 용 코드가 들어 있습니다. 이 빌드에서만 버전을 덮어쓰려면 --build-name 과 --build-number 를 씁니다.

    성공 판정 — 명령이 Built build/app/outputs/bundle/release/app-release.aab (…MB) 같은 줄로 끝나고(Flutter 3.47.6 에서 직접 확인) 그 경로에 .aab 파일이 있습니다.

  5. 올리기 전에 빌드를 점검합니다. 타깃 API 수준과 16KB 정렬을 확인합니다. 두 도구는 APK 를 받으므로 같은 코드로 APK 를 따로 만들어 봅니다. apkanalyzer 는 Android SDK Command-line Tools 패키지(cmdline-tools/<버전>/bin)에 들어 있고, zipalign 은 Build-Tools 35.0.0 이상에 있습니다. Build-Tools 와 NDK 는 Android Studio 의 SDK Manager 나 sdkmanager 로 설치합니다. 이 도구들은 PATH 에 없을 수 있으니 SDK 폴더의 전체 경로(예: <SDK 폴더>/build-tools/35.0.0/zipalign)로 실행하거나 PATH 에 추가하세요.

    bash
    flutter build apk --release --split-per-abi
    apkanalyzer manifest target-sdk build/app/outputs/flutter-apk/app-arm64-v8a-release.apk
    zipalign -v -c -P 16 4 build/app/outputs/flutter-apk/app-arm64-v8a-release.apk
    zipalign -v -c -P 16 4 build/app/outputs/flutter-apk/app-x86_64-release.apk
    

    16KB 요건은 64비트 기기에 적용되니 app-arm64-v8a-release.apk 와 app-x86_64-release.apk 를 모두 점검합니다. zipalign 은 ZIP 안의 위치만 보므로 위 「16KB 메모리 페이지 크기」의 ELF 정렬 점검(APK Analyzer · check_elf_alignment.sh · llvm-objdump)을 함께 합니다. 번들 자체의 정렬은 bundletool dump config --bundle=<AAB 파일> 에서 PAGE_ALIGNMENT_16K 로 확인합니다. --split-per-abi APK 는 ABI 마다 ABI 번호 × 1000 이 versionCode 에 더해져 번들의 버전 코드와 다릅니다(빌드 번호 1 인 Flutter 3.47.6 빈 앱에서 arm64-v8a APK 의 version-code 는 2001 이었습니다). 스토어에 올리는 파일은 4단계의 .aab 입니다.

    성공 판정 — target-sdk 가 36 이상이고, 두 APK 모두 zipalign 의 마지막 줄이 Verification successful 이며, 모든 .so 의 LOAD 정렬이 align 2**14 이상입니다.

  6. 첫 번들을 내부 테스트에 올립니다. 내부 테스트(Internal testing)는 앱 설정을 마치기 전에도 쓸 수 있고, 최대 100명의 테스터에게 빠르게 나눠 줍니다. Google 은 내부 테스트로 시작해 소규모 비공개 테스트로 넓혀 가기를 권장합니다.

    1. 「테스트 및 출시 → 테스트 → 내부 테스트(Test and release → Testing → Internal testing)」에서 오른쪽 위의 「새 버전 만들기(Create new release)」를 누릅니다.
    2. 이 앱의 첫 버전이면 Play 앱 서명을 설정하라는 안내가 나옵니다. 새 앱은 기본으로 Google 이 만든 키를 쓰는 하이브리드 서명에 자동으로 등록되므로 그대로 두면 됩니다.
    3. 4단계에서 만든 .aab 파일을 올리고, 이 버전을 구분할 이름(Play Console 안에서만 보입니다)과 언어별 출시 노트(언어당 500자까지)를 입력합니다. 번들에 SMS · 통화 기록 같은 민감한 권한이 있으면 이 릴리스 도중 권한 선언 양식이 나옵니다. 아래 「자주 겪는 문제」의 권한 항목을 먼저 보세요.
    4. 「다음(Next)」을 눌러 「미리보기 및 확인」 화면으로 갑니다. 위쪽에 「오류 요약(Errors summary)」이 있으면 해결해야 게시할 수 있고, 경고나 사소한 문제는 게시를 막지 않지만 미리 해결하길 권장합니다. 변경이 검토 대상인지에 따라 「저장(Save)」 또는 「게시(Publish)」가 보입니다. 「게시」는 바로 반영합니다. 「저장」은 변경을 게시 개요(Publishing overview) 페이지의 「변경사항이 아직 검토를 위해 전송되지 않음(Changes not yet sent for review)」 섹션에 모아 둘 뿐 검토로 자동 전송하지 않습니다(도움말마다 이 섹션 이름이 달라, 영어로는 Changes ready to send for review, 한국어로는 「변경사항을 전송하여 검토받을 수 있음」 · 「아직 검토를 위해 전송되지 않은 변경사항」으로도 적힙니다). 그러니 게시 개요에서 「검토를 위해 전송(Send for review)」(「전송하여 검토받기」로도 적힙니다)을 눌러야 검토가 시작됩니다.
    5. 「테스터(Testers)」 탭의 「이메일 목록 만들기(Create email list)」에서 목록 이름과 테스터 이메일(쉼표로 구분하거나 CSV 파일)을 넣고 「변경사항 저장(Save changes)」 → 「만들기」를 누릅니다. 이어서 「테스터」 표에서 만든 목록을 선택하고, 피드백을 받을 이메일이나 주소를 입력하고, 공유 가능한 링크를 복사한 뒤 「변경사항 저장」을 누릅니다. 링크를 테스터에게 보냅니다. 테스터는 Google 계정이 있어야 합니다.

    참고

    처음 게시한 테스트의 링크는 열리기까지 몇 시간이 걸릴 수 있습니다. 처음 올린 앱은 최대 48시간 동안 임시 이름과 임시 등록정보가 보일 수 있고, 내부 테스트 앱은 Play 스토어에서 검색되지 않으니 링크를 직접 공유해야 합니다. 내부 테스트 트랙은 앱 설정을 마치지 않았다면 검토 없이 쓸 수 있지만, 설정을 마친 앱의 첫 출시가 내부 테스트이면 검토를 거쳐야 게시되고(몇 시간에서 최대 7일), 직전 제출이 거절된 경우에도 다음 제출은 검토를 거칩니다.

    참고

    직접 만든 앱 서명 키를 쓰려는 고급 개발자는 첫 버전을 만들 때 「앱 무결성(App integrity)」 섹션의 「앱 서명 키 변경(Change app signing key)」으로 기본값을 바꿀 수 있습니다. 바꾸면 이미 앱을 설치한 내부 · 비공개 트랙 테스터는 업데이트를 받지 못해 앱을 지웠다 다시 설치해야 하고, 이전에 올린 앱 버전은 쓸 수 없어 다시 올려야 합니다. 여러 스토어에 같은 서명 키로 배포하려는 경우에도 Android 문서는 Google 이 만든 키 대신 직접 만든 키를 제공하라고 안내합니다.

    성공 판정 — 내부 테스트 출시가 게시되어 앱 이름 아래 게시 상태가 「내부 테스트(Internal testing)」이고, 테스터가 공유 링크로 Play 스토어에서 앱을 설치해 실행합니다.

  7. (API 제공업체를 쓰는 앱) 앱 서명 키 지문을 등록합니다. Firebase · Google 로그인 · 지도 같은 서비스는 앱 서명 키의 지문으로 앱을 확인합니다. 사용자에게는 Google 이 서명한 앱이 배포되므로 업로드 키 지문만으로는 부족합니다. Play Console 의 「Google Play로 보호됨 → Play 스토어 배포 → Play 앱 서명으로 이동(Protected with Play → Play Store distribution → Go to Play app signing)」에서 「앱 서명 키」 섹션의 지문(SHA-1 또는 SHA-256)을 복사해 제공업체 콘솔에 붙여 넣습니다. 하이브리드 서명이면 키 세 개의 지문을 모두 등록해야 하고, Android App Links 를 쓰면 assetlinks.json 도 같은 지문으로 고칩니다.

    성공 판정 — 제공업체 콘솔에 등록한 지문이 Play Console 「Play 앱 서명」 페이지의 앱 서명 키 지문(SHA-1 · SHA-256, 하이브리드 서명이면 세 키 모두)과 같고, Play 에서 설치한 내부 테스트 앱에서 그 서비스(로그인 등)가 동작합니다.

  8. 앱 콘텐츠(App content)를 선언합니다. 「정책 및 프로그램 → 앱 콘텐츠(Policy and programs → App content)」 페이지의 「확인 필요(Needs attention)」 탭에 남은 선언을 모두 마칩니다. 항목 이름과 순서는 콘솔에서 바뀔 수 있습니다.

    선언 하는 일 알아 둘 것
    개인정보처리방침(Privacy policy) 방침을 공개한 웹 주소를 입력합니다 데이터 보안 양식을 작성하려면 방침이 먼저 있어야 해서 출시하는 앱에는 사실상 필요합니다. 민감한 권한이나 데이터를 쓰는 앱은 스토어 등록정보와 앱 안에도 링크가 있어야 하고, 아동을 타겟팅하는 앱은 항상 필요합니다. 주소는 활성 상태여야 합니다
    광고(Ads) 서드파티 광고 SDK 를 포함해 광고가 있는지 예 또는 아니요로 답합니다 광고가 있으면 스토어 등록정보에 「광고 포함」 라벨이 모든 사용자에게 보입니다. 잘못 선언하면 앱이 정지될 수 있습니다
    로그인 세부정보(Sign-in details, 한국어 도움말의 「앱 액세스 권한」) 로그인 등으로 제한된 부분이 있으면 심사자가 쓸 수 있는 정보를 입력합니다 정보는 언제나 쓸 수 있고 재사용할 수 있어야 하며, 2단계 인증이나 일회용 비밀번호를 우회하는 계정이어야 하고, 영어로 제공합니다. 최대 5세트까지 추가할 수 있습니다
    타겟층 및 콘텐츠(Target audience and content) 앱의 타깃 연령대를 선언합니다 아동이 타겟에 포함되면 Families 정책을 지켜야 합니다. 이 섹션을 쓰기 전에 광고 포함 여부와 앱 액세스 안내, 개인정보처리방침을 먼저 마쳐야 합니다
    콘텐츠 등급(Content ratings) IARC 설문에 답해 등급을 받습니다 등급이 없는 앱은 「등급 없음(Unrated)」으로 표시되어 Google Play 에서 제거될 수 있습니다. 콘텐츠나 기능이 바뀌어 답이 달라지면 설문을 다시 합니다. 한국에서 앱(게임 제외)은 Google Play 등급 체계를 씁니다
    데이터 보안(Data safety) 앱이 수집 · 공유하는 데이터와 보안 관행을 양식으로 제출합니다 데이터를 전혀 수집하지 않아도 양식과 개인정보처리방침 링크가 필요합니다. SDK 가 보내는 데이터도 포함합니다. 사용자가 데이터 삭제를 요청할 방법을 제공하는지도 묻고, 앱 안에서 계정을 만들 수 있으면 앱 안의 삭제 경로와 삭제를 요청하는 웹 링크를 제공해야 합니다. 내부 테스트 트랙에서만 쓰는 앱은 제외됩니다
    광고 ID(Advertising ID) 앱이나 SDK 가 광고 ID 를 쓰는지, 쓴다면 목적을 답합니다 Android 13 이상을 타깃하는데 광고 ID 를 쓰면 AD_ID 권한도 선언합니다. 개인정보와 권한을 보세요
    건강 · 정부 앱 · 금융 기능 건강 기능이 있는지, 정부가 또는 정부를 대신해 만든 앱인지, 금융 기능이 있는지 답합니다 해당 기능이 없어도 답해야 하는 질문입니다. 건강과 금융에는 기능이 없다는 선택지가 있고, 정부 앱 선언도 해당하지 않으면 그 취지로 답해 마칩니다
    뉴스 및 매거진 · 아동 안전 표준 뉴스 및 매거진 앱, 소셜 · 데이팅 카테고리 앱과 익명 · 무작위 채팅 앱이 작성하는 선언입니다 해당하는 앱만 작성하고 아니면 건너뜁니다
    권한 선언 양식(Permissions Declaration Form) 위험성이 높거나 민감한 권한(SMS · 통화 기록 등)을 쓸 때 핵심 기능과 사용 방법을 설명합니다 릴리스를 올릴 때 평가되며 승인이 필요합니다. 아래 「자주 겪는 문제」를 보세요

    성공 판정 — 「앱 콘텐츠」 페이지의 「확인 필요(Needs attention)」 탭이 비고, 마친 선언이 「조치됨(Actioned)」 탭에 있습니다.

  9. 스토어 등록정보를 채웁니다. 대시보드의 「앱 카테고리 지정 및 스토어 등록정보 관련 세부정보」 작업에서 앱 카테고리를 고르고(태그도 지정할 수 있습니다), 「기본 스토어 등록정보(Main store listing)」에서 앱 세부정보와 그래픽을 입력하고, 「스토어 설정(Store settings)」의 연락처에 지원 이메일을 입력합니다(필수). 입력 한도는 아래와 같습니다. 이미지 규격은 아이콘 · 스플래시 · 스크린샷을 보세요.

    항목 한도 · 규격
    앱 이름(App name) 영문 도움말은 30자라고 적었고, 한국어 도움말 표는 「한글 15자(영문 30자)」라고 적어 문서끼리 다릅니다(두 문서 모두 문자 종류와 관계없이 표의 숫자가 최대 한도라는 각주를 붙였습니다). 한글 이름은 15자 안에서 지으면 둘 다 만족합니다
    간단한 설명(Short description) 80자
    자세한 설명(Full description) 4,000자
    앱 아이콘 512 × 512 px, 32비트 PNG(알파 포함), 최대 1024KB
    그래픽 이미지(Feature graphic) 1024 × 500 px, JPEG 또는 24비트 PNG(알파 없음)
    스크린샷 등록정보를 게시하려면 기기 유형을 통틀어 최소 2장, JPEG 또는 24비트 PNG(알파 없음), 한 변 320~3840 px, 긴 변이 짧은 변의 2배를 넘지 않아야 합니다

    성공 판정 — 대시보드에서 앱 카테고리 · 스토어 등록정보 · 연락처 관련 필수 작업에 완료 표시(녹색 체크와 취소선)가 붙고 진행 막대가 올라갑니다.

  10. (신규 개인 계정) 비공개 테스트를 진행합니다. 앱 설정(8단계 · 9단계)을 마치면 비공개 테스트를 시작할 수 있습니다.

    • 「테스트 및 출시 → 테스트 → 비공개 테스트(Closed testing)」에서 「트랙 관리(Manage track)」를 누릅니다.
    • 「테스터」 탭에서 이메일 목록이나 Google 그룹으로 테스터를 지정합니다. 이메일 목록은 최대 200개이고 목록마다 2,000명까지, 트랙마다 목록 50개까지 만들 수 있습니다. Google 그룹으로 지정했다면 테스터가 먼저 그룹에 가입해야 옵트인할 수 있습니다.
    • 「국가/지역」 탭에서 테스터가 사는 국가가 포함돼 있는지 확인합니다(기본값은 프로덕션 설정과 동기화됩니다).
    • 새 버전을 만들어 6단계에서 올린 번들을 「라이브러리에서 추가」하거나(같은 .aab 를 다시 올리면 이미 쓴 버전 코드라고 거부될 수 있습니다) 빌드 번호를 올려 다시 빌드한 번들을 올린 뒤 저장합니다.
    • 6단계처럼 게시 개요에서 「검토를 위해 전송」까지 눌러야 검토가 시작되고, 검토를 거쳐 게시된 뒤에야 테스트 참여(옵트인) 링크가 열립니다. 테스트 도움말은 앱 상태가 「게시됨」일 때만 링크가 보이고 「초안」 · 「게시 대기 중」이면 보이지 않는다고 설명합니다.
    • 공유 링크를 테스터 12명 이상에게 보내 각자 옵트인하게 하고, 이때부터 14일을 셉니다.

    성공 판정 — 비공개 테스트 출시가 게시되어 옵트인 링크가 열렸고, 12명 이상이 옵트인한 상태가 연속 14일 이어졌습니다. 콘솔에서 이 숫자를 세어 주는 화면은 도움말에서 확인하지 못했으니 옵트인한 테스터 수와 시작 날짜를 직접 적어 두세요.

  11. (신규 개인 계정) 프로덕션 액세스를 신청합니다. 12명이 연속 14일 옵트인한 상태가 되면 대시보드에서 「프로덕션 신청」을 누르고, 위 「신규 개인 계정의 비공개 테스트 요건」의 세 부분에 답합니다. 승인 이메일이 오면 프로덕션 페이지와 공개 테스트가 열립니다.

    성공 판정 — 신청서의 세 부분을 모두 마쳐 「적용(Apply)」으로 제출했고, 검토가 끝나 Account Owner 의 이메일로 승인 결과가 오며 프로덕션 페이지가 열립니다.

  12. 프로덕션에 출시합니다. 프로덕션이 열려 있어야 합니다(신규 개인 계정은 11단계 승인 뒤). 먼저 「테스트 및 출시 → 프로덕션(Test and release → Production)」의 「국가/지역(Countries/regions)」 탭에서 「국가/지역 추가」로 출시할 국가를 고릅니다. 국가 타겟팅은 사용자가 지금 있는 곳이 아니라 Play 계정을 등록한 국가 기준입니다. 이어서 「새 버전 만들기」를 누르고 번들을 추가한 뒤, 「미리보기 및 확인」에서 오류가 없으면 「프로덕션 출시 시작(Start rollout to production)」을 누릅니다. 변경이 검토 대상이라 「저장」이 보이면 6단계처럼 게시 개요에서 「검토를 위해 전송」을 눌러야 검토가 시작됩니다. 게시되면 선택한 국가 · 지역의 모든 Google Play 사용자에게 보입니다. 첫 출시에는 출시 비율(단계적 출시)과 관리형 게시를 쓸 수 없습니다. 둘 다 업데이트에만 쓰는 기능입니다. 변경사항은 검토를 거치며, 몇 시간에서 최대 7일(예외적으로 더 오래) 걸릴 수 있습니다. 관리형 게시 문서는 제출과 공개 사이에 최소 1주일의 여유를 두라고 권합니다.

    성공 판정 — 앱 이름 아래 게시 상태가 「프로덕션(Production)」이 되고, 몇 시간 안에 Google Play 에서 앱 페이지가 열립니다(게시가 보이기까지 몇 시간 걸릴 수 있습니다).

  13. 업데이트를 올립니다. pubspec.yaml 의 version: 에서 + 뒤 빌드 번호를 올려 다시 빌드하고 새 번들을 올립니다. 업데이트는 단계적 출시(Staged rollout)로 일부 사용자에게만 먼저 내보낼 수 있습니다. 출시 비율은 자동으로 늘지 않아 직접 올려야 하고, 문제가 보이면 롤아웃을 중단할 수 있습니다. 관리형 게시(Managed publishing)를 켜면 승인된 변경을 내가 정한 시각에 공개할 수 있습니다. 업데이트의 단계적 출시와 출시 중단은 업데이트와 단계적 출시에서 이어집니다.

    성공 판정 — 「테스트 및 출시 → 최신 버전 및 번들」의 「최신 버전」에서 새 릴리스가 프로덕션 트랙으로 보입니다. 단계적 출시라면 출시 비율을 직접 올려 100% 로 맞춘 뒤에야 끝난 것입니다.

확인

  • 빌드 점검 통과 — apkanalyzer manifest target-sdk 가 36 이상이고, zipalign 이 Verification successful 을 내며, ELF 정렬 점검에서 align 2**14 보다 작은 .so 가 없습니다. apkanalyzer manifest application-id 가 정해 둔 값과 같습니다. --split-per-abi APK 의 version-code 는 번들과 달라도 정상입니다.
  • 내부 테스트 — 올린 번들의 릴리스가 「최신 버전 및 번들(Latest releases and bundles)」(테스트 및 출시 → 최신 버전 및 번들)에 보이고, 릴리스 이름(기본값은 첫 번들의 버전 이름)이 pubspec.yaml 의 버전 이름과 같습니다. 테스터가 링크로 Play 스토어에서 설치해 실행됩니다.
  • 앱 설정 — 대시보드의 필수 작업에 완료 표시가 붙고 「앱 콘텐츠」의 「확인 필요」 탭이 비어 있으며, 「새 버전 만들기」가 활성화됩니다. 게시 개요(Publishing overview)에 검토를 위해 전송하지 않은 변경사항이 남아 있지 않고, 사전 검토(pre-review checks)에 해결하지 않은 심각한 문제가 없습니다. 사전 검토는 15분 안에 끝나고, 앱 콘텐츠 선언이 빠졌는지도 봅니다.
  • (신규 개인 계정) 프로덕션 액세스 — 12명 · 14일을 채운 뒤 신청해 승인 이메일을 받았고 프로덕션 페이지가 열립니다.
  • 프로덕션 — 앱 상태가 「프로덕션(Production)」이 됩니다. 게시나 업데이트가 Google Play 에 보이기까지 몇 시간이 걸릴 수 있습니다.

자주 겪는 문제

「새 버전 만들기」 버튼이 눌리지 않습니다
  • 대시보드의 설정 작업. 끝내지 못한 설정 작업이 남아 있으면 비활성화됩니다. 필수 작업과 앱 콘텐츠 선언을 모두 마치세요.
  • 끝나지 않은 버전. 롤아웃이 끝나지 않은 버전이 있으면 새 버전을 만들 수 없습니다. 단계적 출시 중이면 100% 로 올리거나, 게시 개요(Publishing overview)에서 변경을 지우고 게시되지 않은 버전을 삭제한 뒤 다시 만드세요.
  • 계정 권한. 새 버전을 만들려면 「앱을 테스트 트랙으로 출시(Release apps to testing tracks)」 권한이 필요합니다. Account Owner 에게 요청하세요.
  • (신규 개인 계정) 비공개 테스트 요건을 채우기 전에는 프로덕션과 공개 테스트를 쓸 수 없습니다.
서명이 맞지 않는다며 번들을 받지 않습니다
  • debug 키로 서명하지 않았는지 봅니다. Flutter 기본 템플릿은 release 빌드도 debug 키로 서명하므로 3단계 설정이 필요하고, debug 인증서로 서명한 앱은 Google Play 가 받지 않습니다.
  • 업로드 키가 같은지 봅니다. Google 은 업로드 인증서로 업로드한 사람을 확인한다고 안내하므로 Play Console 에 등록된 업로드 키와 같은 키로 서명해야 합니다. 업로드 키를 재설정했다면 새로 등록한 키를 씁니다. Play Console 의 Play 앱 서명 페이지에서 업로드 인증서의 지문(MD5 · SHA-1 · SHA-256)을 볼 수 있으니, 내 키의 지문(Android Studio 의 Gradle signingReport 작업으로 봅니다)과 비교하세요.
  • 업로드 키를 잃었거나 유출됐다면 새 키를 만들어 인증서를 PEM 으로 내보내고(keytool -export -rfc -keystore upload-keystore.jks -alias upload -file upload_certificate.pem), Play Console 에서 업로드 키 재설정을 요청합니다. 앱 서명 키는 Google 이 보관하므로 업로드 키를 바꿔도 같은 앱의 업데이트를 계속 올릴 수 있습니다.
이미 사용한 버전 코드라며 업로드를 거부합니다

versionCode 는 올릴 때마다 커져야 하고 이미 쓴 값은 다시 쓸 수 없습니다. pubspec.yaml 의 + 뒤 숫자를 올려 다시 빌드하세요. 자세한 규칙은 식별자와 버전에 있습니다.

16KB 정렬 검사가 실패하거나 Play Console 에 호환성 경고가 보입니다

먼저 어떤 .so 가 문제인지 찾습니다. zipalign 이 실패하거나 check_elf_alignment.sh 가 UNALIGNED 를 내면 그 라이브러리의 정렬이 맞지 않은 것입니다. Android 문서는 이런 라이브러리는 패키징을 고치고 앱을 다시 빌드해 확인하라고 안내합니다. APK Analyzer 로 lib 폴더의 .so 목록을 보고 어느 플러그인이나 SDK 가 싣는 파일인지 가려내세요. 위 「어디를 보나」 표대로 Flutter · AGP · NDK 를 올리고, 네이티브 라이브러리를 싣는 플러그인은 제공사가 16KB 를 지원하는 버전으로 올려 다시 빌드하세요. 플러그인이 싣는 프리빌트 .so 는 제공사가 16KB 지원 버전을 내놓아야 고쳐집니다. Android 개발자 문서는 2027-02-01 부터 지원하지 않는 업데이트를 출시할 수 없다고 하고, Play Console 기술 품질 요건 문서는 이미 적용 중인 요건으로 올려 두었으니 날짜까지 기다리지 말고 고치세요.

타깃 API 요건 때문에 올릴 수 없습니다
  • 값을 올립니다. 빌드한 APK 의 apkanalyzer manifest target-sdk 값이 36 미만이면 targetSdk = flutter.targetSdkVersion 인 프로젝트는 Flutter 를 올리고, 숫자로 고정한 프로젝트는 build.gradle.kts 의 숫자를 올립니다.
  • 올린 뒤 확인합니다. Android 16 에서 달라지는 동작에 앱이 맞는지 실제 기기에서 확인하세요. Flutter 3.35.0 릴리스 노트에는 Android 16 이상에서 엣지 투 엣지(시스템 바 영역) 옵트아웃이 폐기된다는 경고와 SystemChrome.setPreferredOrientations 가 동작하지 않는다는 문서 항목이 있습니다.
  • 연장. 이미 게시된 앱이 기준을 못 채워 정책 경고를 받았다면, 올릴 계획이 있을 때 경고 상세의 양식으로 2026-11-01 까지 연장을 요청할 수 있습니다. 연장 기간에 36 미만을 타깃한 업데이트를 받아 주는지는 공식 문서가 분명히 밝히지 않으니, 새 앱과 업데이트는 36 이상으로 올려 제출하세요.
권한 때문에 심사가 길어지거나 거절됩니다
  • 필요한 권한만 요청합니다. Google 은 앱 소개에 알린 기능에 필요한 권한만 요청하라고 안내합니다. 플러그인이 매니페스트에 권한을 더했을 수 있으니 apkanalyzer manifest permissions <APK 파일> 로 최종 권한을 확인해 쓰지 않는 것은 빼세요.
  • 사진 · 동영상 권한. Android 13(API 수준 33) 이상을 타깃하는 앱은 Android 사진 선택기 같은 시스템 선택기로 충분하지 않을 때만 READ_MEDIA_IMAGES · READ_MEDIA_VIDEO 를 요청할 수 있고, 요청한다면 Play Console 에 선언을 제출해야 합니다.
  • SMS · 통화 기록 권한. 기본 SMS · 전화 · 어시스턴트 핸들러로 등록된 앱이 대상이고, 일부 용도에는 임시 예외가 주어질 수 있습니다. 어느 쪽이든 Play Console 에서 선언하고 승인을 받아야 하며, 해당하지 않으면 매니페스트에서 이 권한을 뺍니다.
  • 권한 선언 양식은 릴리스를 만드는 도중에 나옵니다. 번들에 위험성이 높거나 민감한 권한이 있는데 선언이 없으면 내부 · 비공개 · 공개 테스트 번들도 대상이 되고, 선언을 마치거나 그 권한을 뺀 버전을 올리기 전에는 스토어 등록정보 같은 다른 변경도 게시할 수 없습니다. 양식에는 앱의 핵심 기능을 보여 주는 동영상이 필요하고, 핵심 기능이 로그인한 사용자에게만 열려 있으면 테스트 전용 계정 정보도 제공합니다(실제 사용자의 계정 정보는 쓰지 않습니다).
  • 권한 선언 양식이 필요한 릴리스는 확장 검토를 받아 최대 몇 주가 걸리고 그동안 게시 대기 상태가 됩니다. 급한 업데이트는 해당 권한을 뺀 새 번들로 다시 출시하면 일반 정책 검토만 받아 몇 시간 안에 게시된다고 Google 이 안내합니다. 새 권한을 더할 때마다 선언 양식을 다시 작성해야 합니다.
비공개 테스트에 12명이 모이지 않거나 일수가 다시 시작됩니다

테스터는 신청 시점까지 연속 14일 옵트인 상태여야 하고, 중간에 나갔다 들어오면 그 14일이 연속이어야 합니다. 여유 있게 모으고, 테스터에게 14일 동안 옵트인을 유지해 달라고 미리 알리세요. 내부 테스트에 옵트인한 사용자는 같은 앱의 비공개 · 공개 테스트를 받을 수 없고, 내부 테스트에서 먼저 나온 뒤 비공개 테스트에 옵트인해야 합니다. 비공개 테스트 인원은 내부 테스트에 옵트인하지 않은 사람으로 모으는 편이 안전합니다. 테스터는 옵트인 링크로 들어와 각자 참여를 선택해야 하며, 링크는 앱이 게시된 상태일 때만 보입니다.

테스트 링크가 열리지 않거나 Play 스토어에서 앱을 찾을 수 없습니다

Google 은 내부 테스트와, 공개 테스트나 프로덕션 출시 전의 비공개 테스트는 Play 스토어 검색으로 찾을 수 없다고 안내합니다. 옵트인 링크나 앱의 Play 스토어 주소를 테스터에게 직접 공유하세요. 링크는 앱 상태가 「게시됨」일 때만 보이므로, 변경을 저장만 하고 게시 개요에서 「검토를 위해 전송」을 누르지 않았는지 먼저 확인합니다. 처음 게시한 테스트의 링크는 열리기까지 몇 시간이 걸릴 수 있고, 테스터는 Google 계정으로 로그인해 있어야 합니다.

심사에서 거절됐습니다

Google 은 스토어 등록정보에 적은 기능이 앱에 없는 경우, 로그인이 필요한데 심사용 계정을 주지 않은 경우, 앱이 충돌하거나 제대로 동작하지 않는 경우를 흔한 사유로 듭니다. 사유를 고치세요. Google 은 문제를 고친 업데이트 버전을 다시 제출하라고 안내하고, 로그인 세부정보 때문이라면 새 번들 없이 정보를 고쳐 저장한 뒤 다시 전송하면 된다고 안내합니다. 그 밖의 사유는 거절 안내에 적힌 대로 고치고 번들이 필요하면 새 버전을 올립니다. 어느 쪽이든 거절된 뒤에 바꾼 내용은 자동으로 검토에 전송되지 않으니, 저장한 뒤 게시 개요(Publishing overview)에서 「검토를 위해 전송(Send for review)」(「전송하여 검토받기」)을 눌러야 합니다. 거절이 여러 번 쌓이면 앱이 정지될 수 있다고 Google 이 경고합니다. 스토어별 사유와 번호, 재제출 방법은 심사 거절 대응에 모았습니다.

패키지 이름이 이미 사용 중이라고 합니다

Play Console 은 다른 개발자가 이미 쓰는 패키지 이름이면 다른 이름을 고르라고 안내합니다. applicationId 를 바꿀 때는 namespace 와 MainActivity 의 package 선언 · 파일 위치도 맞추세요. 자세한 방법은 식별자와 버전을 보세요. 첫 번들을 올린 뒤에는 바꿀 수 없습니다.

다음 단계

제출 직전에는 제출 전 체크리스트의 Google Play 항목으로 한 번 더 점검하세요. 같은 Flutter 앱을 Apple 스토어에도 낸다면 App Store · Mac App Store 편을, 다른 스토어는 스토어별 안내에서 고르세요. 출시한 뒤의 업데이트와 거절 대응은 출시 후 운영에서 이어집니다.

출처