- Published on
- ·20 min read
Flutter 문서 번역 - Android 앱 빌드 및 출시
- 이 글은 Flutter 문서 Build and release an Android app를 번역한 글입니다.
- 번역 기준일: 2024년 3월 28일
일반적인 개발 주기 동안, command line에서 flutter run
을 사용하거나 IDE에서 Run and Debug 옵션을 사용하여 앱을 테스트합니다. 기본적으로 Flutter는 앱의 디버그(debug) 버전을 빌드합니다.
예를 들어 Google Play Store에 게시하기 위한 앱의 출시(release) 버전을 준비할 때가 되면 이 페이지가 도움이 될 수 있습니다. 게시하기 전에 앱을 마무리하는 것이 좋습니다. 이 페이지는 다음 주제를 다룹니다:
- 런처 아이콘 추가 (Adding a launcher icon)
- Material Components 활성화 (Enabling Material Components)
- 앱 서명 (Signing the app)
- R8로 코드 축소 (Shrinking your code with R8)
- 멀티덱스 지원 활성화 (Enabling multidex support)
- 앱 매니페스트 검토 (Reviewing the app manifest)
- 빌드 구성 검토 (Reviewing the build configuration)
- 출시용 앱 빌드 (Building the app for release)
- Google Play Store에 게시 (Publishing to the Google Play Store)
- 앱 버전 번호 업데이트 (Updating the app’s version number)
- 안드로이드 출시 FAQ (Android release FAQ)
참고: 이 페이지에서 [project]는 당신의 앱이 있는 디렉터리를 나타냅니다. 이 지침을 따르는 동안 [project]를 당신의 앱 디렉터리로 바꾸세요.
런처 아이콘 추가
새 Flutter 앱이 생성되면, 기본 런처 아이콘이 표시됩니다. 이 아이콘을 변경하려면 flutter_launcher_icons 패키지를 확인하세요.
또는, 다음 단계를 사용하여 수동으로 진행할 수 있습니다.
아이콘 디자인에 관한 Material Design product icons 지침을 검토하세요.
[project]/android/app/src/main/res/
디렉터리에서, 구성 한정자(configuration qualifiers)를 사용하여 이름이 지정된 폴더에 아이콘 파일을 넣습니다. 기본mipmap-
폴더는 올바른 명명 규칙을 보여줍니다.AndroidManifest.xml
에서, 이전 단계의 아이콘을 참조하도록 application 태그의android:icon
속성을 업데이트합니다(예:<application android:icon="@mipmap/ic_launcher" ...
).아이콘이 대체되었는지 확인하려면, 앱을 실행하고 런처에서 앱 아이콘을 검사하세요.
Material Components 활성화
앱이 Platform Views를 사용하는 경우, Getting Started guide for Android에 설명된 단계에 따라 Material Components를 활성화할 수 있습니다.
예를 들어:
<my-app>/android/app/build.gradle
에 Android의 Material에 대한 종속성을 추가합니다.
dependencies {
// ...
implementation 'com.google.android.material:material:<version>'
// ...
}
최신 버전을 확인하려면, Google Maven을 방문하세요.
<my-app>/android/app/src/main/res/values/styles.xml
에서 light them를 설정하세요.
-<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
+<style name="NormalTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
<my-app>/android/app/src/main/res/values-night/styles.xml
에서 dark theme를 설정하세요.
-<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
+<style name="NormalTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
앱 서명
Play Store에 앱을 게시하려면, 디지털 인증서로 앱을 서명해야 합니다.
Android는 두 가지 서명 키를 사용합니다: upload 와 app signing.
- 개발자는 upload key로 서명된
.aab
또는.apk
파일을 Play Store에 업로드합니다. - 사용자는 app signing key로 서명된
.apk
파일을 다운로드합니다.
앱 서명 키를 생성하려면, 공식 Play Store 문서에 설명된 Play App Signing을 사용하세요.
앱을 서명하려면, 다음 지침을 사용하세요.
upload keystore 생성
keystore가 이미 있는 경우, 다음 단계로 넘어가세요. 그렇지 않다면, 다음 방법 중 하나를 사용하여 생성하세요.
Android Studio 키 생성 단계를 따르세요.
다음 명령어를 command line에서 실행하세요:
macOS 또는 Linux에서는, 다음 명령어를 사용하세요:
keytool -genkey -v -keystore ~/upload-keystore.jks -keyalg RSA \
-keysize 2048 -validity 10000 -alias upload
Windows에서는, PowerShell에서 다음 명령어를 사용하세요:
keytool -genkey -v -keystore %userprofile%\upload-keystore.jks ^
-storetype JKS -keyalg RSA -keysize 2048 -validity 10000 ^
-alias upload
이 명령어는 upload-keystore.jks
파일을 홈 디렉터리에 저장합니다. 다른 곳에 저장하려면 -keystore
매개변수에 전달하는 인수를 변경하세요. 하지만 keystore 파일은 비공개(private)를 유지하세요; 공개 소스 제어에 올리지 마세요!
참고
keytool
명령어가 경로에 없을 수도 있습니다—이것은 Android Studio에서 설치되는 Java의 일부입니다. 구체적인 경로의 경우flutter doctor -v
를 실행하고 ‘Java binary at:’ 에 적힌 경로를 찾으세요. 그런 다음 해당 경로의 끝부분에 있는java
를keytool
로 바꾸어 사용하세요. 경로에Program Files
와 같이 공백으로 구분된 이름이 포함된 경우, 이름에 대해 플랫폼에 적합한 표기법을 사용하십시오. 예를 들어 Mac/Linux에서는Program\ Files
를 사용하고 Windows에서는"Program Files"
를 사용합니다.-storetype JKS
태그는 Java 9 이상에만 필요합니다. Java 9 릴리스부터 keystore type의 기본값은 PKS12입니다.
앱에서 keystore 참조
keystore에 대한 참조가 포함된 [project]/android/key.properties
라는 파일을 만듭니다. 꺾쇠 괄호(< >
)를 포함하지 마세요. 꺾쇠 괄호는 해당 텍스트가 여러분의 값(value)의 자리 표시자로 사용됨을 나타냅니다.
storePassword=<password-from-previous-step>
keyPassword=<password-from-previous-step>
keyAlias=upload
storeFile=<keystore-file-location>
storeFile
은 macOS의 경우 /Users/<user name>/upload-keystore.jks
, Windows의 경우 C:\\Users\\<user name>\\upload-keystore.jks
에 있을 수 있습니다.
경고: key.properties
파일을 비공개로 유지하세요; 공개 소스 제어에 올리지 마세요!
Gradle에서 서명(signing) 구성
[project]/android/app/build.gradle
파일을 편집해서 release 모드에서 앱을 빌드할 때 upload key를 사용하도록 gradle을 구성하세요.
android
블록 앞에 properties 파일의 keystore 정보를 추가하세요:def keystoreProperties = new Properties() def keystorePropertiesFile = rootProject.file('key.properties') if (keystorePropertiesFile.exists()) { keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) } android { ... }
key.properties
파일을keystoreProperties
객체에 로드합니다.buildTypes
블록을 찾으세요:buildTypes { release { // TODO: Add your own signing config for the release build. (release build에 대한 자체 서명 구성을 추가) // Signing with the debug keys for now, (현재 debug key로 서명 중) // so `flutter run --release` works. (그래서 `flutter run --release`가 작동됨.) signingConfig signingConfigs.debug } }
그리고 이를 다음 서명 구성 정보로 바꿉니다:
signingConfigs { release { keyAlias keystoreProperties['keyAlias'] keyPassword keystoreProperties['keyPassword'] storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null storePassword keystoreProperties['storePassword'] } } buildTypes { release { signingConfig signingConfigs.release } }
이제 앱의 release 빌드는 자동으로 서명됩니다.
참고: gradle 파일을 변경한 후에 flutter clean
을 실행해야 할 수도 있습니다. 이렇게 하면 캐시된 빌드가 서명 프로세스에 영향을 미치는 것을 방지할 수 있습니다.
앱 서명에 대한 더 자세한 내용은 developer.android.com의 Sign your app를 확인하세요.
R8로 코드 축소
R8은 Google의 새로운 코드 축소기이며, release APK 또는 AAB를 빌드할 때 기본적으로 활성화됩니다. R8을 비활성화하려면 --no-shrink
플래그를 flutter build apk
또는 flutter build appbundle
에 전달하세요.
참고: 난독화 및 축소로 Android 애플리케이션의 컴파일 시간이 상당히 늘어날 수 있습니다.
멀티덱스(multidex) 지원 활성화
대규모 앱을 작성하거나 대규모 플러그인을 작성할 때, 최소 API가 20 이하일 경우 Android의 dex 제한인 64k 메서드에 직면할 수 있습니다. 축소가 활성화되지 않은 flutter run
을 사용하여 앱의 디버그 버전을 실행할 때도 이런 문제가 발생할 수 있습니다.
Flutter 도구는 멀티덱스(multidex)를 쉽게 활성화할 수 있습니다. 가장 간단한 방법은 prompt가 표시될 때 multidex support를 선택하는 것입니다. 도구는 멀티덱스 빌드 오류를 감지하고 Android 프로젝트에 변경을 가하기 전에 묻습니다. 선택하면 Flutter가 자동으로 androidx.multidex:multidex
에 의존하고, 생성된 FlutterMultiDexApplication
을 프로젝트 애플리케이션으로 사용합니다.
IDE에서 Run 및 Debug 옵션으로 앱을 빌드하고 실행하려고 할 때, 다음 메시지와 함께 빌드가 실패할 수 있습니다:
command line에서 multidex를 활성화하려면, flutter run --debug
를 실행하고 Android device를 선택하세요:
prompt가 표시되면 y를 입력하세요. Flutter 도구는 multidex support를 활성화하고 빌드를 다시 시도합니다:
참고: Android SDK 21 이상을 타겟팅하면 멀티덱스 지원이 기본적으로 포함됩니다. 그러나 순전히 멀티덱스 문제를 해결하기 위해 API 21+을 타겟팅하는 것은 권장하지 않습니다. 이렇게 하면 오래된 기기를 사용하는 사용자가 의도하지 않게 제외될 수 있습니다.
Android 가이드에 따라 프로젝트의 Android 디렉터리 구성을 수정하여 수동으로 multidex를 지원하도록 선택할 수도 있습니다. 다음을 포함하도록 multidex keep file을 지정해야 합니다.
io/flutter/embedding/engine/loader/FlutterLoader.class
io/flutter/util/PathUtils.class
또한, 앱 시작에 사용되는 다른 클래스도 포함하세요. 멀티덱스 지원을 수동으로 추가하는 더 자세한 방법은 공식 Android 문서를 확인하세요.
앱 매니페스트 검토
기본 앱 매니페스트 파일인 AndroidManifest.xml
을 검토하세요.이 파일은 [project]/android/app/src/main
에 있습니다. 다음 값을 확인하세요:
application
앱의 최종 이름을 반영하도록 application 태그의 android:label
을 편집하세요.
uses-permission
애플리케이션 코드에 인터넷 액세스가 필요한 경우, android.permission.INTERNET
권한을 추가하세요. 표준 템플릿에는 이 태그가 포함되어 있지 않지만, 개발 중에 인터넷 액세스를 허용하여 Flutter 도구와 실행 중인 앱 간의 통신을 가능하게 합니다.
Gradle 빌드 구성 검토
기본 Gradle build file([project]/android/app
에 있는 build.gradle
)을 검토하여 값이 올바른지 확인하세요.
defaultConfig
block
Under the applicationId
최종의 고유한 application ID를 지정합니다.
minSdkVersion
앱을 실행하도록 설계한 minimum API level을 지정합니다. 기본값은 flutter.minSdkVersion
입니다.
targetSdkVersion
앱을 실행하도록 설계한 target API level을 지정합니다. 기본값은 flutter.targetSdkVersion
입니다.
versionCode
내부 버전 번호로 사용되는 양의 정수입니다. 이 숫자는 한 버전이 다른 버전보다 더 최신인지 확인하는 데에만 사용되며, 숫자가 높을수록 최신 버전을 나타냅니다. 이 버전은 사용자에게 표시되지 않습니다.
versionName
사용자에게 표시되는 버전 번호로 사용되는 문자열입니다. 이 설정은 원시 문자열 또는 문자열 리소스에 대한 참조로 지정할 수 있습니다.
buildToolsVersion
Gradle 플러그인은 프로젝트에서 사용하는 빌드 도구의 기본 버전을 지정합니다. 이 옵션을 사용하여 다른 버전의 빌드 도구를 지정할 수 있습니다.
android
block
Under the compileSdkVersion
Gradle이 앱을 컴파일하는 데 사용할 API level을 지정합니다. 기본값은 flutter.compileSdkVersion
입니다.
출시용(release) 앱 빌드
Play Store에 게시할 때 두 가지 출시 형식이 있습니다.
- App bundle (권장)
- APK
참고: Google Play Store는 app bundle 형식을 선호합니다. 자세한 내용은 Android App Bundles에서 확인하세요.
Build an app bundle
이 섹션에서는 release app bundle을 빌드하는 방법을 설명합니다. 서명 단계를 완료했다면, 앱 번들은 서명됩니다. 이 지점에서, reverse engineer를 더 어렵게 만들기 위한 Dart 코드를 난독화를 고려할 수 있습니다. 코드를 난독화하는 것은 빌드 명령에 몇 가지 플래그를 추가하고, 스택 추적을 해독하기 위한 추가 파일을 유지해야 합니다.
command line에서:
cd [project]
를 입력하세요.flutter build appbundle
을 실행하세요.
(flutter build
를 실행하면 기본적으로 release 빌드로 설정됩니다.)
앱의 release bundle은 [project]/build/app/outputs/bundle/release/app.aab
에 생성됩니다.
기본적으로, 앱 번들에는 armeabi-v7a (ARM 32-bit), arm64-v8a (ARM 64-bit), x86-64 (x86 64-bit)용으로 컴파일된 Dart 코드와 Flutter 런타임이 포함됩니다.
Test the app bundle
앱 번들은 여러 방법으로 테스트할 수 있습니다. 이 섹션에서는 두 가지 방법을 설명합니다.
bundle tool을 사용하여 오프라인으로
- GitHub 저장소에서
bundletool
을 다운로드하세요. - 앱 번들에서 APK 세트를 생성하세요.
- 연결된 장치에 APK를 배포하세요.
Google Play을 사용하여 온라인으로
- 테스트하려면 번들을 Google Play에 업로드하세요. 내부 테스트 트랙이나 알파 또는 베타 채널을 사용하여 번들을 프로덕션에 출시하기 전에 테스트할 수 있습니다.
- Play 스토어에 번들을 업로드하려면 다음 단계를 따르세요.
Build an APK
App Bundle이 APK보다 선호되지만, 아직 App Bundle을 지원하지 않는 스토어가 있습니다. 이 경우, 각 target ABI(Application Binary Interface)에 대해 release APK를 빌드하세요.
서명 단계를 완료했다면, APK는 서명됩니다. 이 지점에서, reverse engineer를 더 어렵게 만들기 위한 Dart 코드를 난독화를 고려할 수 있습니다. 코드를 난독화하려면 빌드 명령에 몇 가지 플래그를 추가해야 합니다.
command line에서:
cd [project]
를 입력하세요.flutter build apk --split-per-abi
를 실행하세요. (flutter build
명령은 기본적으로--release
로 설정됩니다.)
이 명령은 세 개의 APK 파일을 생성합니다:
[project]/build/app/outputs/apk/release/app-armeabi-v7a-release.apk
[project]/build/app/outputs/apk/release/app-arm64-v8a-release.apk
[project]/build/app/outputs/apk/release/app-x86_64-release.apk
--split-per-abi
플래그를 제거하면 모든 target ABI에 대해 컴파일된 코드가 포함된 fat APK가 생성됩니다. 이러한 APK는 분할된 것보다 크기가 더 크며, 사용자가 장치 아키텍처에 적합하지 않은 네이티브 바이너리를 다운로드하게 됩니다.
Install an APK on a device
연결된 Android 장치에 APK를 설치하려면 다음 단계를 따르세요.
command line에서:
- Android 장치를 USB 케이블로 컴퓨터에 연결하세요.
cd [project]
를 입력하세요.flutter install
을 실행하세요.
Google Play Store에 게시
Google Play 스토어에 앱을 게시하는 방법에 대한 자세한 내용은, Google Play 출시 문서를 확인하세요.
앱 버전 번호 업데이트
앱의 기본 version number는 1.0.0
입니다. 업데이트하려면, pubspec.yaml
파일로 이동하여 다음 줄을 업데이트하세요:
version: 1.0.0+1
version number는 위의 예에서 1.0.0
과 같이 점으로 구분된 3개의 숫자이며, 위의 예에서 1
과 같이 +
로 구분된 선택적(optional) build number가 뒤에 옵니다.
--build-name
및 --build-number
를 각각 지정하여 Flutter 빌드에서 version과 build number를 모두 재정의할 수 있습니다.
Android에서 build-name
은 versionName
으로, build-number
는 versionCode
로 사용됩니다. 자세한 내용은 Android 문서의 Version your app를 확인하세요.
Android용 앱을 다시 빌드하면, pubspec 파일의 version number의 업데이트가 local.properties
파일의 versionName
및 versionCode
를 업데이트합니다.
안드로이드 출시 FAQ
다음은 Android 앱 배포에 관해 자주 묻는 몇 가지 질문입니다.
언제 app bundle과 APK를 빌드해야 하나요?
Google Play Store는 사용자에게 앱을 더 효율적으로 전달하기 위해 app bundle을 배포하는 것을 권장합니다. 그러나 Play Store 이외의 수단으로 앱을 배포하는 경우, APK가 유일한 옵션일 수 있습니다.
fat APK가 뭔가요?
fat APK는 여러 ABI에 대한 바이너리가 포함된 단일 APK입니다.
단일 APK가 여러 아키텍처에서 실행되므로 더 넓은 호환성이 있다는 이점이 있지만, 파일 크기가 훨씬 커서 사용자가 애플리케이션을 설치할 때 더 많은 바이트를 다운로드하고 저장하게 된다는 단점이 있습니다. App Bundle 대신 APK로 빌드할 때, --split-per-abi
플래그를 사용하여 Build an APK에 설명된 대로 분할 APK 빌드를 강력히 권장합니다.
지원되는 target 아키텍처는 뭔가요?
release mode에서 애플리케이션을 빌드할 때, Flutter 앱은 armeabi-v7a (ARM 32-bit), arm64-v8a (ARM 64-bit), and x86-64 (x86 64-bit) 용으로 컴파일될 수 있습니다. Flutter는 ARM 에뮬레이션을 통해 x86 Android용 빌드를 지원합니다.
flutter build appbundle
로 생성된 앱 번들을 어떻게 서명하나요?
앱 서명을 참조하세요.
Android Studio에서 릴리스 빌드를 어떻게 하나요?
Android Studio에서 앱 폴더 하위의 android/
폴더를 엽니다. 그런 다음, 프로젝트 패널에서 build.gradle (Module: app) 을 선택하세요:
다음으로, 빌드 변형을 선택하세요. 메인 메뉴에서 Build > Select Build Variant를 클릭하세요. Build Variants 패널에서 variants 중 하나를 선택합니다(debug가 기본값):
결과로 생성된 app bundle 또는 APK 파일은 앱 폴더 내의 build/app/outputs
에 있습니다.