Flutter Android 출시 빌드 설정 (keystore, R8, ProGuard, ML Kit)
이 글에서 다루는 내용
이 글에서는 Flutter Android 앱을 release 모드로 빌드할 때 마주친 세 가지 문제, 즉 keystore.properties 변수 참조 오류, R8 코드 축소 단계에서의 ML Kit 누락 클래스 에러, 그리고 release signingConfig 전환을 해결한 과정을 다룹니다.
문제 1 — keystoreProperties 참조 오류
android/app/build.gradle.kts에 아래 코드만 있고 keystoreProperties 변수 선언이 빠져 있어 컴파일이 실패했습니다.
signingConfigs {
create("release") {
keyAlias = keystoreProperties["keyAlias"] as String?
keyPassword = keystoreProperties["keyPassword"] as String?
storeFile = keystoreProperties["storeFile"]?.let { file(it as String) }
storePassword = keystoreProperties["storePassword"] as String?
}
}
에러 메시지는 Unresolved reference: keystoreProperties였습니다. 변수 선언과 Properties 파일 로드 코드를 파일 상단에 추가해서 해결했습니다.
import java.util.Properties
import java.io.FileInputStream
val keystoreProperties = Properties().apply {
val keystorePropertiesFile = rootProject.file("keystore.properties")
if (keystorePropertiesFile.exists()) {
load(FileInputStream(keystorePropertiesFile))
}
}
문제 2 — R8 Missing Classes 에러
bundleRelease 태스크 중 R8이 google_mlkit_text_recognition 플러그인의 중국어·일본어·한국어·데바나가리 언어 모듈 클래스를 찾지 못해 빌드가 실패했습니다.
ERROR: R8: Missing class com.google.mlkit.vision.text.korean.KoreanTextRecognizerOptions
...
Execution failed for task ':app:minifyReleaseWithR8'.
ML Kit의 언어별 인식 모듈은 선택적 의존성이라 플러그인 코드에서 참조만 존재하고 실제 클래스는 별도로 추가해야 들어옵니다. 해결책은 두 단계입니다.
2-1. 사용하지 않는 언어는 ProGuard keep 규칙으로 경고 억제
android/app/proguard-rules.pro를 생성합니다.
-dontwarn com.google.mlkit.vision.text.chinese.**
-dontwarn com.google.mlkit.vision.text.devanagari.**
-dontwarn com.google.mlkit.vision.text.japanese.**
2-2. 실제 사용하는 한국어 모듈은 의존성으로 추가
android/app/build.gradle.kts에 다음을 추가합니다.
dependencies {
implementation("com.google.mlkit:text-recognition-korean:16.0.1")
}
release 빌드가 ProGuard 규칙 파일을 참조하도록 buildTypes.release도 수정했습니다.
buildTypes {
release {
signingConfig = signingConfigs.getByName("release")
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
문제 3 — debug 서명으로 release 빌드됨
Flutter가 기본 생성하는 build.gradle.kts는 release에 signingConfigs.getByName("debug")를 사용하도록 주석과 함께 설정돼 있습니다. Play Console에 업로드하면 "디버그 모드로 서명한 APK 또는 App Bundle을 업로드했습니다" 오류가 납니다. 위 buildTypes.release 수정에서 getByName("release")로 변경해 실제 release keystore가 사용되도록 했습니다.
최종 build.gradle.kts 구조
import java.util.Properties
import java.io.FileInputStream
plugins { /* ... */ }
val keystoreProperties = Properties().apply {
val keystorePropertiesFile = rootProject.file("keystore.properties")
if (keystorePropertiesFile.exists()) {
load(FileInputStream(keystorePropertiesFile))
}
}
android {
signingConfigs {
create("release") {
keyAlias = keystoreProperties["keyAlias"] as String?
keyPassword = keystoreProperties["keyPassword"] as String?
storeFile = keystoreProperties["storeFile"]?.let { file(it as String) }
storePassword = keystoreProperties["storePassword"] as String?
}
}
buildTypes {
release {
signingConfig = signingConfigs.getByName("release")
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
}
dependencies {
implementation("com.google.mlkit:text-recognition-korean:16.0.1")
}