# 구글 플레이 스토어 신규 앱 첫 배포 가이드 (Flutter / Android)

- 날짜: 2026-10-01 (KST)
- 대상: day_plan_app (모담 하루계획, `com.modamtech.day_plan_app`) 첫 배포 경험을 바탕으로 정리.
  다른 신규 Flutter 앱에도 그대로 적용할 수 있도록 일반화했다.
- 표기: `<앱>` = 프로젝트 폴더명, `<패키지>` = applicationId(예: `com.modamtech.new_app`),
  `<앱이름>` = 스토어/런처에 보이는 이름.

---

## 0. 전체 흐름 한눈에 보기

| 단계 | 어디서 | 내용 |
|---|---|---|
| 1 | 코드 | 패키지명·앱 이름·아이콘·권한·버전 정리 |
| 2 | PC | 업로드 키스토어(.jks) 생성, `key.properties` 작성 |
| 3 | 코드 | `build.gradle.kts` 릴리스 서명 설정 |
| 4 | PC | `flutter build appbundle --release` → `.aab` |
| 5 | 웹 | 개인정보처리방침 페이지(URL) 준비 |
| 6 | PC | 스토어 그래픽(아이콘 512, 피처 그래픽 1024x500, 스크린샷) |
| 7 | Play Console | 앱 만들기 |
| 8 | Play Console | 앱 콘텐츠(정책 선언) 전부 완료 |
| 9 | Play Console | 스토어 등록정보·스토어 설정 |
| 10 | Play Console | 비공개 테스트(Alpha) 버전 만들기 → 검토 제출 |
| 11 | Play Console | 프로덕션 버전 만들기 → 검토 제출 → 공개 |
| 12 | Play Console | Android 개발자 인증 패키지 등록 확인 |

> 실제 소요: 비공개 테스트 심사 약 40분, 프로덕션 심사는 보통 수 시간~수 일(최대 7일 안팎).

---

## 1. 코드 준비

### 1-1. 패키지명(applicationId) 확정 — 한 번 정하면 영구 변경 불가
`android/app/build.gradle.kts`

```kotlin
android {
    namespace = "<패키지>"
    defaultConfig {
        applicationId = "<패키지>"
        minSdk = flutter.minSdkVersion
        targetSdk = flutter.targetSdkVersion
        versionCode = flutter.versionCode
        versionName = flutter.versionName
    }
}
```

- `com.example.*`은 Play 업로드가 거부된다. 반드시 본인 도메인/회사명으로.
- Kotlin `MainActivity.kt`의 `package` 선언과 폴더 경로(`android/app/src/main/kotlin/com/...`)도 맞춘다.

### 1-2. 앱 이름
`android/app/src/main/AndroidManifest.xml`

```xml
<application
    android:label="<앱이름>"
    android:name="${applicationName}"
    android:icon="@mipmap/ic_launcher"
    android:allowBackup="false"
    android:fullBackupContent="false">
```

### 1-3. 런처 아이콘
`flutter_launcher_icons` 사용 시 `pubspec.yaml`:

```yaml
dev_dependencies:
  flutter_launcher_icons: ^0.14.0

flutter_launcher_icons:
  android: true
  ios: false
  image_path: assets/icons/app_icon.png        # 1024x1024 권장
  adaptive_icon_background: "#FFFFFF"
  adaptive_icon_foreground: assets/icons/app_icon_fg.png
```

```powershell
C:\Projects\fluttersdk\bin\flutter.bat pub get
C:\Projects\fluttersdk\bin\dart.bat run flutter_launcher_icons
```

### 1-4. 권한 정리 (Play 심사에서 가장 많이 걸리는 부분)
- 필요한 권한만 남긴다. 플러그인이 자동으로 추가한 불필요 권한은 `tools:node="remove"`로 제거.
- 릴리스 빌드에는 `INTERNET`이 자동으로 들어가지 않으므로 네트워크를 쓰면 명시.

```xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <uses-permission android:name="android.permission.INTERNET"/>

    <!-- 로컬 예약 알림을 쓰는 경우 -->
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
    <uses-permission android:name="android.permission.USE_EXACT_ALARM"/>
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.VIBRATE"/>

    <!-- 플러그인이 자동 추가하는 저장소/미디어 권한 제거(안 쓰면 반드시 제거) -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" tools:node="remove"/>
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" tools:node="remove"/>
    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" tools:node="remove"/>
    <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" tools:node="remove"/>
```

- `USE_EXACT_ALARM`을 넣으면 Play Console에서 **정확한 알람 권한 선언**이 필요하다(10단계 참고).
  캘린더·알람시계 앱만 허용되므로, 해당 안 되면 `SCHEDULE_EXACT_ALARM`만 쓰거나 둘 다 빼야 한다.
- 최종 병합된 권한 확인: 릴리스 빌드 후
  `build/app/intermediates/merged_manifest/release/processReleaseMainManifest/AndroidManifest.xml`.

### 1-5. `flutter_local_notifications` 사용 시 추가 설정
`android/app/build.gradle.kts` — core library desugaring:

```kotlin
android {
    compileOptions {
        isCoreLibraryDesugaringEnabled = true
        sourceCompatibility = JavaVersion.VERSION_17
        targetCompatibility = JavaVersion.VERSION_17
    }
}

dependencies {
    coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4")
}
```

`AndroidManifest.xml`의 `<application>` 안에 예약 알림 수신자 등록(없으면 예약 알림이 안 뜬다):

```xml
<receiver android:exported="false"
    android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" />
<receiver android:exported="false"
    android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
        <action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
        <action android:name="android.intent.action.QUICKBOOT_POWERON" />
        <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
    </intent-filter>
</receiver>
```

### 1-6. 출시 전 정리
- 예시/테스트 데이터 자동 생성 코드 제거 → **설치 직후 DB는 빈 상태**여야 한다.
- 디버그용 버튼·로그·테스트 광고 ID 제거.
- 광고를 쓴다면 실제 광고 단위 ID로 교체(그리고 8단계에서 "광고 있음" 선언).

### 1-7. 버전
`pubspec.yaml`

```yaml
version: 1.0.0+1   # <versionName>+<versionCode>
```

- `+` 뒤 숫자(versionCode)는 **업로드할 때마다 반드시 증가**. 같은 번호는 재업로드 불가.
- 한 번 업로드한 versionCode는 삭제해도 재사용 불가.

### 1-8. 검증
```powershell
cd C:\Projects\<앱>
C:\Projects\fluttersdk\bin\flutter.bat analyze
C:\Projects\fluttersdk\bin\flutter.bat test
```

---

## 2. 업로드 키스토어 만들기 (PC, 최초 1회)

PowerShell에서 실행(JDK의 `keytool` 사용. Android Studio 내장 JBR 경로를 써도 됨):

```powershell
keytool -genkey -v `
  -keystore $env:USERPROFILE\<앱>_upload.jks `
  -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 `
  -alias upload
```

- PowerShell에서는 `%USERPROFILE%`가 치환되지 않는다 → `$env:USERPROFILE` 사용.
- `keytool`을 못 찾으면:
  `"C:\Program Files\Android\Android Studio\jbr\bin\keytool.exe" -genkey ...`
- 비밀번호·이름·조직 등을 묻는다. **비밀번호는 별도 안전한 곳(비밀번호 관리자)에 기록.**
- ⚠️ `.jks` 분실/비밀번호 분실 시: Play 앱 서명을 쓰면 Play Console에서 업로드 키 재설정 요청은 가능하지만
  번거롭다. 반드시 백업(클라우드 비공개 폴더 + 외장 저장소).

### 2-1. `android/key.properties` 작성 (Git 커밋 금지)

```properties
storePassword=<키스토어 비밀번호>
keyPassword=<키 비밀번호>
keyAlias=upload
storeFile=C:\\Users\\<사용자>\\<앱>_upload.jks
```

- Windows 경로는 `\\`로 이스케이프하거나 `/` 사용(`C:/Users/<사용자>/<앱>_upload.jks`).
- `android/.gitignore`에 아래가 있는지 확인(Flutter 기본 템플릿에 포함):

```gitignore
key.properties
**/*.keystore
**/*.jks
```

---

## 3. 릴리스 서명 설정

`android/app/build.gradle.kts` 상단과 `android { }` 블록:

```kotlin
import java.util.Properties
import java.io.FileInputStream

plugins {
    id("com.android.application")
    id("kotlin-android")
    id("dev.flutter.flutter-gradle-plugin")
}

// 릴리스 서명 정보(android/key.properties). 없으면 릴리스 빌드 시 서명 실패.
val keystoreProperties = Properties()
val keystorePropertiesFile = rootProject.file("key.properties")
if (keystorePropertiesFile.exists()) {
    keystoreProperties.load(FileInputStream(keystorePropertiesFile))
}

android {
    // ... namespace, compileSdk, defaultConfig ...

    signingConfigs {
        create("release") {
            keyAlias = keystoreProperties["keyAlias"] as String?
            keyPassword = keystoreProperties["keyPassword"] as String?
            storeFile = (keystoreProperties["storeFile"] as String?)?.let { file(it) }
            storePassword = keystoreProperties["storePassword"] as String?
        }
    }

    buildTypes {
        release {
            signingConfig = signingConfigs.getByName("release")
        }
    }
}
```

- Flutter 템플릿 기본값은 `signingConfig = signingConfigs.getByName("debug")` → 그대로 올리면
  "디버그 모드로 서명된 APK/AAB" 오류로 업로드 거부된다.

---

## 4. AAB 빌드

```powershell
cd C:\Projects\<앱>
C:\Projects\fluttersdk\bin\flutter.bat clean
C:\Projects\fluttersdk\bin\flutter.bat pub get
C:\Projects\fluttersdk\bin\flutter.bat build appbundle --release
```

- 산출물: `build/app/outputs/bundle/release/app-release.aab`
- Play에는 APK가 아니라 **AAB**를 올린다.

### 4-1. (선택) 서명 확인
```powershell
keytool -printcert -jarfile build\app\outputs\bundle\release\app-release.aab
```
- 소유자(Owner)가 `CN=Android Debug`이면 디버그 서명 → 3단계 재확인.

### 4-2. (선택) 릴리스 APK로 실기기 사전 확인
```powershell
C:\Projects\fluttersdk\bin\flutter.bat build apk --release
& "$env:LOCALAPPDATA\Android\Sdk\platform-tools\adb.exe" install -r build\app\outputs\flutter-apk\app-release.apk
```

---

## 5. 개인정보처리방침 URL

- 모든 앱에 필수(데이터를 수집하지 않아도 필요).
- 간단히 **Google Sites**로 공개 페이지 생성 → 예: `https://sites.google.com/view/<앱>-privacy`
- 포함할 내용(앱 실제 동작과 일치해야 함):
  - 수집하는 개인정보 항목(없으면 "수집하지 않음")
  - 저장 위치(예: 기기 로컬 DB, 앱 삭제 시 삭제)
  - 외부 전송·제3자 제공·광고·분석 SDK 유무
  - 권한 사용 목적(알림, 네트워크 등)
  - 개발자명, 연락 이메일, 시행일
  - **안드로이드 패키지명 `<패키지>` 명시**(iOS 번들 ID와 다르면 별도 페이지)
- 로그인 없이 누구나 열람 가능한지 시크릿 창에서 확인.

---

## 6. 스토어 그래픽 준비

| 항목 | 규격 | 비고 |
|---|---|---|
| 앱 아이콘 | 512x512 PNG(32-bit), 1MB 이하 | 투명 대신 배경 채움 권장 |
| 그래픽 이미지(피처 그래픽) | 1024x500 PNG/JPG | 필수 |
| 휴대전화 스크린샷 | 최소 2장(권장 4~8장), 9:16 또는 16:9, 각 변 320~3840px | 긴 변이 짧은 변의 2배 이하 |
| 태블릿 스크린샷 | 선택(7인치/10인치) | 태블릿 지원 표시하려면 필요 |

### 6-1. 아이콘 512 생성 스크립트 (Pillow)
`store/gen_icon.py`

```python
# -*- coding: utf-8 -*-
# Play 스토어 앱 아이콘(512x512, 32-bit PNG) — 런처 아이콘 원본에서 생성.
from PIL import Image

SRC = r"C:\Projects\<앱>\assets\icons\app_icon.png"
OUT = r"C:\Projects\<앱>\store\icon_512.png"

im = Image.open(SRC).convert("RGBA")
bg = Image.new("RGBA", im.size, (255, 255, 255, 255))
bg.alpha_composite(im)
bg.resize((512, 512), Image.LANCZOS).save(OUT, "PNG")
print("saved", OUT)
```

```powershell
pip install pillow
python store\gen_icon.py
```

### 6-2. 스크린샷 캡처
```powershell
$adb = "$env:LOCALAPPDATA\Android\Sdk\platform-tools\adb.exe"
& $adb shell screencap -p /sdcard/s1.png
& $adb pull /sdcard/s1.png store\raw\1_home.png
```
- 상태바·내비게이션바를 잘라내고, 캡션/배경을 입힌 홍보용 이미지로 가공하면 좋다
  (day_plan_app은 `store/gen_shots.py`로 1500x1825 이미지 6장 생성).
- 스크린샷에 **테스트/예시용 메뉴나 개인정보가 보이지 않게** 확인.

---

## 7. Play Console — 앱 만들기

전제: Google Play 개발자 계정(등록비 25달러, 본인 인증 완료).

1. [Play Console](https://play.google.com/console) → **모든 앱 → 앱 만들기**
2. 입력
   - 앱 이름: `<앱이름>`
   - 기본 언어: 한국어 – ko-KR
   - 앱 또는 게임: 앱
   - 무료 또는 유료: 무료(⚠️ 무료로 출시하면 나중에 유료로 바꿀 수 없음)
3. 선언 체크: **개발자 프로그램 정책** ✔, **미국 수출 법규** ✔ (둘 다 체크해야 만들기 가능)
4. **앱 만들기**

> 패키지명은 이 단계가 아니라 **첫 AAB 업로드 시점에 확정**된다.

---

## 8. Play Console — 앱 콘텐츠(정책 선언)

왼쪽 메뉴 **정책 및 프로그램 → 앱 콘텐츠**(또는 대시보드의 "앱 설정" 체크리스트). 모두 완료해야 출시 가능.

| 항목 | day_plan_app에서 고른 값 / 요령 |
|---|---|
| 개인정보처리방침 | 5단계 URL 입력 |
| 앱 액세스 권한 | 로그인 없이 전체 기능 사용 → "모든 기능을 특별한 액세스 권한 없이 사용 가능" |
| 광고 | 광고 SDK 없으면 "아니요, 광고가 없습니다" (AdMob 등 있으면 "예") |
| 콘텐츠 등급 | 설문: 카테고리 "기타 앱 유형"(유틸리티/생산성), 폭력·성·도박 등 모두 "아니요" → 전체이용가 |
| 타겟층 및 콘텐츠 | 대상 연령: **18세 이상**(또는 13세 이상) 선택. 13세 미만 포함 시 가족 정책 추가 심사 |
| 뉴스 앱 | 아니요 |
| 코로나19 접촉자 추적 | 해당 없음 |
| 데이터 보안 | 아래 8-1 참고 |
| 정부 앱 | 아니요 |
| 금융 기능 | 해당 없음 |
| 건강 | 해당 없음(건강 기능 없을 때) |
| 광고 ID | 광고 SDK 없고 `AD_ID` 권한 없으면 "아니요" |

### 8-1. 데이터 보안(Data Safety) — 서버 없는 로컬 앱 기준
1. "앱에서 필수 사용자 데이터 유형을 수집하거나 공유하나요?" → **아니요**
   - 기기 안에서만 처리하고 개발자 서버로 전송하지 않으면 "수집"이 아니다.
   - 서버 동기화·로그인·분석(Firebase Analytics 등)·크래시 리포트·광고 SDK가 있으면 **예**로 하고 항목별 선언.
2. 다음 → 미리보기 확인 → **저장**

> 보안 관행 질문(전송 중 암호화, 삭제 요청 방법)이 나오면 실제와 맞게 답한다.
> 데이터 미수집 앱은 해당 질문이 생략된다.

---

## 9. Play Console — 스토어 등록정보 / 스토어 설정

### 9-1. 기본 스토어 등록정보 (메뉴: 사용자 늘리기 → 스토어 등록정보)
- 앱 이름(30자), 간단한 설명(80자), 자세한 설명(4000자)
- 그래픽: 앱 아이콘(512), 그래픽 이미지(1024x500), 휴대전화 스크린샷(2장 이상)
- **저장**

> "일부 언어에 오류" 표시가 뜨면, 해당 언어(ko-KR)에 필수 그래픽/문구가 빠진 것.
> 에셋 라이브러리에 업로드만 하고 **슬롯(아이콘/그래픽 이미지/스크린샷)에 지정하지 않은** 경우가 많다
> → 각 슬롯의 "에셋 추가 → 라이브러리에서 선택"으로 지정 후 저장.

### 9-2. 스토어 설정 (메뉴: 사용자 늘리기 → 스토어 설정)
- 앱 카테고리: 예) **생산성**
- 태그(선택), 연락처 이메일(필수, 공개됨), 웹사이트(선택)
- **저장**

---

## 10. 비공개 테스트(Alpha) 출시

> **12명 / 14일 규칙**: 2023-11-13 이후 생성된 **개인** 개발자 계정은 프로덕션 출시 전에
> "테스터 12명 이상이 14일 연속 참여한 비공개 테스트"가 필요하다.
> 확인법: **테스트 및 출시 → 프로덕션** 화면에서 "새 버전 만들기"가 비활성이고
> "프로덕션 액세스 신청" 안내가 보이면 대상. 버튼이 바로 활성이면 대상 아님(조직 계정·구 계정).
> 대상이 아니어도 비공개 테스트로 먼저 실기기 검증하는 것을 권장한다.

### 10-1. 테스터 목록
1. **테스트 및 출시 → 테스트 → 비공개 테스트 → Alpha(기본 트랙) → 트랙 관리**
2. **테스터** 탭 → 이메일 목록 만들기 → 이름(예: `모담 하루계획 테스트`), 테스터 Gmail 추가 → 저장
3. 피드백 URL 또는 이메일 입력(예: 개발자 이메일)

### 10-2. 국가/지역
- **국가/지역** 탭 → 국가 추가 → **대한민국** 체크 → 저장

### 10-3. 새 버전 만들기
1. **출시** 탭 → **새 버전 만들기**
2. **Play 앱 서명**: 처음 한 번 "Google에서 앱 서명 키 관리(권장)" 선택 → 계속
   - 이후 Google이 최종 서명키를 보관, 우리는 업로드 키(.jks)로만 서명해서 올림.
3. **App Bundle 업로드** → `app-release.aab` 드래그
   - 업로드되면 `1 (1.0.0)` / API 수준 / 타겟 SDK가 표에 나타난다.
4. 출시명: 자동(`1 (1.0.0)`) 그대로
5. 출시 노트(언어 태그 필수):

```text
<ko-KR>
<앱이름> 첫 출시
- 핵심 기능 1
- 핵심 기능 2
- 핵심 기능 3
</ko-KR>
```

6. **다음** → 미리보기 및 확인
   - 오류(빨강)는 반드시 해결, 경고(노랑)는 대부분 진행 가능.
7. **저장** → 팝업 "게시 개요로 이동"

### 10-4. 업로드 시 자주 나오는 오류
| 오류 | 원인 / 해결 |
|---|---|
| 디버그 모드로 서명됨 | 3단계 `signingConfig` release 확인 후 재빌드 |
| 버전 코드 N은 이미 사용됨 | `pubspec.yaml` `+N` 증가 후 재빌드 |
| 패키지 이름 com.example 사용 불가 | 1-1 applicationId 변경 |
| 정확한 알람 권한(USE_EXACT_ALARM) 선언 필요 | 앱 콘텐츠의 **정확한 알람** 선언에서 앱 유형 **캘린더** 또는 **알람 시계** 선택 후 저장 |
| 타겟 API 수준 요구사항 미달 | Flutter SDK 업데이트(targetSdk는 `flutter.targetSdkVersion`) |

### 10-5. 검토 제출
1. **게시 개요** → "변경사항이 아직 검토를 위해 제출되지 않음" 목록 확인
   (비공개 테스트 출시, 스토어 등록정보, 앱 콘텐츠, 스토어 설정 등)
2. **검토를 위해 변경사항 N개 제출**
   - "빠른 검사 실행 중(최대 14분)"이 떠도 그냥 제출하면 검사 후 자동 전송된다.
3. 관리형 게시: **사용 중지됨**이면 승인 즉시 자동 게시. 공개 시점을 직접 정하려면 제출 전에 켠다.

### 10-6. 승인 후 테스터 설치
1. Alpha → **테스터** 탭 → "테스터 참여 방법"의 **웹에서 참여** 링크 복사
2. 테스터 목록에 있는 Gmail 계정으로 폰에서 링크 열기 → **테스터 되기** → Play 스토어에서 설치
3. 확인 항목: 첫 실행 시 데이터가 비어 있는지, 알림이 정시에 오는지, 권한 요청 흐름, 주요 기능

---

## 11. 프로덕션 출시

### 방법 A (권장) — 비공개 테스트 버전 승격
- **비공개 테스트 → Alpha → 출시** 탭 → 해당 버전 오른쪽 **버전 승격 ▼ → 프로덕션**
- ⚠️ 프로덕션 트랙에 이미 **임시(draft) 버전**이 있으면 "트랙에 이미 임시 버전이 있음"으로 승격이
  비활성화된다 → 방법 B로 그 임시 버전을 제출하거나, 임시 버전을 삭제 후 승격.

### 방법 B — 프로덕션에서 직접 만들기
1. **테스트 및 출시 → 프로덕션 → 새 버전 만들기**(또는 임시 버전의 **버전 수정**)
2. App Bundle: **라이브러리에서 추가** → 이미 올린 `1 (1.0.0)` 선택
   (같은 파일을 "업로드"로 다시 올리면 버전 코드 중복 오류)
3. 상단 "개선사항 N개 중 M개 활성"(Play 앱 서명/자동 보호/자동 번역)은 정보 표시 → 그대로 두면 됨
4. 출시명/출시 노트(**이전 버전에서 복사** 가능) → **다음** → **저장**
5. **국가/지역** 탭 → 대한민국 추가 → 저장

### 11-1. 검토 제출 & ⚠️ 함정
1. **게시 개요** 목록에 반드시 아래 줄이 있어야 한다:
   - `프로덕션 · 1 (1.0.0) · 전체 출시 시작`
2. **검토를 위해 변경사항 제출**

> ⚠️ day_plan_app에서 실제로 겪은 문제: 프로덕션 버전을 "임시"로만 만들어 둔 채
> 국가/지역만 저장하고 제출했더니, 제출 내용이 **국가 추가뿐**이었다.
> 제출 활동에 "출시됨"으로 떠도 앱 버전은 공개되지 않아 스토어 검색이 안 됐다.
> → **프로덕션 → 출시 탭**에서 버전 상태가 "임시"가 아닌지, 게시 개요 목록에
> "전체 출시 시작" 줄이 있는지 꼭 확인할 것.

### 11-2. 공개 여부 확인
- **게시 개요 → 제출 활동**: 프로덕션 제출이 "검토 중" → **출시됨**
  (→ 화살표로 각 제출에 무엇이 포함됐는지 확인 가능)
- **프로덕션** 트랙 요약: 비활성 → **활성**, 버전에 "사용자에게 제공됩니다"
- 알림(🔔)·이메일: "앱 업데이트가 게시되었습니다"
- 실제 스토어: 테스터가 아닌 계정/시크릿 창에서
  `https://play.google.com/store/apps/details?id=<패키지>`
  - 검색 노출까지 수 시간~하루 더 걸릴 수 있다.

---

## 12. 계정/정책 알림 처리

| 알림 | 처리 |
|---|---|
| Android 개발자 인증: 앱(패키지) 등록 | 왼쪽 계정 메뉴 **Android 개발자 인증** → 패키지 목록에서 `<패키지>`가 **등록됨**인지 확인. 없으면 **패키지 이름 등록** |
| 휴면 계정(비활성으로 해지 위험) | **개발자 계정**에서 이메일·전화번호 인증 + 앱 게시(프로덕션 출시되면 해소) |
| 정책 위반 / 거부 | 제출 활동 → 해당 제출 → 사유 확인 → 수정 후 versionCode 올려 재제출 |

---

## 13. 업데이트(재출시) 절차

```powershell
# 1) pubspec.yaml 버전 올리기: 1.0.0+1 → 1.0.1+2 (versionCode는 반드시 증가)
# 2) 검증
C:\Projects\fluttersdk\bin\flutter.bat analyze
C:\Projects\fluttersdk\bin\flutter.bat test
# 3) 빌드
C:\Projects\fluttersdk\bin\flutter.bat build appbundle --release
```

4. Play Console
   - 테스트 먼저: 비공개 테스트 → Alpha → **새 버전 만들기** → 업로드 → 저장 → 제출 → 확인 후 **버전 승격 → 프로덕션**
   - 바로 배포: 프로덕션 → **새 버전 만들기** → 업로드 → 출시 노트 → 저장 → 게시 개요에서 제출
5. 업데이트 심사는 보통 첫 출시보다 빠르다(수 시간~하루).

> 프로덕션 버전이 검토 중일 때 새 프로덕션 버전을 제출하면 기존 검토가 새 버전으로 대체된다.

---

## 14. 체크리스트 (복사해서 사용)

```text
[코드]
[ ] applicationId / namespace 확정 (com.example 아님)
[ ] android:label 앱 이름, 런처 아이콘
[ ] 불필요 권한 제거, 필요한 권한만 (INTERNET 명시)
[ ] 예시/테스트 데이터·디버그 코드 제거 (설치 시 빈 DB)
[ ] pubspec version x.y.z+N
[ ] flutter analyze / flutter test 통과

[서명/빌드]
[ ] 업로드 키스토어(.jks) 생성 + 비밀번호 안전 보관 + 백업
[ ] android/key.properties 작성 (gitignore 확인)
[ ] build.gradle.kts release signingConfig
[ ] flutter build appbundle --release 성공

[준비물]
[ ] 개인정보처리방침 URL (패키지명 명시, 공개 열람 가능)
[ ] 아이콘 512, 피처 그래픽 1024x500, 휴대전화 스크린샷 2장+
[ ] 간단한 설명(80자) / 자세한 설명 / 연락처 이메일

[Play Console]
[ ] 앱 만들기 (정책·수출 법규 체크)
[ ] 앱 콘텐츠 전 항목 (개인정보, 액세스, 광고, 등급, 타겟층, 데이터 보안, 정부앱, 금융, 건강, 광고ID)
[ ] 정확한 알람 권한 선언 (USE_EXACT_ALARM 사용 시)
[ ] 스토어 등록정보 (그래픽 슬롯 지정 확인) / 스토어 설정
[ ] 비공개 테스트: 테스터 목록, 국가, Play 앱 서명, AAB, 출시 노트 → 제출
[ ] 테스터 설치 확인 (빈 DB, 알림, 권한)
[ ] 프로덕션: 버전(임시 아님) + 국가 → 게시 개요에 "전체 출시 시작" 확인 → 제출
[ ] Android 개발자 인증 패키지 "등록됨"
[ ] 제출 활동 "출시됨" + 스토어 링크로 공개 확인
```

---

## 부록. 이 PC 환경 메모
- Flutter SDK: `C:\Projects\fluttersdk\bin\flutter.bat` (`C:\fluttersdk`는 없음)
- adb: `%LOCALAPPDATA%\Android\Sdk\platform-tools\adb.exe`
- day_plan_app 실제 값
  - 패키지: `com.modamtech.day_plan_app`, 업로드 키: `C:\Users\Elijah\day_plan_upload.jks`(alias `upload`)
  - 개인정보처리방침: https://sites.google.com/view/dayplanapp-privacy
  - 스토어 그래픽 스크립트: `store/gen_icon.py`, `store/gen_feature.py`, `store/gen_shots.py`
  - 일정: 2026-09-30 비공개 테스트 제출(약 40분 후 출시됨) → 2026-10-01 프로덕션 제출(검토 중)
