Android 앱 빌드 — APK · AAB · 서명
Android 앱 빌드 — APK · AAB · 서명
Android 앱을 빌드한다는 일은 어떤 도구를 쓰든 결국 비슷한 단계를 통과합니다. 소스를 컴파일하고, 자원을 묶고, DEX 로 변환하고, 서명. 결과 파일은 APK 또는 AAB. 이 글은 그 흐름과 sdk 버전 (min · target · compile) 의 의미 · 서명 키 운영 · Tauri · Flutter · React Native 가 공유하는 공통점.
1. APK · AAB
APK (Android Package) — Android 의 전통적 패키지 형식. ZIP 컨테이너 안에 컴파일된 코드 (DEX) · 자원 · 매니페스트 · 서명.
AAB (Android App Bundle) — Google 이 2018 년 도입. 사용자 단말의 화면 밀도 · 언어 · 아키텍처에 맞는 최소 APK 를 Play Store 가 동적으로 만들어 배포. 결과적으로 사용자가 받는 다운로드 크기가 줄어듦.
| 항목 | APK | AAB |
|---|---|---|
| 단말 설치 | 직접 가능 | 직접 설치 불가 (bundletool 로 APK 생성) |
| Play Store 업로드 | 가능 (옛 앱) | 의무 (2021-08 이후 신규 앱) |
| 크기 최적화 | 한 APK | 단말별 분리 |
| 사이드로딩 | 자연스러움 | 불편 |
2021 년 8월부터 Play Console 의 신규 앱은 AAB 가 의무화. 결과적으로 Play 배포는 AAB, 사이드로딩 · 서드파티 스토어는 APK.
2. 빌드 흐름
소스 (Java · Kotlin) → javac · kotlinc → .class
자원 (res/ · assets/) → AAPT2 → 컴파일된 자원
.class → R8 (또는 D8) → .dex (또는 축소 · 난독화 포함)
DEX + 자원 + AndroidManifest → 패키저 → 서명 → APK · AAB
Gradle — Android 빌드의 사실상 표준 도구. build.gradle 또는 build.gradle.kts 에 의존성 · 플러그인 · 빌드 변형:
android {
compileSdk = 35
defaultConfig {
applicationId = "com.example.app"
minSdk = 24
targetSdk = 35
versionCode = 1
versionName = "1.0.0"
}
buildTypes {
release {
minifyEnabled = true
shrinkResources = true
proguardFiles(...)
}
}
}
AAPT2 (Android Asset Packaging Tool 2) — 자원 (res/) 을 컴파일하고 링크. PNG 최적화 · ID 부여 · binary XML 변환.
R8 — ProGuard 의 후속. 사용되지 않는 클래스 · 메서드를 제거하고 이름을 짧게 바꿔 DEX 크기 축소. minifyEnabled = true 로 활성.
D8 — .class (JVM 바이트코드) 를 .dex (Android 가상 머신용) 로 변환. R8 이 함께 수행하기도.
Bundletool — AAB 를 단말별 APK 로 생성하는 도구. 로컬 디버깅 시 bundletool build-apks ... 로 실행 가능한 APK.
3. sdk 버전의 의미
| 속성 | 의미 |
|---|---|
minSdk |
앱이 동작 가능한 가장 낮은 OS 버전 |
targetSdk |
앱이 테스트 · 동작을 보장하는 OS 버전. 권한 · 동작 기본값에 영향 |
compileSdk |
빌드에 사용하는 SDK. 새 API 호출 가능 여부 |
Google Play 정책은 신규 / 업데이트 앱의 targetSdk 최소값을 매년 올림. 2024 년 후반 기준 신규 앱은 Android 14 (API 34) targetSdk 의무.
minSdk 를 낮추면 사용자 범위가 넓어지지만 코드 분기가 늘어남. 보통 시장 점유율이 일정 수준 이하인 OS 는 끊는 흐름.
4. 서명
키스토어 — Java 의 keytool 로 만드는 .jks 파일. 비공개 키와 인증서를 묶어 보관:
# Mac · Linux
keytool -genkey -v -keystore release.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload
# Windows (PowerShell, JDK 설치 후)
keytool.exe -genkey -v -keystore release.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload
Upload Key 와 App Signing Key — Play App Signing (2017 도입) 모델 이후 두 키가 분리:
- Upload Key — 개발자가 보유. Play 에 업로드할 때 서명. 잃어도 Google 에 요청해 재발급 가능.
- App Signing Key — Google 이 보관. 사용자에게 배포되는 최종 서명.
Play App Signing 을 옵트인하면 키 분실 위험이 줄지만, App Signing Key 의 직접 접근은 제한.
서명 방식의 진화:
- v1 (JAR signing) —
META-INF/*.SF. 개별 항목 무결성. 약점 보고 후 v2 로. - v2 (APK Signing Block) — 7.0+. 전체 APK 무결성.
- v3 (key rotation) — 9.0+.
- v4 (incremental) — 11.0+.
Gradle Android Plugin 이 적절한 서명 체계를 자동 적용. 일반적으로 v2 + v3 가 함께 활성화.
서명 설정 — 키스토어 비밀번호는 환경 변수 · 시크릿 매니저로 분리. 저장소에 평문으로 두지 않음:
android {
signingConfigs {
release {
storeFile = file(System.getenv("KEYSTORE_PATH"))
storePassword = System.getenv("KEYSTORE_PASSWORD")
keyAlias = System.getenv("KEY_ALIAS")
keyPassword = System.getenv("KEY_PASSWORD")
}
}
buildTypes {
release {
signingConfig = signingConfigs.release
}
}
}
5. 크로스플랫폼 도구의 공통점
Tauri Mobile · Flutter · React Native 모두 결국 같은 Android 빌드 흐름:
- 자체 코드 (Rust · Dart · JS) 를 컴파일 · 번들.
- Android 프로젝트 (Gradle) 를 자동 생성 · 관리.
gradlew assembleRelease·gradlew bundleRelease로 APK · AAB 산출.- 서명 · minSdk · targetSdk 는
build.gradle에 정의.
각 도구는 기본 템플릿을 제공하지만, 결과물의 모양은 표준 Android 앱과 같음. 경계가 흐릿한 자리에서는 Android Studio 로 직접 열어 확인.
6. 빌드 변형과 CI
빌드 변형 — flavor 와 buildType 의 곱으로 다양한 빌드:
flavorDimensions += "tier"
productFlavors {
free { dimension = "tier" }
pro { dimension = "tier" }
}
assembleFreeDebug · assembleProRelease 같은 태스크가 자동 생성.
CI 빌드:
- GitHub Actions —
gradle/wrapper-validation-action+actions/cache로 빌드 가속. - 키스토어 파일은 base64 인코딩 후 시크릿으로 저장 → 빌드 시 디코드.
- run: |
echo "$KEYSTORE_BASE64" | base64 -d > release.jks
./gradlew bundleRelease
7. 자주 걸리는 자리
키 분실의 의미 — Play App Signing 옵트아웃이라면 키 분실 시 같은 앱 ID 로 업데이트 불가. 새 앱으로 재출시 필요.
targetSdk 갱신 누락 — Play Console 이 신규 업데이트를 거부할 수 있음. 매년 정책 점검.
minSdk 와 라이브러리 충돌 — 일부 라이브러리가 더 높은 minSdk 를 요구. 의존성 트리 검토.
Multi-arch APK — x86_64 · arm64-v8a · armeabi-v7a 를 모두 포함하면 APK 가 무거움. AAB 가 자동 분리. APK 직접 배포라면 ABI splits.
R8 의 의도치 않은 제거 — 런타임 리플렉션으로만 참조되는 클래스를 제거할 수 있음. ProGuard 규칙 (-keep) 으로 보존.
퍼미션의 새 모델 — Android 13+ 의 알림 권한, 14+ 의 부분 미디어 접근 등 시기마다 새 권한 모델. 호환 코드 필요.
Play Integrity API — 봇 · 변조 차단 API. 도입 시 사용자 단말의 일부에서 거부됨이 보고.
Gradle 버전 불일치 — Android Gradle Plugin · Gradle · Kotlin · JDK 의 호환 매트릭스가 빠르게 변함. 공식 문서 확인.
하고픈 말
Android 빌드는 어떤 크로스플랫폼 도구를 쓰든 결국 같은 Gradle + AAPT2 + R8 + 서명 흐름. AAB 가 신규 앱의 표준이 됐고, Play App Signing 이 키 분실 위험을 줄여주는 자리. 매년 targetSdk 갱신 + 새 권한 모델 호환이 운영의 정기 자리.
Next
- ios-build
- (mobile 끝)
Android Developers Build · Android App Bundle · Play App Signing · APK Signature Scheme v2/v3/v4 · R8 / ProGuard 규칙 · Play Console 정책 · bundletool GitHub · Android 버전 점유율 를 참고합니다.