Flutter 앱을 Google Play 스토어에 출시하는 과정
Flutter 앱을 Google Play에 처음 올릴 때 거치는 과정을 개발자 계정 등록부터 심사 제출까지 순서대로 정리했어요.
1. 시작하기 전에 알아야 할 것들
Flutter 앱을 만들었다고 바로 스토어에 올릴 수 있는 것은 아니에요. 출시 전에 반드시 준비해야 할 것들이 있어요.
필요한 것 목록
| 항목 | 설명 |
|---|---|
| Google 계정 | Play Console 가입에 사용할 Google 계정 |
| 등록비 $25 | 일회성 비용, 한 번만 내면 평생 사용 |
| 신용카드 또는 체크카드 | 등록비 결제용 (해외 결제 가능해야 함) |
| 앱 서명 키 (Keystore) | 앱에 서명하는 키를 담은 파일 |
| 스토어 등록용 이미지 | 스크린샷, 아이콘, 그래픽 이미지 등 |
| 개인정보처리방침 URL | 앱이 어떤 개인정보를 수집하는지 안내하는 페이지 |
왜 이런 것들이 필요할까?
Google Play 스토어는 전 세계 수십억 명이 사용하는 앱 마켓이에요. 악의적인 앱이 올라오는 것을 방지하고, 사용자를 보호하기 위해 개발자 인증, 앱 서명, 심사 과정 등을 거치게 되어 있어요.
2. Google Play Console 개발자 계정 등록
2-1. Play Console 접속
브라우저에서 Google Play Console 가입 페이지에 접속해요.
Google 계정으로 로그인해요. 이 계정이 앞으로 앱을 관리하는 개발자 계정이 되므로, 개인용 계정보다는 앱 관리 전용 계정을 만드는 것을 권장해요.
2-2. 개발자 계정 유형 선택
두 가지 유형이 있어요.
- 개인 계정: 개인 개발자로 등록해요. 본인 이름과 연락처 정보가 필요해요.
- 조직 계정: 회사나 단체 이름으로 등록해요. 사업자등록번호 등 조직 증빙이 필요하며, DUNS 번호 인증을 거쳐야 해서 시간이 더 걸려요.
[참고] 개인 개발자라면 "개인 계정"을 선택하세요. 나중에 조직 계정으로 변경할 수도 있어요.
2-3. 개발자 정보 입력
다음 정보를 입력해요.
- 개발자 이름: 스토어에 공개적으로 표시되는 이름이에요. 본명 또는 브랜드명을 사용해요.
- 이메일 주소: 사용자 문의를 받을 이메일이에요. 스토어에 공개돼요.
- 전화번호: 본인 인증에 사용돼요. 실제로 문자를 받을 수 있는 번호여야 해요.
- 웹사이트 (선택): 개발자 웹사이트가 있다면 입력해요.
2-4. 본인 인증
Google은 2023년부터 개인 계정에 대해서도 본인 인증을 요구해요. 신분증 사진 업로드 또는 주소 인증 절차가 필요할 수 있어요. 인증 완료까지 며칠이 걸릴 수 있으니 여유를 두고 진행하세요.
2-5. 등록비 $25 결제
- 일회성 비용이에요. Apple Developer Program은 매년 $99예요.
- 해외 결제가 가능한 신용카드 또는 체크카드가 필요해요.
2-6. 계정 활성화 확인
결제가 완료되면 Play Console 대시보드에 접근할 수 있게 돼요. "모든 앱" 페이지가 보이면 정상적으로 등록된 거예요.
[주의] 계정 등록 후 바로 앱을 업로드하기보다, 먼저 앱 빌드 준비를 끝내고 나서 업로드하는 것이 순서상 편해요. 아래 과정을 먼저 진행하세요.
3. 앱 서명 키(Keystore) 생성
Keystore가 뭔가요?
Keystore는 앱에 서명하는 키를 담은 파일이에요. Google Play는 같은 키로 서명된 빌드만 기존 앱의 업데이트로 받아요. 그래서 서명 키가 없는 사람은 같은 패키지명으로 업데이트를 올릴 수 없어요.
잃어버리면 어떻게 되나요
2021년 8월 이후 새 앱은 Play 앱 서명(7-3)이 필수라서, 여기서 만드는 키는 업로드 키가 돼요. 업로드 키를 잃어버리면 Play Console에서 업로드 키 재설정을 요청할 수 있어요. 재설정에는 시간이 걸리니 안전한 곳에 백업하세요.
3-1. keytool 명령어로 Keystore 생성
터미널(또는 명령 프롬프트)을 열고 아래 명령어를 실행해요.
keytool -genkey -v -keystore ~/upload-keystore.jks -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 -alias upload
각 옵션의 의미를 설명할게요.
| 옵션 | 설명 |
|---|---|
-genkey | 새로운 키 쌍(공개키 + 개인키)을 생성해요 |
-v | 상세한 출력을 보여줘요 (verbose) |
-keystore ~/upload-keystore.jks | 키가 저장될 파일 경로와 이름이에요. 경로는 원하는 곳으로 바꿀 수 있어요 |
-storetype JKS | Java KeyStore 형식으로 저장해요 |
-keyalg RSA | RSA 알고리즘으로 키를 만들어요 |
-keysize 2048 | 키의 길이를 2048비트로 설정해요 |
-validity 10000 | 키의 유효 기간을 10,000일(약 27년)로 설정해요. Android 문서는 25년 이상을 권장해요 |
-alias upload | 키의 별칭이에요. 나중에 이 이름으로 키를 참조해요 |
3-2. 정보 입력
명령어를 실행하면 아래 정보를 차례로 물어요.
키 저장소 비밀번호 입력: (비밀번호를 입력해요. 화면에 표시되지 않으니 정확히 입력하세요)
새 비밀번호 다시 입력: (같은 비밀번호를 한 번 더 입력해요)
이름과 성을 입력하십시오.
[Unknown]: Hong Gildong
조직 단위 이름을 입력하십시오.
[Unknown]: Development
조직 이름을 입력하십시오.
[Unknown]: MyCompany
구/군/시 이름을 입력하십시오.
[Unknown]: Seoul
시/도 이름을 입력하십시오.
[Unknown]: Seoul
이 조직의 두 자리 국가 코드를 입력하십시오.
[Unknown]: KR
마지막에 입력한 정보가 맞는지 확인을 요청해요. y를 입력하면 돼요.
[참고] 여기서 입력하는 이름, 조직 등의 정보는 스토어에 공개되지 않아요. 키 안에 기록되는 정보예요. 다만 비밀번호는 반드시 기억하세요.
3-3. 생성 확인
명령어가 완료되면 지정한 경로에 .jks 파일이 생성돼요.
ls -la ~/upload-keystore.jks
파일이 존재하면 성공이에요. 이 파일을 안전한 곳에 백업해 두세요. 클라우드 스토리지, USB 드라이브 등 여러 곳에 보관하는 것을 권장해요.
[주의] 이 keystore 파일은 절대 Git에 커밋하지 마세요.
.gitignore에 반드시 추가해야 해요.
4. key.properties 파일 생성
key.properties가 뭔가요?
Keystore의 비밀번호와 파일 경로 같은 민감한 정보를 코드에 직접 쓰면 위험해요. 누군가 코드를 보면 비밀번호를 알 수 있으니까요. 그래서 이 정보를 별도 파일에 저장하고, 빌드 시에만 참조하도록 해요. 이 파일이 key.properties예요.
4-1. 파일 생성
프로젝트의 android 폴더 안에 key.properties 파일을 만들어요.
# 프로젝트 루트에서 실행
touch android/key.properties
4-2. 내용 작성
텍스트 편집기로 android/key.properties 파일을 열고 아래 내용을 입력해요.
storePassword=여기에_키저장소_비밀번호
keyPassword=여기에_키_비밀번호
keyAlias=upload
storeFile=/Users/사용자이름/upload-keystore.jks
각 항목의 의미는 다음과 같아요.
| 항목 | 설명 |
|---|---|
storePassword | Keystore 파일 자체의 비밀번호 (3-2에서 설정한 것) |
keyPassword | 키 항목의 비밀번호 (보통 storePassword와 같게 설정) |
keyAlias | 키 생성 시 -alias 옵션에 지정한 이름 |
storeFile | Keystore 파일의 절대 경로 |
[주의]
storeFile의 경로를 정확히 입력해야 해요. macOS라면/Users/사용자이름/upload-keystore.jks, Windows라면C:\\Users\\사용자이름\\upload-keystore.jks형태예요. Windows에서는 역슬래시를 두 개(\\) 쓰거나 슬래시(/)로 바꿔야 해요.
4-3. .gitignore에 추가
이 파일에는 비밀번호가 들어있으므로 절대 Git에 올라가면 안 돼요. android/.gitignore 파일을 열어서 아래 줄을 추가해요.
key.properties
확인 방법:
# 프로젝트 루트에서 실행
git status
key.properties가 "Untracked files" 목록에 나타나지 않으면 .gitignore가 정상 작동하는 거예요.
5. build.gradle.kts 서명 설정
왜 build.gradle.kts를 수정해야 하나요?
Flutter 프로젝트를 처음 만들면 디버그 키로 서명되도록 설정되어 있어요. 디버그 키는 개발 중 테스트용이고, 스토어에 올리려면 위에서 만든 우리만의 키로 서명해야 해요. build.gradle.kts 파일에서 "릴리스 빌드 시 어떤 키로 서명할지"를 지정해주는 거예요.
[참고] 최근 Flutter 프로젝트는 Kotlin DSL 방식의
build.gradle.kts를 기본으로 써요. 인터넷 검색 시 Groovy 방식의build.gradle예제가 나올 수 있는데, 문법이 다르므로 주의하세요.
5-1. 수정 전 원본 확인
android/app/build.gradle.kts 파일의 원본은 대략 아래와 같아요.
plugins {
id("com.android.application")
id("kotlin-android")
id("dev.flutter.flutter-gradle-plugin")
}
android {
namespace = "com.example.just_qr"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.toString()
}
defaultConfig {
applicationId = "com.example.just_qr"
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}
buildTypes {
release {
signingConfig = signingConfigs.getByName("debug")
}
}
}
flutter {
source = "../.."
}
5-2. 수정된 전체 코드
아래와 같이 수정해요. 변경된 부분에 주석을 달아 두었어요.
import java.util.Properties // [추가] Properties 클래스 임포트
plugins {
id("com.android.application")
id("kotlin-android")
id("dev.flutter.flutter-gradle-plugin")
}
// [추가] key.properties 파일 읽기
val keystoreProperties = Properties()
val keystorePropertiesFile = rootProject.file("key.properties")
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(keystorePropertiesFile.inputStream())
}
android {
namespace = "com.example.just_qr"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.toString()
}
// [추가] 서명 설정 정의
signingConfigs {
create("release") {
keyAlias = keystoreProperties["keyAlias"] as String
keyPassword = keystoreProperties["keyPassword"] as String
storeFile = file(keystoreProperties["storeFile"] as String)
storePassword = keystoreProperties["storePassword"] as String
}
}
defaultConfig {
applicationId = "com.example.just_qr"
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}
buildTypes {
release {
// [변경] debug 서명 -> release 서명으로 변경
signingConfig = signingConfigs.getByName("release")
}
}
}
flutter {
source = "../.."
}
5-3. 변경 내용 상세 설명
1) Properties 임포트와 key.properties 읽기
import java.util.Properties
val keystoreProperties = Properties()
val keystorePropertiesFile = rootProject.file("key.properties")
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(keystorePropertiesFile.inputStream())
}
Properties는 Java의.properties파일을 읽는 클래스예요.rootProject.file("key.properties")로android/key.properties파일을 찾아요.if (keystorePropertiesFile.exists())로 파일이 있을 때만 읽어요. 다만 파일이 없으면 아래 signingConfigs의as String이 null을 만나 Gradle 설정 단계에서 실패해요. 그래서 key.properties가 없는 환경(예: CI 서버, 다른 팀원의 PC)에서는 디버그 빌드도 깨져요. 그런 환경도 빌드하려면 signingConfigs 블록도 파일이 있을 때만 만들도록 감싸야 해요.
2) signingConfigs 블록
signingConfigs {
create("release") {
keyAlias = keystoreProperties["keyAlias"] as String
keyPassword = keystoreProperties["keyPassword"] as String
storeFile = file(keystoreProperties["storeFile"] as String)
storePassword = keystoreProperties["storePassword"] as String
}
}
create("release")로 "release"라는 이름의 서명 설정을 새로 만들어요.key.properties에서 읽어온 값들을 각 속성에 매핑해요.storeFile은file(...)함수로 감싸서 File 객체로 변환해야 해요.
3) buildTypes에서 서명 설정 변경
buildTypes {
release {
signingConfig = signingConfigs.getByName("release")
}
}
- 기존에
"debug"로 되어 있던 것을"release"로 바꿔요. - 이제 릴리스 빌드 시 우리가 만든 keystore로 서명돼요.
5-4. applicationId 변경 (중요)
위 코드에서 applicationId가 "com.example.just_qr"로 되어 있어요. com.example로 시작하는 패키지명은 Google Play에 등록할 수 없어요. 반드시 고유한 패키지명으로 변경해야 해요.
applicationId = "com.여러분의도메인.just_qr"
예를 들어:
com.honggildong.justqrkr.co.mycompany.justqr
[주의] applicationId는 한 번 스토어에 등록하면 바꿀 수 없어요. 보통 본인이 소유한 도메인의 역순을 써요. 도메인이 없다면
io.github.깃허브아이디.앱이름형태를 많이 써요.
최신 Flutter 템플릿은 AndroidManifest.xml에 package 속성이 없고, 패키지명은 build.gradle.kts의 namespace와 applicationId로 정해져요. namespace를 바꾸면 MainActivity.kt의 package 선언과 폴더 위치도 맞춰야 해요.
6. 릴리스 빌드 만들기
AAB vs APK
Google Play 스토어는 2021년 8월부터 새 앱은 AAB(Android App Bundle) 형식으로 제출해야 해요.
| 형식 | 용도 |
|---|---|
| APK | 기기에 직접 설치하거나 테스트용. 스토어 제출 불가 (신규 앱 기준) |
| AAB | Google Play 스토어 제출용. Google이 사용자 기기에 맞는 최적화된 APK를 자동 생성 |
AAB를 사용하면 앱 용량이 줄어들어요. Google이 각 기기에 필요한 리소스만 골라서 APK를 만들어주기 때문이에요.
6-1. 빌드 전 점검
빌드하기 전에 아래 사항을 확인하세요.
# Flutter 환경이 정상인지 확인
flutter doctor
# 패키지가 모두 설치되어 있는지 확인
flutter pub get
# 코드에 에러가 없는지 확인
flutter analyze
6-2. AAB 빌드 실행
프로젝트 루트 디렉토리에서 아래 명령어를 실행해요.
flutter build appbundle --release
성공하면 아래와 같은 메시지가 나타나요.
Built build/app/outputs/bundle/release/app-release.aab
6-3. 빌드 결과물 확인
생성된 AAB 파일은 아래 경로에 있어요.
build/app/outputs/bundle/release/app-release.aab
이 파일이 Google Play Console에 업로드할 파일이에요.
6-4. 빌드 실패 시 확인할 것들
빌드가 실패하면 아래 사항을 확인하세요.
key.properties파일의 경로와 비밀번호가 정확한가?- Keystore 파일이 지정한 경로에 실제로 존재하는가?
build.gradle.kts문법에 오타가 없는가?flutter clean후 다시 빌드해보기
# 빌드 캐시를 모두 지우고 다시 빌드
flutter clean
flutter pub get
flutter build appbundle --release
6-5. 버전 관리
pubspec.yaml 파일에서 앱의 버전을 관리해요.
version: 1.0.0+1
1.0.0부분은versionName이에요. 사용자에게 보이는 버전 번호예요.+1부분은versionCode예요. 스토어 내부에서 사용하는 정수값으로, 업데이트할 때마다 반드시 이전보다 큰 숫자여야 해요.
업데이트할 때는 이렇게 올려요:
version: 1.0.1+2 # 버그 수정
version: 1.1.0+3 # 기능 추가
version: 2.0.0+4 # 대규모 변경
[주의]
versionCode(+ 뒤의 숫자)를 올리는 것을 잊으면 업로드가 거부돼요. 매 업로드마다 반드시 이전보다 큰 값이어야 해요.
7. Play Console에서 앱 만들기 및 AAB 업로드
7-1. 앱 만들기
- Google Play Console에 로그인해요.
- 왼쪽 상단의 "모든 앱" 페이지에서 "앱 만들기" 버튼을 클릭해요.
- 아래 정보를 입력해요:
- 앱 이름: 스토어에 표시될 앱 이름 (나중에 변경 가능)
- 기본 언어: 한국어
- 앱 또는 게임: 앱
- 유료 또는 무료: 무료 (무료로 출시한 앱은 나중에 유료로 바꿀 수 없어요)
- 개발자 프로그램 정책과 미국 수출 법규에 동의해요.
- "앱 만들기" 버튼을 클릭해요.
7-2. 대시보드 이해하기
앱을 만들면 대시보드가 나타나요. 왼쪽 메뉴에 여러 항목이 있는데, 앱을 출시하기 위해 채워야 할 항목들이 있어요. 대시보드 상단에 "앱을 출시하기 전에 완료해야 할 작업"이 표시되니 하나씩 진행하면 돼요.
7-3. 앱 서명 설정
Play Console에서 앱 서명 설정 페이지로 이동해요 (메뉴 위치는 Play Console 개편에 따라 바뀌어 왔어요).
Google Play 앱 서명을 사용하면 Google이 앱 서명 키를 안전하게 관리해줘요. 우리가 만든 키는 "업로드 키"로 사용되고, Google이 별도의 "앱 서명 키"를 생성하여 실제 사용자에게 배포되는 앱에 서명해요.
[참고] 새 앱은 Google Play 앱 서명이 필수예요. 업로드 키와 앱 서명 키가 나뉘어 있어서, 업로드 키를 분실해도 Play Console에서 재설정을 요청해 새 업로드 키를 등록할 수 있어요.
7-4. AAB 파일 업로드
- 왼쪽 메뉴에서 "출시" > "프로덕션"을 클릭해요. 새 개인 계정이라면 프로덕션이 아직 잠겨 있으니 "비공개 테스트" 트랙에서 시작해요 (7-5).
- "새 버전 만들기" 버튼을 클릭해요.
- "App Bundle" 섹션에서 AAB 파일을 업로드해요. 아까 빌드한
app-release.aab파일을 드래그하거나 파일 선택으로 업로드해요. - 업로드가 완료되면 버전 코드와 버전 이름이 자동으로 표시돼요.
- "출시 노트"를 작성해요. 사용자에게 보여줄 "새로운 기능" 안내예요.
예시:
<ko-KR>
- 첫 번째 릴리스
- QR 코드 생성 및 스캔 기능
</ko-KR>
- "저장"을 클릭해요. 아직 "출시 검토"를 누르지 마세요. 스토어 등록 정보를 먼저 작성해야 해요.
[참고] 처음이라면 "내부 테스트" 트랙에 먼저 올려서 테스트하는 걸 권장해요. 내부 테스트는 지정한 이메일 주소의 사용자만 앱을 설치할 수 있어서, 문제가 있어도 일반 사용자에게 노출되지 않아요.
7-5. 새 개인 계정은 비공개 테스트가 먼저예요
2023년 11월 13일 이후에 만든 개인 개발자 계정은 바로 프로덕션에 출시할 수 없어요. 먼저 비공개 테스트를 열고, 테스터 12명 이상이 14일 이상 계속 참여한 뒤에 대시보드에서 프로덕션 액세스를 신청해요. 그전까지 프로덕션 트랙은 비활성화돼 있어요.
8. 스토어 등록 정보 작성
스토어 등록 정보는 사용자가 Play 스토어에서 여러분의 앱을 검색했을 때 보게 되는 모든 정보예요.
8-1. 기본 스토어 등록 정보
왼쪽 메뉴에서 "스토어 등록 정보" > "기본 스토어 등록 정보"로 이동해요.
앱 이름 (최대 30자)
좋은 예: Just QR - 빠른 QR 코드 리더
나쁜 예: QR코드리더스캐너생성기무료최고 (키워드 나열)
[주의] 앱 이름에 키워드를 과도하게 넣으면 Google 정책 위반으로 거부될 수 있어요.
간단한 설명 (최대 80자)
앱 이름 아래에 표시되는 한 줄 설명이에요.
예: QR 코드를 빠르고 간편하게 스캔하고 생성하세요
자세한 설명 (최대 4,000자)
앱의 기능과 특징을 상세히 적어요. 검색 최적화(ASO)를 위해 핵심 키워드를 자연스럽게 포함하세요.
예시:
Just QR은 QR 코드 스캔과 생성을 한 번에 할 수 있는 깔끔한 앱입니다.
주요 기능:
- 카메라로 QR 코드 즉시 스캔
- URL, 텍스트, 연락처 등 다양한 형식의 QR 코드 생성
- 생성한 QR 코드를 갤러리에 저장
- 깔끔하고 직관적인 인터페이스
...
8-2. 그래픽 에셋 (이미지)
스토어에 표시될 이미지들을 준비해야 해요.
앱 아이콘 (필수)
- 크기: 512 x 512 픽셀
- 형식: PNG (32비트, 알파 포함 가능)
- Flutter 프로젝트의 앱 아이콘과 동일한 디자인을 고해상도로 준비해요.
그래픽 이미지 (Feature Graphic) (필수)
- 크기: 1024 x 500 픽셀
- Play 스토어의 여러 곳에 배너로 쓰여요.
- 앱의 핵심 기능을 보여주는 배너 이미지를 만드세요.
- Figma, Canva 등 무료 도구로 만들 수 있어요.
스크린샷 (필수)
- 최소 2장, 최대 8장
- 휴대전화 스크린샷: 최소 2장 필수
- 형식: JPEG 또는 24비트 PNG (알파 없음)
- 한 변 최소 320px, 최대 3840px. 긴 변이 짧은 변의 두 배를 넘으면 안 돼요
- 실제 앱 화면을 캡처하거나, 디바이스 프레임을 씌운 목업 이미지를 사용해요.
- 앱의 핵심 기능이 잘 드러나는 화면들을 선택하세요.
스크린샷을 찍는 방법:
# Flutter 앱 실행 후 에뮬레이터에서 스크린샷 찍기
flutter run
# 또는 실제 기기에서 캡처
# Android: 전원 버튼 + 볼륨 다운 버튼 동시 누르기
[참고] 스크린샷에 설명 텍스트를 넣으려면 Figma나 Canva에서 "앱 스토어 스크린샷 템플릿"을 검색하면 무료 템플릿을 찾을 수 있어요.
태블릿 스크린샷 (선택)
- 태블릿에서 앱이 잘 작동한다면 태블릿 스크린샷도 추가할 수 있어요.
8-3. 카테고리 및 태그
카테고리 선택
- 앱의 성격에 맞는 카테고리를 선택해요.
- QR 코드 앱이라면 "도구" 카테고리가 적합해요.
태그
- 앱과 관련된 태그를 선택해요 (Google이 제공하는 목록에서 선택).
8-4. 연락처 정보
- 이메일 주소 (필수): 사용자 문의를 받을 이메일. 스토어에 공개돼요.
- 전화번호 (선택): 공개돼요.
- 웹사이트 (선택): 앱 소개 웹사이트가 있다면 입력해요.
8-5. 개인정보처리방침 (Privacy Policy)
Google Play는 모든 앱에 대해 개인정보처리방침 URL을 요구해요. 개인정보를 전혀 수집하지 않더라도 그 사실을 명시한 페이지가 필요해요.
개인정보처리방침 페이지를 만드는 방법:
-
GitHub Pages 이용 (무료, 추천)
- GitHub 저장소에
privacy-policy.md파일을 만들고 GitHub Pages로 배포해요.
- GitHub 저장소에
-
무료 생성기 이용
- App Privacy Policy Generator 같은 무료 도구를 사용해요.
-
Google Sites 이용 (무료)
- Google Sites에서 간단한 페이지를 만들어요.
개인정보처리방침에 반드시 포함해야 할 내용:
- 앱이 수집하는 개인정보의 종류 (수집하지 않는다면 그 사실을 명시)
- 수집한 정보의 사용 목적
- 정보 보관 기간 및 삭제 방법
- 제3자 제공 여부
- 문의 연락처
간단한 개인정보처리방침 예시:
# 개인정보처리방침
Just QR 앱(이하 "앱")은 사용자의 개인정보를 수집하지 않습니다.
## 수집하는 정보
본 앱은 어떠한 개인정보도 수집, 저장, 전송하지 않습니다.
## 카메라 권한
본 앱은 QR 코드 스캔을 위해 카메라 권한을 사용합니다.
카메라를 통해 촬영된 이미지는 기기 내에서만 처리되며,
외부 서버로 전송되지 않습니다.
## 문의
본 개인정보처리방침에 대한 문의는 아래 이메일로 연락해주세요.
이메일: your-email@example.com
시행일: 2024년 1월 1일
8-6. 앱 콘텐츠 설정
Play Console 왼쪽 메뉴에서 "정책" > "앱 콘텐츠"로 이동하면 여러 가지 선언을 해야 해요.
개인정보처리방침: 위에서 만든 URL을 입력해요.
광고: 앱에 광고가 포함되어 있는지 여부를 선택해요.
앱 액세스 권한: 앱의 모든 기능에 자유롭게 접근할 수 있는지, 로그인이 필요한지 등을 선택해요.
콘텐츠 등급: 설문지를 작성하면 IARC 등급이 자동 부여돼요. 앱의 콘텐츠에 폭력, 성적 콘텐츠 등이 포함되는지 질문하고, 답변에 따라 연령 등급이 정해져요.
타겟 연령층: 앱의 타겟 연령층을 선택해요. 13세 미만 아동을 대상으로 하는 경우 추가적인 규정이 적용돼요.
데이터 안전: 앱이 수집하고 공유하는 데이터의 종류를 선언해요. 데이터를 수집하지 않는 경우에도 이 섹션을 작성해야 해요.
[참고] "앱 콘텐츠" 섹션의 모든 항목을 빠짐없이 작성해야 해요. 하나라도 빠지면 심사 제출이 불가능해요.
8-7. 국가/지역 설정
"출시" > "프로덕션" > "국가/지역" 탭에서 앱을 출시할 국가를 선택해요.
- 모든 국가에 출시하려면 "국가/지역 추가"에서 모두 선택해요.
- 한국에서만 출시하려면 "대한민국"만 선택해요.
9. 심사 제출 및 주의사항
9-1. 출시 전 체크리스트
심사에 제출하기 전에 아래 항목을 모두 확인하세요.
- applicationId가
com.example로 시작하지 않는가? - 앱 버전 코드와 버전 이름이 올바른가?
- 기본 스토어 등록 정보 (이름, 설명, 스크린샷 등)가 모두 작성되었는가?
- 개인정보처리방침 URL이 유효한가?
- 앱 콘텐츠 섹션이 모두 작성되었는가?
- 콘텐츠 등급 설문이 완료되었는가?
- 데이터 안전 섹션이 작성되었는가?
- 타겟 국가가 선택되었는가?
- AAB 파일이 정상적으로 업로드되었는가?
9-2. 심사 제출하기
- Play Console 대시보드를 확인해요. "앱을 출시하려면 완료해야 하는 작업"이 0개여야 해요.
- "출시" > "프로덕션"으로 이동해요.
- 저장해 둔 버전을 열고 검토 화면으로 넘어가요.
- 경고나 오류가 있으면 수정해요. 경고는 출시를 막지 않지만, 오류는 고쳐야 넘어갈 수 있어요.
- 버전을 저장한 뒤 게시 개요에서 변경사항을 검토에 보내요. 버튼 이름은 Play Console이 바뀌면서 달라져 왔으니 화면 안내를 따라요.
9-3. 심사 기간
- Google 안내로는 일부 개발자 계정은 더 꼼꼼히 검토해서 최대 7일, 예외적으로 그보다 오래 걸릴 수 있어요. 이 경우 예상 기간이 대시보드에 알림으로 나와요.
- 심사 중에는 앱 상태가 "검토 중"으로 표시돼요.
- 심사가 완료되면 이메일로 알림이 와요.
9-4. 심사에서 거부되는 주요 사유
- 메타데이터 정책 위반: 앱 이름이나 설명에 키워드를 과도하게 반복한 경우
- 기능 미작동: 앱이 크래시하거나 핵심 기능이 동작하지 않는 경우
- 개인정보처리방침 누락 또는 불일치: 앱의 데이터 수집 행위와 개인정보처리방침 내용이 다른 경우
- 권한 과다 요청: 앱 기능과 관계없는 권한을 요청하는 경우 (예: 계산기 앱이 카메라 권한 요청)
- 지적재산권 침해: 다른 브랜드의 로고나 이름을 무단 사용한 경우
- 최소 기능 부족: 앱이 웹사이트의 단순 래퍼이거나 기능이 거의 없는 경우
9-5. 거부되었을 때 대처법
- 거부 사유를 정확히 확인해요. Play Console과 이메일에 거부 이유가 안내돼요.
- 해당 사유를 수정해요.
- 새 AAB를 빌드해요. (이때
versionCode를 올려야 해요!) - 다시 제출해요.
- 거부 사유가 불명확하면 Play Console의 이의 제기 기능을 사용할 수 있어요.
10. 자주 하는 실수 / FAQ
Q1. "com.example"을 그대로 두고 제출했어요
com.example로 시작하는 패키지명은 Play Console에서 업로드 자체가 거부돼요. build.gradle.kts에서 applicationId와 namespace를 변경해야 해요. 또한 android/app/src/main/AndroidManifest.xml과 android/app/src/main/kotlin/ 하위의 디렉토리 구조도 패키지명에 맞게 변경해야 해요.
Q2. Keystore 비밀번호를 잊어버렸어요
Keystore 비밀번호를 복구하는 방법은 없어요. Google Play 앱 서명을 쓰고 있다면 Play Console에서 업로드 키 재설정을 요청해 새 업로드 키를 등록할 수 있어요. 그렇지 않다면 해당 앱은 더 이상 업데이트할 수 없어요.
Q3. versionCode를 올리지 않고 빌드해서 업로드가 거부돼요
pubspec.yaml에서 version 값의 + 뒤에 있는 숫자를 올려야 해요.
# 변경 전
version: 1.0.0+1
# 변경 후
version: 1.0.1+2
Q4. 앱 크기가 200MB를 넘어요
Google Play는 AAB의 기본 모듈을 압축 다운로드 크기 기준 200MB로 제한해요. Flutter 앱에서 크기를 줄이는 방법:
# 의존성 목록 확인 (안 쓰는 패키지는 pubspec.yaml에서 제거)
flutter pub deps
# 불필요한 에셋(이미지, 폰트 등) 제거
# 난독화 및 최적화 적용 빌드
flutter build appbundle --release --obfuscate --split-debug-info=build/debug-info
--obfuscate 옵션은 코드를 난독화하여 리버스 엔지니어링을 어렵게 만들어요. --split-debug-info는 디버그 정보를 별도 파일로 분리하여 앱 크기를 줄여줘요.
Q5. 64비트 지원 관련 경고가 나와요
Google Play는 64비트를 지원하는 앱만 허용해요. Flutter는 기본적으로 32비트와 64비트를 모두 포함하여 빌드하므로 보통 문제가 되지 않아요. 경고가 나온다면 build.gradle.kts의 ndk 설정을 확인하세요.
Q6. 내부 테스트 트랙이 뭔가요?
Play Console에는 여러 단계의 테스트 트랙이 있어요.
| 트랙 | 설명 |
|---|---|
| 내부 테스트 | 최대 100명, 이메일로 초대한 테스터만 설치 가능. 심사 없이 바로 배포 |
| 비공개 테스트 | 이메일 목록 또는 Google 그룹으로 테스터 관리. 심사 있음. 새 개인 계정은 여기서 12명·14일 요건을 채워요 |
| 공개 테스트 | 누구나 참여 가능한 베타 테스트. 심사 있음 |
| 프로덕션 | 모든 사용자에게 공개. 정식 심사 |
처음이라면 내부 테스트 -> 비공개/공개 테스트 -> 프로덕션 순서로 단계적으로 출시하는 것이 안전해요.
Q7. 대상 API 수준(target API level) 요구사항 오류가 나요
Google Play는 매년 targetSdk 요구사항을 높여요. 2026년 8월 31일부터 새 앱과 업데이트는 API 36(Android 16) 이상을 타깃해야 해요. 최신 Flutter를 쓰면 보통 충족되지만, 오래된 Flutter 버전이라면 업그레이드가 필요해요.
# Flutter 업그레이드
flutter upgrade
# 그래도 안 되면 build.gradle.kts에서 직접 지정
# defaultConfig 블록 안에:
targetSdk = 36 # Google Play가 요구하는 API 레벨
Q8. build.gradle vs build.gradle.kts 차이가 뭔가요?
인터넷에서 검색하면 두 가지 방식의 예제가 나와요.
build.gradle: Groovy 언어 기반 (구 방식)build.gradle.kts: Kotlin DSL 기반 (신 방식)
최근 Flutter 프로젝트는 build.gradle.kts를 기본으로 사용해요. 두 파일의 문법이 다르므로, Groovy 방식의 예제를 build.gradle.kts에 그대로 복사하면 에러가 발생해요. 주요 차이점:
// Groovy (build.gradle)
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
storeFile file(keystoreProperties['storeFile'])
}
}
// Kotlin DSL (build.gradle.kts)
signingConfigs {
create("release") {
keyAlias = keystoreProperties["keyAlias"] as String
storeFile = file(keystoreProperties["storeFile"] as String)
}
}
Q9. 앱이 출시된 후 수정하고 싶어요
- 코드를 수정해요.
pubspec.yaml에서 버전을 올려요 (versionCode 필수).flutter build appbundle --release로 새 AAB를 빌드해요.- Play Console에서 새 버전을 만들어 AAB를 업로드해요.
- 심사 제출해요.
Q10. 무료 앱을 유료로 바꿀 수 있나요?
아니요. 무료로 출시한 앱은 유료로 변경할 수 없어요. 반대로 유료 앱을 무료로 변경하는 것은 가능해요. 유료화를 고려한다면 처음부터 유료로 등록하거나, 인앱 결제(IAP) 방식을 사용하세요.
마무리
핵심 요약:
- Play Console 개발자 계정을 등록해요 ($25 일회성).
- Keystore를 생성하고 안전하게 보관해요.
key.properties와build.gradle.kts를 설정해요.flutter build appbundle --release로 AAB를 빌드해요.- Play Console에 앱을 만들고 AAB를 업로드해요. 새 개인 계정은 비공개 테스트(12명·14일)를 거쳐 프로덕션 액세스를 신청해요.
- 스토어 등록 정보를 빠짐없이 작성해요.
- 심사에 제출하고 승인을 기다려요.