Google은 흑인 공동체를 위한 인종 간 평등을 진전시키기 위해 노력하고 있습니다. Google에서 어떤 노력을 하고 있는지 확인하세요.

Play Feature Delivery 개요

Google Play의 앱 제공 모델은 Android App Bundle을 사용하여 각 사용자의 기기 설정에 최적화된 APK를 생성하고 제공하므로 사용자는 앱을 실행하는 데 필요한 코드와 리소스만 다운로드하면 됩니다.

Play Feature Delivery는 App Bundle의 고급 기능을 사용하여 앱의 특정 기능을 조건부로 제공하거나 주문형으로 다운로드할 수 있도록 합니다.

맞춤 제공을 위한 기능 모듈 사용

기능 모듈의 고유한 이점은 Android 5.0(API 수준 21) 이상을 실행하는 기기에 앱의 다양한 기능을 다운로드하는 방법 및 시기를 맞춤설정할 수 있다는 점입니다. 예를 들어 앱의 최초 다운로드 크기를 줄이기 위해 특정 기능은 주문형으로 필요에 따라 다운로드되도록 설정하거나 사진 촬영 또는 증강 현실 기능 지원과 같은 특정 기능을 지원하는 기기에만 다운로드되도록 설정할 수 있습니다.

앱을 App Bundle로 업로드하면 기본적으로 매우 최적화된 다운로드를 제공할 수 있지만 더 고급의 맞춤설정 가능한 기능 제공 옵션을 사용하려면 기능 모듈을 사용하여 앱 기능을 추가로 설정하고 모듈화해야 합니다. 즉, 기능 모듈은 각각 필요에 따라 다운로드되도록 설정할 수 있는 모듈식 기능을 생성하기 위한 기본 구성요소를 제공합니다.

사용자가 온라인 마켓플레이스에서 상품을 사고팔 수 있는 앱을 생각해 보세요. 앱의 다음 기능을 각각 별도의 기능 모듈로 모듈화할 수 있습니다.

  • 계정 로그인 및 생성
  • 마켓플레이스 탐색
  • 판매할 상품 배치
  • 결제 처리

아래 표에서는 기능 모듈이 지원하는 다양한 제공 옵션을 소개하고, 이러한 옵션을 사용하여 샘플 마켓플레이스 앱의 최초 다운로드 크기를 최적화할 수 있는 방법을 설명합니다.

제공 옵션 동작 샘플 사용 사례 시작하기
설치 시 제공 위에서 설명한 제공 옵션을 전혀 설정하지 않은 기능 모듈은 기본적으로 앱 설치 시 다운로드됩니다. 이 동작은 고급 제공 옵션을 점진적으로 수용할 수 있다는 의미이기 때문에 중요합니다. 예를 들어 Play Core 라이브러리를 사용하여 주문형 다운로드를 완전히 구현한 후에만 앱 기능 모듈화를 활용하고 주문형 전송을 사용 설정할 수 있습니다.

또한 앱에서 나중에 기능을 제거하도록 요청할 수 있습니다. 만약 앱 설치 시 특정 기능이 필요하며 그 후에는 필요하지 않다면 기기에서 해당 기능을 삭제하도록 요청함으로써 설치 크기를 줄일 수 있습니다.

마켓플레이스에서 상품을 사고파는 방법에 관한 대화형 가이드와 같은 특정 교육 활동이 앱에 있다면 기본적으로 앱 설치 시 이러한 기능을 포함할 수 있습니다.

하지만 앱의 설치 크기를 줄이기 위해 앱에서는 사용자가 교육을 마친 후 이 기능을 삭제하도록 요구할 수 있습니다.

고급 제공 옵션을 설정하지 않은 기능 모듈을 사용하여 앱을 모듈화합니다.

사용자에게 더 이상 필요하지 않은 특정 기능 모듈을 삭제함으로써 앱의 설치 크기를 줄이는 방법에 관해 알아보려면 설치된 모듈 관리를 참고하세요.

주문형 제공 앱이 필요에 따라 기능 모듈을 요청하고 다운로드할 수 있도록 허용합니다. 마켓플레이스 앱을 사용하는 사용자의 20%만 판매를 위해 상품을 게시한다면 대부분의 사용자를 위해 최초 다운로드 크기를 줄일 수 있는 좋은 전략은 사진을 찍고 상품 설명을 추가하며 상품을 판매 가능하도록 배치하는 것과 관련된 기능을 주문형 다운로드로 설정하는 것입니다. 즉, 사용자가 마켓플레이스에 판매할 상품을 배치하는 데 관심을 보일 때만 앱의 판매 기능에 관한 기능 모듈이 다운로드되도록 설정할 수 있습니다.

또한 사용자가 일정 기간이 지난 후 더 이상 상품을 판매하지 않는다면 앱이 이 기능을 제거하도록 요청하여 설치된 크기를 줄일 수 있습니다.

기능 모듈을 만들고 주문형 제공을 설정합니다. 그러면 앱이 Play Core 라이브러리를 사용하여 주문형 모듈을 다운로드하도록 요청할 수 있습니다.
조건부 제공 앱 설치 시 모듈화된 기능이 다운로드될지 여부를 결정하기 위해 하드웨어 기능, 언어, 최소 API 수준과 같은 특정 사용자 기기 요구사항을 지정하도록 허용합니다. 마켓플레이스 앱이 전 세계에 제공되는 경우 특정 지역에서만 사용되는 결제 수단을 지원해야 할 수 있습니다. 앱의 최초 다운로드 크기를 줄이려면 특정 유형의 결제 수단을 처리하는 별도의 기능 모듈을 만들어 등록된 언어에 따라 사용자 기기에 조건부로 설치되도록 할 수 있습니다. 기능 모듈을 만들고 조건부 제공을 설정합니다.
인스턴트 제공 Google Play 인스턴트를 사용하면 사용자가 기기에 APK를 설치하지 않고도 앱과 상호작용할 수 있습니다. 또는 Google Play 스토어의 '사용해 보기' 버튼이나 개발자가 만든 URL을 통해 앱을 사용해 볼 수 있습니다. 이런 형식으로 콘텐츠를 제공하면 더 쉽게 앱 참여도를 높일 수 있습니다.

인스턴트 제공 기능을 사용하면 Google Play 인스턴트를 활용하여 사용자가 앱을 설치하지 않고도 앱의 특정 기능을 즉시 사용해 보도록 할 수 있습니다.

게임의 처음 몇 레벨을 용량이 작은 기능 모듈에 포함한 게임을 생각해 보세요. 이 모듈을 인스턴트로 지원하도록 설정함으로써 사용자는 URL 링크나 '사용해 보기' 버튼을 통해 앱을 설치하지 않고도 게임을 즉시 해볼 수 있습니다. 기능 모듈을 만들고 인스턴트 제공을 설정합니다. 그러면 앱이 Play Core 라이브러리를 사용하여 주문형 모듈을 다운로드하도록 요청할 수 있습니다.

기능 모듈을 사용하여 앱 기능을 모듈화하는 것은 첫 단계에 불과합니다. Google Play 인스턴트를 지원하려면 앱의 기본 모듈 및 해당 인스턴트 지원 기능의 다운로드 크기가 엄격한 크기 제한을 충족해야 합니다. 자세한 내용은 앱 또는 게임 크기를 줄여 인스턴트 환경 사용 설정을 참고하세요.

앱 모듈화하기

앱 모듈화는 앱 프로젝트의 논리적 구성요소를 분리형 모듈로 구분하는 프로세스입니다.

앱 기능을 이러한 분리형 구성요소로 재구성하려면 신중하게 고려해야 하며 일정한 시간이 소요됩니다. 하지만 모듈화할 경우 프로젝트에 다음과 같은 이점이 있습니다.

  • 동시 개발: 앱의 논리적 구성요소를 모듈로 분리함으로써 조직의 다양한 팀 또는 개인이 각 모듈의 소유권을 갖고 작업하여 병합 충돌 또는 다른 팀과의 충돌을 줄일 수 있습니다. 또한 앱의 다양한 부분에 사용되는 논리가 있다면 라이브러리 모듈을 사용하여 코드를 재사용하고 캡슐화할 수 있습니다.
  • 빌드 시간 개선: Gradle을 사용한 Android 스튜디오 빌드 시스템과 같은 빌드 시스템은 모듈로 조직된 프로젝트에 최적화되어 있습니다. 예를 들어 다중 코어 프로세서가 포함된 워크스테이션에서 Gradle의 병렬 프로젝트 실행 최적화를 사용 설정하면 빌드 시스템에서 여러 모듈을 동시에 빌드하여 빌드 시간을 크게 줄일 수 있습니다. 모듈화 작업을 많이 진행한 프로젝트일수록 빌드 성능은 더 크게 개선됩니다.
  • 기능 제공 맞춤설정: 앱의 기능을 기능 모듈로 모듈화하는 작업은 주문형, 조건부 및 인스턴트 제공과 같은 Play Feature Delivery의 맞춤 제공 옵션 활용 시 필요합니다. 주문형 기능을 생성하려면 추가 작업이 필요하고 앱을 리팩터링해야 할 수도 있습니다. 따라서 기능 모듈로 모듈화함으로써 가장 많은 이점을 얻을 수 있는 앱 기능 및 맞춤 제공 옵션을 통해 얻을 수 있는 이점이 가장 큰 기능이 무엇인지 신중하게 고려해야 합니다.

앱 기능별로 프로젝트를 모듈화하는 작업을 완료하려면 시간이 필요하며 여러 사항을 고려해야 합니다. 앱 모듈화를 시작하기로 결정했다면 가장 먼저 모듈화 기능을 지원하는 데 필요한 속성이 포함된 기본 모듈을 설정해야 합니다. 그런 다음, 설치 시 제공되는 기능 모듈을 설정하여 앱의 현재 동작을 변경하지 않고 앱 기능을 점진적으로 모듈화하면 됩니다.

기능 모듈 매니페스트

Android 스튜디오를 사용하여 새로운 기능 모듈을 만들 때 IDE에는 모듈이 기능 모듈처럼 작동하는 데 필요한 대부분의 매니페스트 속성이 포함됩니다. 또한 일부 속성은 컴파일 시 빌드 시스템에 의해 삽입되므로 직접 지정하거나 수정하지 않아도 됩니다. 다음 표에서는 기능 모듈에 중요한 매니페스트 속성을 설명합니다.

속성 설명
<manifest
...
일반적인 <manifest> 블록입니다.
xmlns:dist="http://schemas.android.com/apk/distribution" 새로운 dist: XML 네임스페이스를 지정하며 아래에서 자세히 설명합니다.
split="split_name" Android 스튜디오에서 App Bundle을 빌드할 때 이 속성을 포함합니다. 따라서 이 속성을 직접 포함하거나 수정하면 안 됩니다.

Play Core 라이브러리를 사용하여 주문형 모듈을 요청할 때 앱이 지정하는 모듈 이름을 정의합니다.

Gradle에서 이 속성의 값을 결정하는 방법

기본적으로 Android 스튜디오를 사용하여 기능 모듈을 만들 때 IDE는 모듈 이름으로 지정한 항목을 사용하여 Gradle 설정 파일에서 모듈을 Gradle 하위 프로젝트로 식별합니다.

App Bundle을 빌드할 때 Gradle은 하위 프로젝트 경로의 마지막 요소를 사용하여 모듈의 매니페스트에 이 매니페스트 속성을 삽입합니다. 예를 들어 MyAppProject/features/ 디렉터리에 새로운 기능 모듈을 생성하고 모듈 이름을 'dynamic_feature1'이라고 지정했다면 IDE는 settings.gradle 파일에 ':features:dynamic_feature1'을 하위 프로젝트로 추가합니다. App Bundle을 빌드할 때 Gradle은 모듈의 매니페스트에 <manifest split="dynamic_feature1">을 삽입합니다.

android:isFeatureSplit="true | false"> Android 스튜디오에서 App Bundle을 빌드할 때 이 속성을 포함시킵니다. 따라서 이 속성을 직접 포함하거나 수정하면 안 됩니다.

이 모듈이 기능 모듈임을 지정합니다. 기본 모듈 및 구성 APK의 매니페스트는 이 속성을 생략하거나 false로 설정합니다.

<dist:module 이 새로운 XML 요소는 모듈이 패키징되는 방식 및 APK로 배포되는 방식을 결정하는 속성을 정의합니다.
dist:instant="true | false" 모듈이 Google Play 인스턴트를 통해 인스턴트 환경으로 사용 가능한지 여부를 지정합니다.

앱에 하나 이상의 인스턴트 지원 기능 모듈이 포함되어 있다면 기본 모듈도 인스턴트를 지원하도록 설정해야 합니다. Android 스튜디오 3.5 이상을 사용 중이라면 인스턴트 지원 기능 모듈을 생성할 때 IDE에서 이 작업을 해줍니다.

이 XML 요소를 true로 설정하는 동시에 <dist:on-demand/>도 설정할 수 없습니다. 그러나 여전히 Play Core 라이브러리를 사용하여 인스턴트 환경으로 인스턴트 지원 기능 모듈의 주문형 다운로드를 요청할 수 있습니다. 사용자가 앱을 다운로드하고 설치할 때 기기는 기본적으로 기본 APK와 함께 앱의 인스턴트 지원 기능 모듈을 다운로드하여 설치합니다.

dist:title="@string/feature_name" 사용자에게 표시될 모듈 제목을 지정합니다. 예를 들어 기기에서 다운로드 확인을 요청할 때 이 제목을 표시합니다.

기본 모듈의 module_root/src/source_set/res/values/strings.xml 파일에 이 제목의 문자열 리소스를 포함해야 합니다.

<dist:fusing dist:include="true | false" />
</dist:module>
Android 4.4(API 수준 20) 이하를 실행 중인 기기를 타겟팅하는 멀티 APK에 모듈을 포함할지 여부를 지정합니다.

또한 bundletool을 사용하여 App Bundle에서 APK를 생성할 때 이 속성을 true로 설정하는 기능 모듈만 범용 APK에 포함됩니다. 범용 APK란 앱이 지원하는 모든 기기 설정에 관한 코드와 리소스가 포함된 모놀리식 APK입니다.

<dist:delivery> 아래와 같이 모듈 제공을 맞춤설정하는 옵션을 캡슐화합니다. 각 기능 모듈은 이러한 맞춤 제공 옵션 유형 한 가지만 설정해야 합니다.
<dist:install-time> 모듈이 설치 시에 사용 가능해야 함을 지정합니다. 이는 다른 맞춤 제공 옵션 유형을 지정하지 않는 기능 모듈의 기본 동작입니다.

설치 시 다운로드에 관한 자세한 내용은 설치 시 제공 구성을 참고하세요.

또한 이 노드는 기기 기능, 사용자 국가, 최소 API 수준과 같은 특정 요구사항에 부합하는 기기로 모듈을 제한하는 조건을 지정할 수도 있습니다. 자세한 내용은 조건부 전송 구성을 참조하세요.

<dist:removable value="true | false" />

설정을 해제하거나 false로 설정하면 bundletool이 번들에서 분할 APK를 생성할 때 기본 모듈에 설치 시간 모듈을 통합합니다. 통합으로 인해 분할 APK 수가 줄어들기 때문에 이 설정으로 앱 성능이 향상될 수 있습니다.

removabletrue로 설정된 경우: 설치 시간 모듈이 기본 모듈에 통합되지 않습니다. 나중에 모듈을 제거하려면 true로 설정합니다. 그러나 삭제될 수 있는 모듈을 너무 많이 구성하면 앱의 설치 시간이 늘어날 수 있습니다.

기본값은 false입니다. 기능 모듈에 융합을 사용 중지하려는 경우에만 매니페스트에서 이 값을 설정해야 합니다.

참고: Android Gradle 플러그인 4.2를 사용하거나 명령줄에서 bundletool v1.0을 사용하는 경우에만 이 기능을 사용할 수 있습니다.

</dist:install-time>  
<dist:on-demand/> 모듈이 주문형 다운로드로 제공되어야 함을 지정합니다. 즉, 설치 시에는 모듈을 사용할 수 없지만 앱에서 나중에 다운로드하도록 요청할 수 있습니다.

주문형 다운로드에 관한 자세한 내용은 주문형 제공 구성을 참고하세요.

</dist:delivery>
<application
android:hasCode="true | false">
...
</application>
기능 모듈이 DEX 파일을 생성하지 않는다면, 즉 나중에 DEX 파일 형식으로 컴파일되는 코드가 기능 모듈에 포함되어 있지 않다면 다음을 실행해야 합니다. 그러지 않으면 런타임 오류가 발생할 수 있습니다.
  1. 기능 모듈의 매니페스트에서 android:hasCode"false"로 설정합니다.
  2. 기본 모듈의 매니페스트에 다음을 추가합니다.
    
    <application
      android:hasCode="true"
      tools:replace="android:hasCode">
      ...
    </application>
    

Play Feature Delivery 테스트

Play Feature Delivery를 테스트하는 가장 좋은 방법은 Google Play 스토어를 통해 테스트하는 것입니다. Play Feature Delivery의 많은 이점에는 최적화된 APK 생성 연기, 서명, Play 스토어에 제공 등이 필요하기 때문입니다. 따라서 단순히 App Bundle을 업로드하든지 고급 제공 옵션을 설정하든지 상관없이 다음 방법을 사용하여 앱을 테스트해야 합니다.

  • URL로 앱 공유. 이 형태가 App Bundle을 업로드하고 앱을 신뢰할 수 있는 테스터와 Google Play 스토어 링크 형태로 공유할 수 있는 가장 빠른 방법입니다. 또한 주문형 기능 다운로드와 같은 맞춤 전송 옵션을 테스트할 수 있는 가장 빠른 방법이기도 합니다.
  • 공개, 비공개 또는 내부 테스트를 설정. 이 방법은 구조화된 테스트 채널을 제공하며 외부 사용자에게 앱을 출시하기 전에 최종 출시 버전을 테스트할 수 있는 좋은 방법입니다.

리소스의 URI 빌드

URI를 사용하여 기능 모듈에 저장된 리소스에 액세스하려면 다음과 같이 Uri.Builder()를 사용하여 기능 모듈 리소스 URI를 생성하는 방법을 사용하세요.

Kotlin

val uri = Uri.Builder()
                .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
                .authority(context.getPackageName()) // Look up the resources in the application with its splits loaded
                .appendPath(resources.getResourceTypeName(resId))
                .appendPath(String.format("%s:%s",
                  resources.getResourcePackageName(resId), // Look up the dynamic resource in the split namespace.
                  resources.getResourceEntryName(resId)
                  ))
                .build()

자바

String uri = Uri.Builder()
                .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
                .authority(context.getPackageName()) // Look up the resources in the application with its splits loaded
                .appendPath(resources.getResourceTypeName(resId))
                .appendPath(String.format("%s:%s",
                  resources.getResourcePackageName(resId), // Look up the dynamic resource in the split namespace.
                  resources.getResourceEntryName(resId)
                  ))
                .build().toString();

리소스 경로의 각 부분은 런타임 시 구성되며 분할 APK가 로드된 후 올바른 네임스페이스가 생성되었는지 확인합니다.

URI가 생성되는 방식의 예로 다음과 같은 이름의 앱 및 기능 모듈이 있다고 가정해 보겠습니다.

  • 앱 패키지 이름: com.example.my_app_package
  • 기능의 리소스 패키지 이름: com.example.my_app_package.my_dynamic_feature

위 코드 스니펫의 resId가 기능 모듈의 'my_video'라는 원시 파일 리소스를 참조한다면 위의 Uri.Builder() 코드는 다음을 출력합니다.

android.resource://com.example.my_app_package/raw/com.example.my_app_package.my_dynamic_feature:my_video

그러면 앱에서 이 URI를 사용하여 기능 모듈의 리소스에 액세스할 수 있습니다.

URI의 경로를 검증하기 위해 다음과 같이 APK Analyzer를 사용하여 기능 모듈 APK를 검사하고 패키지 이름을 확인할 수 있습니다.

컴파일된 리소스 파일의 콘텐츠를 검사하는 APK Analyzer의 스크린샷

그림 2. APK Analyzer를 사용하여 컴파일된 리소스 파일의 패키지 이름을 검사합니다.

기능 모듈 고려사항

기능 모듈이 포함된 앱을 프로덕션 트랙에 게시하려면 고려사항에 유의하세요.

  • 50개 이상의 기능 모듈을 단일 기기에 설치하면 성능 문제가 발생할 수 있습니다. 이를 방지하려면 Play Core 라이브러리를 사용하여 사용자에게 더 이상 필요하지 않은 모듈을 제거하세요.
  • 설치 시 제공을 위해 삭제 가능으로 구성하는 모듈 수를 10개 이하로 제한하세요. 제한하지 않으면 앱의 다운로드 및 설치 시간이 늘어날 수 있습니다.
  • Android 5.0(API 수준 21) 이상을 실행하는 기기에서만 주문형 기능 다운로드 및 설치를 지원합니다. 이전 버전의 Android에서 기능을 사용할 수 있도록 하려면 기능 모듈을 만들 때 융합을 사용 설정해야 합니다.
  • SplitCompat을 사용 설정하여 앱이 다운로드된 기능 모듈에 액세스할 수 있도록 합니다.
  • 기능의 다운로드 크기가 큰 경우 기기에 기능 모듈을 다운로드하려면 먼저 앱에서 사용자의 확인을 받아야 합니다.
  • 기능 모듈은 android:exportedtrue로 설정된 매니페스트에서 활동을 지정하면 안 됩니다. 다른 앱이 활동을 실행하려고 할 때 기기가 기능 모듈을 다운로드했다는 보장이 없기 때문입니다. 또한 앱은 코드 및 리소스에 액세스하기 전에 기능이 다운로드되었는지 확인해야 합니다. 자세한 내용은 설치된 모듈 관리를 참고하세요.
  • Play Feature Delivery를 사용하려면 App Bundle을 사용하여 앱을 게시해야 하므로 App Bundle의 알려진 문제에 관해 알고 있어야 합니다.

참고 자료

Play Feature Delivery 지원 사용에 관해 자세히 알아보려면 다음 리소스를 참고하세요.

샘플

  • PlayCore API 샘플: PlayCore API를 사용하여 기능 모듈을 요청하고 다운로드하는 방법을 보여줍니다.
  • 동적 코드 로드 샘플: 설치된 기능 모듈에서 안전하게 코드에 액세스하는 세 가지 접근 방식을 보여줍니다.

Codelab

  • 첫 번째 Android App Bundle: Android App Bundle의 기본 원리를 살펴보고 Android 스튜디오를 사용하여 자신만의 고유한 App Bundle 구성을 빠르게 시작하는 방법을 보여주는 Codelab입니다. 이 Codelab에서는 bundletool을 사용해 App Bundle을 테스트하는 방법도 알아봅니다.
  • 주문형 모듈: 주문형 기능 모듈을 다운로드하여 설치하는 앱을 만드는 데 도움을 줍니다.

블로그 게시물

동영상