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를 내야 하는 것과 비교하면 매우 저렴합니다.
- 해외 결제가 가능한 신용카드 또는 체크카드가 필요합니다.
- 원화로는 약 33,000원~35,000원 정도입니다 (환율에 따라 변동).
- 결제 후 계정이 활성화되는 데 최대 48시간이 소요될 수 있습니다.
2-6. 계정 활성화 확인
결제가 완료되면 Play Console 대시보드에 접근할 수 있게 됩니다. "모든 앱" 페이지가 보이면 정상적으로 등록된 것입니다.
[주의] 계정 등록 후 바로 앱을 업로드하기보다, 먼저 앱 빌드 준비를 끝내고 나서 업로드하는 것이 순서상 편합니다. 아래 과정을 먼저 진행하세요.
3. 앱 서명 키(Keystore) 생성
Keystore가 뭔가요?
Keystore는 앱의 "디지털 인감도장"입니다. 이 키로 서명된 앱만이 "진짜 내 앱"으로 인정됩니다.
왜 필요한지 예를 들어보겠습니다. 누군가 여러분의 앱 이름과 패키지명을 똑같이 만들어서 악성코드를 심은 가짜 앱을 배포하려 한다고 가정해봅시다. 하지만 여러분의 서명 키 없이는 기존 앱의 업데이트로 등록할 수 없기 때문에, 사용자들이 가짜 앱에 속을 위험이 줄어듭니다.
절대 잃어버리면 안 됩니다
Keystore 파일과 비밀번호를 잃어버리면 해당 앱은 영원히 업데이트할 수 없습니다. 새로운 패키지명으로 완전히 새 앱을 등록해야 하며, 기존 사용자들은 직접 새 앱을 다시 설치해야 합니다. 반드시 안전한 곳에 백업하세요.
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년)로 설정합니다. 앱을 오래 유지할 것이므로 길게 잡습니다 |
-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 파일에서 "릴리스 빌드 시 어떤 키로 서명할지"를 지정해주는 것입니다.
[참고] 이 프로젝트는 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())로 파일이 있을 때만 읽습니다. 이렇게 하면 key.properties가 없는 환경(예: CI 서버, 다른 팀원의 PC)에서도 디버그 빌드는 정상 작동합니다.
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는 한 번 스토어에 등록하면 절대 변경할 수 없습니다. 신중하게 정하세요. 일반적으로 본인이 소유한 도메인의 역순을 사용합니다. 도메인이 없다면
com.github.깃허브아이디.앱이름형태도 괜찮습니다.
applicationId를 변경했다면, android/app/src/main/AndroidManifest.xml의 패키지명도 함께 확인하세요. Flutter 최신 버전에서는 build.gradle.kts의 namespace와 applicationId만 변경하면 됩니다.
6. 릴리스 빌드 만들기
AAB vs APK
Google Play 스토어는 2021년 8월부터 새 앱은 반드시 AAB(Android App Bundle) 형식으로 제출해야 합니다. APK가 아닙니다.
| 형식 | 용도 |
|---|---|
| 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
빌드에는 보통 1~5분 정도 소요됩니다. 성공하면 아래와 같은 메시지가 나타납니다.
Built build/app/outputs/bundle/release/app-release.aab
6-3. 빌드 결과물 확인
생성된 AAB 파일은 아래 경로에 있습니다.
build/app/outputs/bundle/release/app-release.aab
이 파일이 Google Play Console에 업로드할 파일입니다. 파일 크기는 보통 10~50MB 정도입니다.
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에서 왼쪽 메뉴의 "설정" > "앱 서명"으로 이동합니다.
Google Play 앱 서명을 사용하면 Google이 앱 서명 키를 안전하게 관리해줍니다. 우리가 만든 키는 "업로드 키"로 사용되고, Google이 별도의 "앱 서명 키"를 생성하여 실제 사용자에게 배포되는 앱에 서명합니다.
[참고] Google Play 앱 서명은 필수입니다. 이중 서명 구조 덕분에 업로드 키를 분실해도 Google에 연락하면 새 업로드 키를 등록할 수 있습니다. 하지만 그래도 키를 잃어버리지 않는 것이 가장 좋습니다.
7-4. AAB 파일 업로드
- 왼쪽 메뉴에서 "출시" > "프로덕션"을 클릭합니다.
- "새 버전 만들기" 버튼을 클릭합니다.
- "App Bundle" 섹션에서 AAB 파일을 업로드합니다. 아까 빌드한
app-release.aab파일을 드래그하거나 파일 선택으로 업로드합니다. - 업로드가 완료되면 버전 코드와 버전 이름이 자동으로 표시됩니다.
- "출시 노트"를 작성합니다. 사용자에게 보여줄 "새로운 기능" 안내입니다.
예시:
<ko-KR>
- 첫 번째 릴리스
- QR 코드 생성 및 스캔 기능
</ko-KR>
- "저장"을 클릭합니다. 아직 "출시 검토"를 누르지 마세요. 스토어 등록 정보를 먼저 작성해야 합니다.
[참고] 처음이라면 "내부 테스트" 트랙에 먼저 업로드하여 테스트하는 것을 강력히 권장합니다. 내부 테스트는 지정한 이메일 주소의 사용자만 앱을 설치할 수 있어서, 문제가 있어도 일반 사용자에게 노출되지 않습니다. 내부 테스트에서 충분히 검증한 후 프로덕션으로 승격하세요.
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 픽셀
- 앱 검색 결과 상단에 표시됩니다.
- 앱의 핵심 기능을 보여주는 배너 이미지를 만드세요.
- Figma, Canva 등 무료 도구로 만들 수 있습니다.
스크린샷 (필수)
- 최소 2장, 최대 8장
- 휴대전화 스크린샷: 최소 2장 필수
- 가로세로 비율: 16:9 또는 9:16
- 최소 크기: 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개여야 합니다.
- "출시" > "프로덕션"으로 이동합니다.
- 이전에 저장해둔 버전이 있을 것입니다. "출시 검토" 버튼을 클릭합니다.
- 경고나 오류가 있으면 수정합니다. 경고(노란색)는 출시에 영향을 주지 않지만, 오류(빨간색)는 반드시 수정해야 합니다.
- "프로덕션에 출시 시작" 버튼을 클릭합니다.
9-3. 심사 기간
- 신규 앱: 보통 3일~7일 정도 소요됩니다. 길면 2주까지 걸릴 수 있습니다.
- 앱 업데이트: 보통 1일~3일 정도 소요됩니다.
- 심사 중에는 앱 상태가 "검토 중"으로 표시됩니다.
- 심사가 완료되면 이메일로 알림이 옵니다.
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 앱 서명을 사용하고 있다면, Google에 연락하여 새로운 업로드 키를 등록할 수 있습니다. 그렇지 않다면 해당 앱은 더 이상 업데이트할 수 없습니다.
Q3. versionCode를 올리지 않고 빌드해서 업로드가 거부돼요
pubspec.yaml에서 version 값의 + 뒤에 있는 숫자를 올려야 합니다.
# 변경 전
version: 1.0.0+1
# 변경 후
version: 1.0.1+2
Q4. 앱 크기가 150MB를 넘어요
Google Play의 AAB 파일 크기 제한은 150MB입니다. Flutter 앱에서 크기를 줄이는 방법:
# 사용하지 않는 패키지 제거
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 그룹으로 테스터 관리. 간단한 심사 있음 |
| 공개 테스트 | 누구나 참여 가능한 베타 테스트. 심사 있음 |
| 프로덕션 | 모든 사용자에게 공개. 정식 심사 |
처음이라면 내부 테스트 -> 비공개/공개 테스트 -> 프로덕션 순서로 단계적으로 출시하는 것이 안전합니다.
Q7. "이 앱은 Google Play의 대상 API 수준 요구사항을 충족하지 않습니다" 오류
Google Play는 매년 targetSdkVersion 요구사항을 높입니다. Flutter의 최신 버전을 사용하면 보통 자동으로 충족되지만, 오래된 Flutter 버전을 사용 중이라면 업그레이드가 필요합니다.
# Flutter 업그레이드
flutter upgrade
# 그래도 안 되면 build.gradle.kts에서 직접 지정
# defaultConfig 블록 안에:
targetSdk = 34 # 또는 Google이 요구하는 최신 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를 업로드합니다.
- 스토어 등록 정보를 빠짐없이 작성합니다.
- 심사에 제출하고 승인을 기다립니다.
화이팅!