Kivy 앱 배포: Android APK 생성하기 🚀
모바일 앱 개발 시장이 급속도로 성장하면서, 크로스 플랫폼 개발 도구의 중요성이 더욱 부각되고 있습니다. 그 중에서도 Kivy는 Python 개발자들에게 특히 주목받는 프레임워크입니다. Kivy를 사용하면 데스크톱과 모바일 플랫폼에서 동작하는 애플리케이션을 단일 코드베이스로 개발할 수 있어, 개발 효율성을 크게 높일 수 있습니다.
이 글에서는 Kivy를 사용하여 개발한 앱을 Android APK로 변환하고 배포하는 과정을 상세히 다룰 예정입니다. 앱 개발부터 배포까지의 전 과정을 다루므로, 재능넷과 같은 플랫폼에서 모바일 앱 개발 서비스를 제공하고자 하는 개발자들에게 특히 유용할 것입니다.
Kivy로 개발한 앱을 Android APK로 변환하는 과정은 크게 다음과 같은 단계로 나눌 수 있습니다:
- 개발 환경 설정
- Kivy 앱 개발
- Buildozer 설치 및 설정
- APK 빌드
- APK 서명 및 최적화
- Google Play Store 배포
각 단계별로 자세히 살펴보며, 실제 개발 과정에서 마주칠 수 있는 문제점들과 그 해결 방법도 함께 알아보겠습니다. 🛠️
1. 개발 환경 설정 🖥️
Kivy 앱을 Android APK로 변환하기 위해서는 먼저 적절한 개발 환경을 구축해야 합니다. 이 과정은 운영 체제에 따라 약간의 차이가 있을 수 있지만, 기본적인 단계는 동일합니다.
1.1 Python 설치
Kivy는 Python 기반 프레임워크이므로, 먼저 Python을 설치해야 합니다. Python 3.7 이상의 버전을 권장합니다.
# Python 버전 확인
python --version
만약 Python이 설치되어 있지 않다면, Python 공식 웹사이트에서 다운로드하여 설치할 수 있습니다.
1.2 가상 환경 생성
프로젝트별로 독립적인 환경을 유지하기 위해 가상 환경을 사용하는 것이 좋습니다. 다음 명령어로 가상 환경을 생성하고 활성화할 수 있습니다:
# 가상 환경 생성
python -m venv kivy_env
# 가상 환경 활성화 (Windows)
kivy_env\Scripts\activate
# 가상 환경 활성화 (macOS/Linux)
source kivy_env/bin/activate
1.3 Kivy 설치
가상 환경이 활성화된 상태에서 pip를 사용하여 Kivy를 설치합니다:
pip install kivy
Kivy의 최신 버전이 설치되었는지 확인하려면 다음 명령어를 실행합니다:
python -c "import kivy; print(kivy.__version__)"
1.4 Android SDK 설치
Android APK를 생성하기 위해서는 Android SDK가 필요합니다. Android Studio를 설치하면 SDK도 함께 설치됩니다.
- Android Studio 공식 웹사이트에서 Android Studio를 다운로드하여 설치합니다.
- 설치 과정에서 "Custom" 설치를 선택하고, "Android SDK"를 포함시킵니다.
- 설치가 완료되면 Android Studio를 실행하고, "Tools" > "SDK Manager"에서 필요한 SDK 플랫폼과 도구를 설치합니다.
1.5 Java Development Kit (JDK) 설치
Android SDK를 사용하기 위해서는 JDK가 필요합니다. OpenJDK 8 또는 그 이상의 버전을 설치하는 것이 좋습니다.
Ubuntu나 다른 Debian 기반 시스템에서는 다음 명령어로 OpenJDK를 설치할 수 있습니다:
sudo apt-get install openjdk-8-jdk
Windows나 macOS 사용자는 AdoptOpenJDK 웹사이트에서 JDK를 다운로드하여 설치할 수 있습니다.
1.6 환경 변수 설정
Android SDK와 JDK의 경로를 시스템 환경 변수에 추가해야 합니다. 이는 운영 체제에 따라 다르게 설정됩니다.
Windows의 경우:
- 시스템 속성 > 고급 > 환경 변수로 이동합니다.
- 시스템 변수에 다음을 추가합니다:
- ANDROID_HOME: Android SDK 경로 (예: C:\Users\YourUsername\AppData\Local\Android\Sdk)
- JAVA_HOME: JDK 설치 경로 (예: C:\Program Files\AdoptOpenJDK\jdk-8.0.275.1-hotspot)
- Path 변수에 다음을 추가합니다:
- %ANDROID_HOME%\tools
- %ANDROID_HOME%\platform-tools
macOS/Linux의 경우 ~/.bashrc 또는 ~/.zshrc 파일에 다음 라인을 추가합니다:
export ANDROID_HOME=$HOME/Android/Sdk
export PATH=$PATH:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools
export JAVA_HOME=/path/to/your/jdk
이렇게 개발 환경 설정이 완료되었습니다. 다음 단계에서는 실제 Kivy 앱을 개발하는 과정을 살펴보겠습니다. 🎉
2. Kivy 앱 개발 💻
이제 개발 환경이 준비되었으니, Kivy를 사용하여 실제 앱을 개발해보겠습니다. 이 섹션에서는 간단한 "Hello, World!" 앱부터 시작하여 점진적으로 복잡한 기능을 추가해 나갈 것입니다.
2.1 "Hello, World!" 앱 만들기
먼저 가장 기본적인 Kivy 앱을 만들어 보겠습니다. 다음 코드를 main.py
파일에 저장합니다:
from kivy.app import App
from kivy.uix.label import Label
class HelloWorldApp(App):
def build(self):
return Label(text='Hello, World!')
if __name__ == '__main__':
HelloWorldApp().run()
이 코드는 화면에 "Hello, World!"라는 텍스트를 표시하는 간단한 앱을 만듭니다. 실행하려면 터미널에서 다음 명령어를 입력하세요:
python main.py
앱이 실행되면 "Hello, World!" 텍스트가 표시된 창이 나타날 것입니다.
2.2 사용자 인터페이스 개선하기
이제 좀 더 복잡한 사용자 인터페이스를 만들어 보겠습니다. 버튼을 추가하고, 버튼을 클릭하면 텍스트가 변경되도록 해보겠습니다.
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
class ImprovedApp(App):
def build(self):
layout = BoxLayout(orientation='vertical')
self.label = Label(text='Hello, Kivy!')
button = Button(text='Click me!')
button.bind(on_press=self.on_button_press)
layout.add_widget(self.label)
layout.add_widget(button)
return layout
def on_button_press(self, instance):
self.label.text = 'Button clicked!'
if __name__ == '__main__':
ImprovedApp().run()
이 코드는 수직으로 정렬된 BoxLayout을 사용하여 레이블과 버튼을 배치합니다. 버튼을 클릭하면 레이블의 텍스트가 변경됩니다.
2.3 Kivy 언어 (KV 언어) 사용하기
Kivy는 사용자 인터페이스를 정의하기 위한 자체 언어인 KV 언어를 제공합니다. KV 언어를 사용하면 UI 레이아웃과 스타일을 Python 코드와 분리하여 관리할 수 있습니다.
다음과 같이 improved.kv
파일을 생성합니다:
BoxLayout:
orientation: 'vertical'
Label:
id: my_label
text: 'Hello, Kivy!'
Button:
text: 'Click me!'
on_press: app.change_label_text()
그리고 main.py
파일을 다음과 같이 수정합니다:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
class ImprovedApp(App):
def build(self):
return BoxLayout()
def change_label_text(self):
self.root.ids.my_label.text = 'Button clicked!'
if __name__ == '__main__':
ImprovedApp().run()
이렇게 하면 UI 정의와 로직이 분리되어 코드의 가독성과 유지보수성이 향상됩니다.
2.4 데이터 바인딩 사용하기
Kivy는 강력한 데이터 바인딩 기능을 제공합니다. 이를 통해 프로퍼티 간의 관계를 선언적으로 정의할 수 있습니다.
main.py
파일을 다음과 같이 수정합니다:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
class RootWidget(BoxLayout):
label_text = StringProperty('Hello, Kivy!')
def change_label_text(self):
self.label_text = 'Button clicked!'
class ImprovedApp(App):
def build(self):
return RootWidget()
if __name__ == '__main__':
ImprovedApp().run()
그리고 improved.kv
파일을 다음과 같이 수정합니다:
<RootWidget>:
orientation: 'vertical'
Label:
text: root.label_text
Button:
text: 'Click me!'
on_press: root.change_label_text()
이제 label_text
프로퍼티가 변경될 때마다 Label의 텍스트가 자동으로 업데이트됩니다.
2.5 이미지 추가하기
앱에 이미지를 추가하는 것도 매우 간단합니다. 먼저 프로젝트 디렉토리에 이미지 파일(예: 'logo.png')을 추가한 후, KV 파일을 다음과 같이 수정합니다:
<RootWidget>:
orientation: 'vertical'
Image:
source: 'logo.png'
size_hint: 1, 0.7
Label:
text: root.label_text
size_hint: 1, 0.15
Button:
text: 'Click me!'
on_press: root.change_label_text()
size_hint: 1, 0.15
이렇게 하면 이미지, 레이블, 버튼이 수직으로 배치된 앱이 만들어집니다.
2.6 화면 전환 구현하기
대부분의 앱은 여러 화면으로 구성되어 있습니다. Kivy의 ScreenManager
를 사용하면 쉽게 화면 전환을 구현할 수 있습니다.
main.py
파일을 다음과 같이 수정합니다:
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import StringProperty
class FirstScreen(Screen):
label_text = StringProperty('This is the first screen')
class SecondScreen(Screen):
label_text = StringProperty('This is the second screen')
class RootWidget(ScreenManager):
pass
class ImprovedApp(App):
def build(self):
return RootWidget()
if __name__ == '__main__':
ImprovedApp().run()
그리고 improved.kv
파일을 다음과 같이 수정합니다:
<FirstScreen>:
BoxLayout:
orientation: 'vertical'
Label:
text: root.label_text
Button:
text: 'Go to Second Screen'
on_press: root.manager.current = 'second'
<SecondScreen>:
BoxLayout:
orientation: 'vertical'
Label:
text: root.label_text
Button:
text: 'Go to First Screen'
on_press: root.manager.current = 'first'
<RootWidget>:
FirstScreen:
name: 'first'
SecondScreen:
name: 'second'
이제 앱에 두 개의 화면이 생겼고, 버튼을 통해 화면 간 전환이 가능해졌습니다.
2.7 애니메이션 추가하기
Kivy의 Animation
클래스를 사용하면 쉽게 애니메이션을 추가할 수 있습니다. 다음은 버튼을 클릭할 때 레이블이 페이드 인/아웃되는 예제입니다:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
from kivy.animation import Animation
class RootWidget(BoxLayout):
label_text = StringProperty('Hello, Kivy!')
def change_label_text(self):
anim = Animation(opacity=0, duration=1) + Animation(opacity=1, duration=1)
anim.start(self.ids.my_label)
self.label_text = 'Animated!'
class AnimatedApp(App):
def build(self):
return RootWidget()
if __name__ == '__main__':
AnimatedApp().run()
KV 파일도 다음과 같이 수정합니다:
<RootWidget>:
orientation: 'vertical'
Label:
id: my_label
text: root.label_text
Button:
text: 'Animate!'
on_press: root.change_label_text()
이제 버튼을 클릭하면 레이블이 페이드 아웃되었다가 다시 페이드 인되면서 텍스트가 변경됩니다.
2.8 네트워크 요청 처리하기
대부분의 모바일 앱은 서버와 통신해야 합니다. Kivy 앱에서 네트워크 요청을 처리하는 방법을 알아보겠습니다. 여기서는 requests
라이브러리를 사용하겠습니다.
먼저 requests
를 설치합니다:
pip install requests
그리고 다음과 같이 코드를 수정합니다:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
import requests
from kivy.clock import Clock
class RootWidget(BoxLayout):
api_result = StringProperty('Click the button to fetch data')
def fetch_data(self, *args):
try:
response = requests.get('https://api.github.com')
self.api_result = f'GitHub API Status: {response.status_code}'
except Exception as e:
self.api_result = f'Error: {str(e)}'
def on_button_press(self):
self.api_result = 'Fetching data...'
Clock.schedule_once(self.fetch_data, 1) # Run after 1 second
class NetworkApp(App):
def build(self):
return RootWidget()
if __name__ == '__main__':
NetworkApp().run()
KV 파일은 다음과 같이 수정합니다:
<RootWidget>:
orientation: 'vertical'
Label:
text: root.api_result
Button:
text: 'Fetch Data'
on_press: root.on_button_press()
이 예제에서는 버튼을 클릭하면 GitHub API에 GET 요청을 보내고 응답 상태 코드를 표시합니다. 네트워크 요청은 비동기적으로 처리되어 앱의 UI가 멈추지 않습니다.
2.9 로컬 저장소 사용하기
앱에서 데이터를 로컬에 저장하고 불러오는 것은 매우 중요한 기능입니다. Kivy는 App.get_running_app().user_data_dir
을 통해 앱의 데이터 디렉토리에 접근할 수 있게 해줍니다. 이를 이용해 간단한 설정 저장 기능을 구현해보겠습니다.
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
import json
import os
class RootWidget(BoxLayout):
user_name = StringProperty('')
def save_name(self):
app = App.get_running_app()
data = {'name': self.user_name}
with open(os.path.join(app.user_data_dir, 'settings.json'), 'w') as f:
json.dump(data, f)
def load_name(self):
app = App.get_running_app()
try:
with open(os.path.join(app.user_data_dir, 'settings.json'), 'r') as f:
data = json.load(f)
self.user_name = data.get('name', '')
except FileNotFoundError:
pass
class StorageApp(App):
def build(self):
root = RootWidget()
root.load_name()
return root
if __name__ == '__main__':
StorageApp().run()
KV 파일은 다음과 같이 수정합니다:
<RootWidget>:
orientation: 'vertical'
TextInput:
text: root.user_name
on_text: root.user_name = self.text
Button:
text: 'Save Name'
on_press: root.save_name()
Label:
text: f'Current Name: {root.user_name}'
이 예제에서는 사용자가 입력한 이름을 JSON 파일로 저장하고, 앱이 시작될 때 저장된 이름을 불러옵니다.
2.10 권한 요청 처리하기
Android 앱에서는 특정 기능을 사용하기 위해 사용자의 권한이 필요할 수 있습니다. Kivy에서는 plyer
라이브러리를 사용하여 권한 요청을 처리할 수 있습니다.
먼저 plyer
를 설치합니다:
pip install plyer
그리고 다음과 같이 코드를 수정합니다:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
from plyer import gps
from kivy.clock import Clock
class RootWidget(BoxLayout):
gps_location = StringProperty('GPS is off')
def request_android_permissions(self):
from android.permissions import request_permissions, Permission
request_permissions([Permission.ACCESS_COARSE_LOCATION,
Permission.ACCESS_FINE_LOCATION])
def get_gps_location(self, *args):
try:
gps.configure(on_location=self.on_location)
gps.start()
except NotImplementedError:
self.gps_location = 'GPS is not implemented for your platform'
def on_location(self, **kwargs):
self.gps_location = f'lat: {kwargs["lat"]}, lon: {kwargs["lon"]}'
class GPSApp(App):
def build(self):
root = RootWidget()
Clock.schedule_once(root.request_android_permissions, 0)
return root
if __name__ == '__main__':
GPSApp().run()
KV 파일은 다음과 같이 수정합니다:
<RootWidget>:
orientation: 'vertical'
Button:
text: 'Get GPS Location'
on_press: root.get_gps_location()
Label:
text: root.gps_location
이 예제에서는 GPS 권한을 요청하고, 사용자가 권한을 허용하면 현재 위치의 위도와 경도를 표시합니다.
이렇게 해서 Kivy를 사용한 기본적인 앱 개발 과정을 살펴보았습니다. 다음 섹션에서는 이렇게 만든 앱을 Android APK로 변환하는 과정을 알아보겠습니다. 🚀
3. Buildozer 설치 및 설정 🛠️
Kivy 앱을 Android APK로 변환하기 위해서는 Buildozer라는 도구를 사용합니다. Buildozer는 Kivy 앱을 다양한 플랫폼용 패키지로 만들어주는 강력한 도구입니다. 이 섹션에서는 Buildozer를 설치하고 설정하는 방법을 자세히 알아보겠습니다.
3.1 Buildozer 설치
Buildozer는 pip를 통해 쉽게 설치할 수 있습니다. 다음 명령어를 실행하세요:
pip install buildozer
Linux 사용자의 경우, 추가적인 의존성 패키지를 설치해야 할 수 있습니다. Ubuntu나 Debian 기반 시스템에서는 다음 명령어를 실행하세요:
sudo apt-get install python3-pip build-essential git python3 python3-dev ffmpeg libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev libportmidi-dev libswscale-dev libavformat-dev libavcodec-dev zlib1g-dev
macOS 사용자의 경우, Homebrew를 통해 필요한 패키지를 설치할 수 있습니다:
brew install pkg-config sdl2 sdl2_image sdl2_ttf sdl2_mixer gstreamer
3.2 Buildozer 초기화
Buildozer를 사용하기 위해서는 먼저 프로젝트를 초기화해야 합니다. 프로젝트 디렉토리에서 다음 명령어를 실행하세요:
buildozer init
이 명령어는 buildozer.spec
파일을 생성합니다. 이 파 일이 앱 빌드 과정을 제어하는 설정 파일입니다.
3.3 buildozer.spec 파일 설정
buildozer.spec
파일을 열고 다음 항목들을 프로젝트에 맞게 수정합니다:
title
: 앱의 이름package.name
: 앱의 패키지 이름 (예: com.example.myapp)package.domain
: 앱의 도메인 (예: org.test)source.dir
: 소스 코드가 있는 디렉토리 (기본값은 .)source.include_exts
: 포함할 파일 확장자 (예: py,png,jpg,kv,atlas)version
: 앱의 버전requirements
: 앱에 필요한 Python 패키지들 (예: python3,kivy)orientation
: 앱의 화면 방향 (portrait, landscape, 또는 all)fullscreen
: 전체 화면 여부 (0 또는 1)android.permissions
: 앱에 필요한 Android 권한android.api
: 타겟 Android API 레벨android.minapi
: 최소 지원 Android API 레벨android.sdk
: 사용할 Android SDK 버전android.ndk
: 사용할 Android NDK 버전
예를 들어, GPS 기능을 사용하는 앱의 경우 다음과 같이 설정할 수 있습니다:
[app]
title = My GPS App
package.name = mygpsapp
package.domain = org.example
version = 0.1
requirements = python3,kivy,plyer
orientation = portrait
fullscreen = 0
android.permissions = ACCESS_FINE_LOCATION,ACCESS_COARSE_LOCATION
android.api = 29
android.minapi = 21
android.sdk = 29
android.ndk = 19b
3.4 아이콘 및 시작 화면 설정
앱의 아이콘과 시작 화면을 설정하려면 buildozer.spec
파일에 다음 항목을 추가하세요:
# (str) Presplash of the application
presplash.filename = %(source.dir)s/data/presplash.png
# (str) Icon of the application
icon.filename = %(source.dir)s/data/icon.png
그리고 프로젝트의 data
디렉토리에 presplash.png
와 icon.png
파일을 추가하세요.
3.5 서드파티 라이브러리 추가
프로젝트에 추가적인 Python 라이브러리가 필요한 경우, requirements
항목에 추가하세요. 예를 들어:
requirements = python3,kivy,plyer,requests
일부 라이브러리는 추가적인 설정이 필요할 수 있습니다. 예를 들어, numpy
를 사용하는 경우 다음과 같이 설정해야 합니다:
requirements = python3,kivy,numpy
[app:android.meta_data]
android.meta_data = NUMPY_PACKAGE_NAME=org.numpy
3.6 Android 관련 설정
Android 특정 설정을 추가하려면 android
섹션을 사용합니다. 예를 들어:
android.wakelock = True
android.meta_data = com.google.android.gms.version=@integer/google_play_services_version
android.library_references = libs/android-support-v4.jar
3.7 빌드 옵션 설정
빌드 과정을 세밀하게 제어하려면 다음과 같은 옵션을 사용할 수 있습니다:
# (bool) If True, then skip trying to update the Android sdk
# This can be useful to avoid excess Internet downloads or save time
# when an update is due and you just want to test/build your package
android.skip_update = False
# (bool) If True, then automatically accept SDK license
# agreements. This is intended for automation only. If set to False,
# the default, you will be shown the license when first running
# buildozer.
android.accept_sdk_license = True
# (str) Android logcat filters to use
android.logcat_filters = *:S python:D
# (bool) Copy library instead of making a libpymodules.so
android.copy_libs = 1
3.8 디버그 빌드 설정
개발 중에는 디버그 빌드를 사용하는 것이 유용합니다. 다음 설정을 추가하세요:
# (bool) Indicate whether the screen should stay on
# Don't forget to add the WAKE_LOCK permission if you set this to True
android.wakelock = False
# (list) Android application meta-data to set (key=value format)
android.meta_data = android.debug=true
3.9 Gradle 설정
Android 빌드 시스템인 Gradle에 대한 설정도 가능합니다:
# (bool) Use --private data storage (True) or --dir public storage (False)
android.private_storage = True
# (str) Android NDK directory (if empty, it will be automatically downloaded.)
android.ndk_path =
# (str) Android SDK directory (if empty, it will be automatically downloaded.)
android.sdk_path =
# (str) ANT directory (if empty, it will be automatically downloaded.)
android.ant_path =
# (bool) If True, then skip trying to update the Android sdk
# This can be useful to avoid excess Internet downloads or save time
# when an update is due and you just want to test/build your package
android.skip_update = False
# (str) Android entry point, default is ok for Kivy-based app
android.entrypoint = org.renpy.android.PythonActivity
3.10 buildozer.spec 파일 검증
설정을 완료한 후, 다음 명령어로 buildozer.spec
파일의 유효성을 검사할 수 있습니다:
buildozer android debug
이 명령어는 실제로 APK를 빌드하지는 않지만, 설정 파일의 오류를 체크하고 필요한 의존성을 다운로드합니다.
이제 Buildozer 설정이 완료되었습니다. 다음 섹션에서는 실제로 APK를 빌드하는 과정을 살펴보겠습니다. 🛠️
4. APK 빌드 🏗️
Buildozer 설정이 완료되었다면, 이제 실제로 APK를 빌드할 차례입니다. 이 과정은 시간이 다소 걸릴 수 있으며, 특히 처음 빌드할 때는 필요한 모든 의존성을 다운로드해야 하므로 더 오래 걸릴 수 있습니다.
4.1 디버그 APK 빌드
개발 중에는 주로 디버그 APK를 빌드합니다. 디버그 APK는 테스트 목적으로 사용되며, Google Play Store에 업로드할 수 없습니다. 디버그 APK를 빌드하려면 다음 명령어를 실행하세요:
buildozer android debug
이 명령어는 다음과 같은 작업을 수행합니다:
- 필요한 의존성 다운로드 (처음 실행 시)
- Python 코드를 Android에서 실행 가능한 형태로 변환
- 리소스 파일 복사
- Android 프로젝트 생성
- APK 빌드
빌드가 성공적으로 완료되면, bin
디렉토리에 APK 파일이 생성됩니다.
4.2 릴리스 APK 빌드
앱을 Google Play Store에 출시하려면 릴리스 APK를 빌드해야 합니다. 릴리스 APK는 서명되어야 하며, 디버그 정보가 제거되어 있습니다. 릴리스 APK를 빌드하려면 다음 명령어를 실행하세요:
buildozer android release
릴리스 빌드를 위해서는 키스토어(keystore)가 필요합니다. 키스토어가 없다면 Buildozer가 자동으로 생성해주지만, 프로덕션 앱의 경우 직접 키스토어를 생성하고 관리하는 것이 좋습니다.
4.3 커스텀 키스토어 사용
자체 키스토어를 사용하려면 buildozer.spec
파일에 다음 설정을 추가하세요:
android.keystore = path/to/your/keystore.jks
android.keyalias = your_key_alias
android.keystore_password = your_keystore_password
android.keyalias_password = your_key_password
보안상의 이유로 패스워드를 직접 파일에 입력하는 것은 권장되지 않습니다. 대신 환경 변수를 사용할 수 있습니다:
android.keystore_password = %(KEYSTORE_PASSWORD)s
android.keyalias_password = %(KEYALIAS_PASSWORD)s
그리고 빌드 전에 환경 변수를 설정합니다:
export KEYSTORE_PASSWORD=your_keystore_password
export KEYALIAS_PASSWORD=your_key_password
4.4 빌드 로그 확인
빌드 과정에서 문제가 발생하면 로그를 확인해야 합니다. 기본적으로 Buildozer는 화면에 로그를 출력하지만, 파일로 저장하려면 다음과 같이 실행하세요:
buildozer android debug 2>&1 | tee buildozer.log
이렇게 하면 로그가 화면에 출력되면서 동시에 buildozer.log
파일에 저장됩니다.
4.5 빌드 캐시 관리
Buildozer는 빌드 속도를 높이기 위해 캐시를 사용합니다. 하지만 가끔 캐시로 인해 문제가 발생할 수 있습니다. 이런 경우 캐시를 지우고 다시 빌드해볼 수 있습니다:
buildozer android clean
buildozer android debug
모든 Buildozer 관련 파일을 지우려면 다음 명령어를 사용하세요:
buildozer distclean
4.6 특정 아키텍처용 APK 빌드
기본적으로 Buildozer는 모든 지원 아키텍처(armeabi-v7a, arm64-v8a, x86, x86_64)용 APK를 빌드합니다. 특정 아키텍처만을 대상으로 빌드하려면 buildozer.spec
파일에 다음 설정을 추가하세요:
android.arch = armeabi-v7a
여러 아키텍처를 지정하려면 쉼표로 구분하세요:
android.arch = armeabi-v7a, arm64-v8a
4.7 APK 크기 최적화
APK 크기를 줄이기 위해 다음과 같은 방법을 사용할 수 있습니다:
- 불필요한 리소스 제거:
android.add_aars = android.add_jars = android.add_libs_armeabi_v7a = android.add_libs_arm64_v8a = android.add_libs_x86 = android.add_libs_x86_64 =
- 필요한 권한만 포함:
android.permissions = INTERNET
- 불필요한 Python 모듈 제외:
android.enable_androidx = True android.enable_google_services = False
4.8 멀티 APK 지원
Google Play에서는 다양한 기기 설정에 최적화된 여러 APK를 업로드할 수 있습니다. 이를 위해 Buildozer에서 다음과 같이 설정할 수 있습니다:
[app@arm]
android.arch = armeabi-v7a
[app@arm64]
android.arch = arm64-v8a
[app@x86]
android.arch = x86
[app@x86_64]
android.arch = x86_64
이렇게 설정하면 각 아키텍처별로 별도의 APK가 생성됩니다.
4.9 빌드 자동화
CI/CD 파이프라인에서 Buildozer를 사용하여 자동으로 APK를 빌드할 수 있습니다. 예를 들어, GitHub Actions를 사용한 워크플로우 파일은 다음과 같을 수 있습니다:
name: Build Android APK
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install dependencies
run: |
pip install buildozer
sudo apt-get install -y python3-pip build-essential git python3 python3-dev ffmpeg libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev libportmidi-dev libswscale-dev libavformat-dev libavcodec-dev zlib1g-dev
- name: Build APK
run: buildozer android debug
- name: Upload APK
uses: actions/upload-artifact@v2
with:
name: app-debug
path: bin/*.apk
이 워크플로우는 main 브랜치에 푸시가 발생할 때마다 자동으로 APK를 빌드하고, 결과물을 아티팩트로 업로드합니다.
4.10 빌드 문제 해결
APK 빌드 과정에서 문제가 발생할 경우, 다음과 같은 방법으로 해결할 수 있습니다:
- 로그 확인:
buildozer.log
파일을 자세히 살펴봅니다. - 의존성 업데이트:
buildozer android update
명령어로 모든 의존성을 최신 버전으로 업데이트합니다. - 클린 빌드:
buildozer android clean
후 다시 빌드합니다. - Buildozer 버전 확인: 최신 버전의 Buildozer를 사용하고 있는지 확인합니다.
- Android SDK/NDK 버전 확인:
buildozer.spec
파일에서 지정한 버전이 호환되는지 확인합니다. - Python 버전 확인: 사용 중인 Python 버전이 Buildozer와 호환되는지 확인합니다.
이제 APK 빌드 과정을 마쳤습니다. 다음 섹션에서는 생성된 APK에 서명하고 최적화하는 방법을 알아보겠습니다. 📱
5. APK 서명 및 최적화 🔐
APK를 성공적으로 빌드했다면, 이제 서명하고 최적화하는 단계가 남았습니다. 이 과정은 앱의 보안을 강화하고 성능을 개선하는 데 중요합니다.
5.1 APK 서명의 중요성
APK 서명은 다음과 같은 이유로 중요합니다:
- 앱의 출처를 인증합니다.
- 앱의 무결성을 보장합니다.
- Google Play Store에 앱을 등록하기 위해 필요합니다.
- 앱 업데이트 시 동일한 키로 서명해야 합니다.
5.2 키스토어 생성
APK 서명을 위해서는 키스토어가 필요합니다. 키스토어를 생성하는 방법은 다음과 같습니다:
keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000
이 명령어를 실행하면 몇 가지 정보를 입력하라는 프롬프트가 나타납니다. 입력한 정보는 나중에 Google Play Store에 표시될 수 있으므로 주의해서 입력하세요.
5.3 APK 서명
생성된 키스토어를 사용하여 APK에 서명하는 방법은 다음과 같습니다:
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore my_application.apk alias_name
이 명령어를 실행하면 키스토어 비밀번호를 입력하라는 프롬프트가 나타납니다.
5.4 APK 최적화 (zipalign)
서명된 APK를 최적화하면 앱의 메모리 사용량을 줄일 수 있습니다. 이를 위해 Android SDK에 포함된 zipalign 도구를 사용합니다:
zipalign -v 4 my_application.apk my_application-aligned.apk
5.5 APK 확인
최종적으로 APK가 올바르게 서명되었는지 확인할 수 있습니다:
jarsigner -verify -verbose -certs my_application-aligned.apk
5.6 자동화된 서명 및 최적화
Buildozer를 사용하면 이 과정을 자동화할 수 있습니다. buildozer.spec
파일에 다음 설정을 추가하세요:
android.keystore = path/to/your/keystore.jks
android.keyalias = your_key_alias
android.keystore_password = your_keystore_password
android.keyalias_password = your_key_password
그리고 릴리스 빌드를 실행하면 자동으로 서명된 APK가 생성됩니다:
buildozer android release
5.7 APK 분할 (App Bundle)
Google Play Store는 Android App Bundle(AAB) 형식을 권장합니다. AAB는 사용자의 기기에 맞는 최적화된 APK를 동적으로 생성합니다. Buildozer에서 AAB를 생성하려면 다음 설정을 추가하세요:
android.accept_sdk_license = True
android.release_artifact = aab
그리고 다음 명령어로 AAB를 빌드합니다:
buildozer android release
5.8 ProGuard 사용
ProGuard는 코드 난독화와 최적화를 수행하여 APK 크기를 줄이고 리버스 엔지니어링을 어렵게 만듭니다. Buildozer에서 ProGuard를 사용하려면 다음 설정을 추가하세요:
android.minify_python = True
5.9 다중 ABI 지원
다양한 CPU 아키텍처를 지원하기 위해 여러 ABI(Application Binary Interface)를 포함할 수 있습니다:
android.archs = armeabi-v7a, arm64-v8a, x86, x86_64
5.10 리소스 최적화
앱의 리소스를 최적화하여 APK 크기를 줄일 수 있습니다:
- 이미지 압축: PNG 이미지를 최적화하고, 가능한 경우 WebP 형식을 사용합니다.
- 불필요한 리소스 제거: 사용하지 않는 리소스 파일을 제거합니다.
- 다국어 지원: 필요한 언어만 포함합니다.
android.whitelist = lib-dynload/termios.so, lib-dynload/mmap.so, lib-dynload/math.so
이 설정은 필요한 Python 모듈만 포함하도록 합니다.
이제 APK 서명과 최적화 과정을 마쳤습니다. 다음 섹션에서는 최종적으로 Google Play Store에 앱을 배포하는 방법을 알아보겠습니다. 🚀
6. Google Play Store 배포 🌍
APK를 성공적으로 빌드하고 서명했다면, 이제 Google Play Store에 앱을 배포할 준비가 되었습니다. 이 과정은 몇 가지 단계로 나눌 수 있습니다.
6.1 Google Play Console 계정 생성
먼저 Google Play Console 계정이 필요합니다. 아직 계정이 없다면 다음 단계를 따라 생성하세요:
- Google Play Console에 접속합니다.
- '새 계정 만들기'를 클릭합니다.
- 개발자 계정 유형을 선택합니다 (개인 또는 조직).
- 필요한 정보를 입력하고 개발자 배포 계약에 동의합니다.
- 등록 비용을 지불합니다 (일회성 $25).
6.2 앱 정보 입력
Google Play Console에 로그인한 후, 다음 단계를 따라 앱 정보를 입력하세요:
- '모든 앱' 페이지에서 '앱 만들기'를 클릭합니다.
- 앱의 기본 정보를 입력합니다:
- 앱 이름
- 기본 언어
- 앱 또는 게임
- 유료 또는 무료
- '앱 만들기'를 클릭하여 계속 진행합니다.
6.3 스토어 등록 정보 설정
앱의 스토어 등록 정보를 설정합니다. 이는 사용자가 Play Store에서 볼 수 있는 정보입니다:
- 앱 설명 (짧은 설명 및 전체 설명)
- 스크린샷 (최소 2개, 최대 8개)
- 고해상도 아이콘
- 특징 그래픽
- 프로모션 비디오 (선택사항)
- 개인정보처리방침 URL
6.4 콘텐츠 등급 설정
Google Play Store는 모든 앱에 대해 콘텐츠 등급을 요구합니다. 이는 사용자가 앱의 적합성을 판단하는 데 도움을 줍니다:
- Play Console의 '콘텐츠 등급' 섹션으로 이동합니다.
- 질문지를 작성합니다. 이는 앱의 콘텐츠에 대한 정보를 수집합니다.
- 답변을 제출하면 자동으로 콘텐츠 등급이 생성됩니다.
- 생성된 등급을 검토하고 확인합니다.
6.5 가격 및 배포 설정
앱의 가격과 배포 국가를 설정합니다:
- '가격 책정 및 배포' 섹션으로 이동합니다.
- 앱이 무료인지 유료인지 선택합니다.
- 앱을 배포할 국가를 선택합니다.
- 앱 내 구매 여부를 지정합니다 (해당되는 경우).
6.6 APK 또는 App Bundle 업로드
이제 빌드한 APK 또는 App Bundle을 업로드할 차례입니다:
- '앱 번들 및 APK' 섹션으로 이동합니다.
- '프로덕션' 트랙을 선택합니다.
- '새 버전 만들기'를 클릭합니다.
- APK 또는 App Bundle 파일을 업로드합니다.
- 버전 이름과 버전 코드를 확인합니다.
6.7 출시 노트 작성
사용자에게 앱의 새로운 기능이나 변경 사항을 알리는 출시 노트를 작성합니다:
- '출시 노트' 섹션으로 이동합니다.
- 지원하는 각 언어에 대해 출시 노트를 작성합니다.
- 주요 변경 사항, 새로운 기능, 버그 수정 등을 간단히 설명합니다.
6.8 앱 검토 및 출시
모든 정보를 입력하고 APK를 업로드했다면, 앱을 검토하고 출시할 준비가 된 것입니다:
- '앱 출시' 섹션으로 이동합니다.
- 모든 섹션이 완료되었는지 확인합니다.
- '검토 시작'을 클릭합니다.
Google은 앱을 검토하고, 문제가 없다면 승인합니다. 이 과정은 보통 몇 시간에서 며칠이 걸릴 수 있습니다.
6.9 앱 업데이트
앱을 업데이트하려면 다음 단계를 따릅니다:
- 새 버전의 APK 또는 App Bundle을 빌드합니다.
- 버전 코드를 증가시킵니다.
- Play Console에 새 버전을 업로드합니다.
- 변경 사항을 설명하는 새 출시 노트를 작성합니다.
- 업데이트를 검토하고 출시합니다.
6.10 앱 성과 모니터링
앱이 출시된 후에는 Play Console에서 다양한 지표를 모니터링할 수 있습니다:
- 설치 수 및 활성 사용자 수
- 평점 및 리뷰
- 충돌 보고서 및 ANR (Application Not Responding) 오류
- 수익 (유료 앱 또는 인앱 구매가 있는 경우)
이러한 지표를 주기적으로 확인하고, 사용자 피드백에 적극적으로 대응하여 앱을 지속적으로 개선하세요.
6.11 ASO (App Store Optimization)
ASO는 앱의 가시성을 높이고 더 많은 사용자를 유치하는 데 도움이 됩니다:
- 관련성 높은 키워드를 앱 제목과 설명에 포함시킵니다.
- 고품질의 스크린샷과 비디오를 사용합니다.
- 정기적으로 앱을 업데이트하고 새로운 기능을 추가합니다.
- 사용자 리뷰에 신속하게 응답합니다.
6.12 마케팅 및 프로모션
Google Play Store에 앱을 출시하는 것은 시작일 뿐입니다. 앱의 성공을 위해서는 적극적인 마케팅과 프로모션이 필요합니다:
- 소셜 미디어를 활용하여 앱을 홍보합니다.
- 관련 블로그나 뉴스 사이트에 앱을 소개합니다.
- 인플루언서 마케팅을 고려해봅니다.
- Google Ads를 사용하여 앱 광고를 실행합니다.
- 앱 리뷰 사이트에 앱을 제출합니다.
이렇게 해서 Kivy로 개발한 Android 앱을 Google Play Store에 성공적으로 배포하는 전체 과정을 살펴보았습니다. 이 과정은 처음에는 복잡해 보일 수 있지만, 경험이 쌓이면 점점 더 쉬워질 것입니다. 지속적인 업데이트와 사용자 피드백 반영을 통해 앱을 계속 발전시켜 나가세요. 앱 개발과 배포 여정에서 행운이 함께하기를 바랍니다! 🚀📱