앱 최적화를 사용 설정하면 isShrinkResources = true
설정은 최적화 도구에 사용되지 않는 리소스를 삭제하도록 지시하여 앱 크기를 줄이는 데 도움이 됩니다. 리소스 축소는 코드 축소와 함께 사용할 때만 작동하므로 리소스를 최적화하는 경우 isMinifyEnabled = true
도 설정합니다. 예를 들면 다음과 같습니다.
buildTypes {
release {
isMinifyEnabled = true
isShrinkResources = true
...
}
}
특정 리소스를 유지하거나 삭제하려면 프로젝트 리소스(예: res/raw/my.package.keep.xml
)에 XML keep 파일을 만듭니다. keep 파일에는 다음과 같은 구성요소가 있습니다.
<resources>
태그: 모든 하위 리소스 요소와 keep/discard 속성을 포함합니다.tools:keep
속성: 유지할 리소스를 식별하는 리소스 이름의 쉼표로 구분된 목록을 허용합니다.tools:discard
속성: 삭제할 리소스를 식별하는 리소스 이름의 쉼표로 구분된 목록을 허용합니다.
별표 문자를 와일드 카드로 사용하여 동일한 폴더의 여러 리소스를 참조합니다. 예를 들면 다음과 같습니다.
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"
tools:discard="@layout/unused2" />
리소스를 삭제할 수 있는데도 불구하고 삭제할 리소스를 지정하는 것이 불필요해 보일 수 있지만 빌드 변형을 사용할 때는 리소스를 삭제하는 것이 유용할 수 있습니다.
특정 빌드 변형 타겟팅
일부 빌드 변형에서만 리소스를 삭제하려면 모든 리소스를 공통 프로젝트 디렉터리에 배치한 다음 변형의 리소스 디렉터리에서 각 빌드 변형에 대해 다른 my.package.build.variant.keep.xml
파일을 만듭니다. keep 파일에서 특정 리소스가 코드에서 사용되는 것처럼 보이지만 (따라서 축소기에서 삭제되지 않음) 실제로는 특정 빌드 변형에 사용되지 않을 때 삭제할 리소스를 수동으로 지정합니다.
사용하지 않는 대체 리소스 삭제
최적화 도구는 앱 코드에서 참조하지 않는 리소스만 삭제합니다. 즉, 최적화 도구는 다양한 기기 구성의 대체 리소스를 삭제하지 않습니다.
앱의 모듈 build.gradle
파일에서 Android Gradle resConfigs
속성을 사용하여 앱에 필요하지 않은 대체 리소스 파일을 삭제합니다.
예를 들어 언어 리소스가 포함된 라이브러리 (예: Google Play 서비스)를 사용 중인 경우, 앱은 앱의 나머지 부분이 동일 언어로 번역되었는지와 상관없이 라이브러리의 메시지를 위해 번역된 모든 언어 문자열을 포함합니다. 앱에서 공식적으로 지원하는 언어만 유지하려면 resConfigs
속성을 사용하여 언어를 지정합니다.
지정되지 않은 언어의 모든 리소스는 제거됩니다.
다음 스니펫은 언어 리소스를 영어와 프랑스어로 제한하는 방법을 보여줍니다.
android {
defaultConfig {
...
resourceConfigurations.addAll(listOf("en", "fr"))
}
}
또는
android {
defaultConfig {
...
resConfigs "en", "fr"
}
}
Android App Bundle (AAB) 형식을 사용하여 앱을 게시하면 기본적으로 사용자가 앱을 설치할 때 사용자 기기에 구성된 언어만 다운로드됩니다. 마찬가지로 기기의 화면 밀도와 일치하는 리소스와 기기의 ABI와 일치하는 네이티브 라이브러리만 다운로드에 포함됩니다. 자세한 내용은 구성 APK 유형을 다시 사용 또는 사용 중지를 참고하세요.
APK로 출시되는 기존 앱 (2021년 8월 이전에 생성됨)의 경우 서로 다른 기기 구성을 타겟팅하는 여러 APK를 빌드하여 APK에 포함할 화면 밀도 또는 ABI 리소스를 맞춤설정할 수 있습니다.
리소스 병합 시 충돌 방지
기본적으로 Android Gradle 플러그인(AGP)은 이름이 동일한 리소스를 병합합니다(예: 동일한 이름의 드로어블이 다른 리소스 폴더에 있는 경우).
이 동작은 shrinkResources
속성에 의해 제어되지 않으며 사용 중지할 수 없습니다. 코드가 참조하는 이름이 여러 리소스에 있는 경우 오류를 방지하는 데 이 동작이 필요하기 때문입니다.
리소스 병합은 둘 이상의 파일이 동일한 리소스 이름, 유형 및 한정자를 공유하는 경우에만 발생합니다. AGP는 중복된 파일 중에서 가장 적합하다고 식별된 파일을 아래에 설명된 우선순위에 따라 선택한 후 최종 빌드 아티팩트에 배포하기 위해 하나의 리소스만 AAPT에 전달합니다.
AGP는 다음 위치에서 중복 리소스를 찾습니다.
- 기본 소스 세트와 연관된 기본 리소스. 일반적으로
src/main/res/
에 있습니다. - 빌드 유형 및 빌드 버전에서 파생한 변형 오버레이
- 라이브러리 프로젝트 종속 항목
AGP는 다음과 같은 우선순위 단계에 따라 중복 리소스를 병합합니다.
예를 들어 중복 리소스가 기본 리소스와 빌드 버전 양쪽에 나타나는 경우 Gradle은 빌드 버전에 있는 리소스를 선택합니다.
동일한 소스 세트 안에 동일한 리소스가 있으면 Gradle이 리소스를 병합할 수 없으며 리소스 병합 오류가 발생합니다. 이러한 오류는 모듈 build.gradle
파일의 sourceSet
속성에 여러 개의 소스 세트가 정의되는 경우에 발생할 수 있습니다(예: src/main/res/
및 src/main/res2/
에 동일한 리소스가 포함된 경우).
리소스 축소 문제 해결
리소스를 축소하면 Build 창에 앱에서 삭제된 리소스의 요약이 표시됩니다. Gradle의 자세한 텍스트 출력을 표시하려면 창 왼쪽에서 Toggle view를 클릭합니다. 예를 들면 다음과 같습니다.
:android:shrinkDebugResources
Removed unused resources: Resource data reduced from 2570KB to 1711KB: Removed 33%
:android:validateDebugSigning
Gradle은 또한 이름이 resources.txt
인 진단 파일을 <module-name>/build/outputs/mapping/release/
(ProGuard의 출력 파일과 동일한 폴더)에 생성합니다. 이 파일에는 다른 리소스를 참조하는 리소스 및 사용되거나 삭제되는 리소스에 관한 세부정보가 포함됩니다.
예를 들어 @drawable/ic_plus_anim_016
이 아직도 앱에 남아있는 이유를 알아보려면 resources.txt
파일을 열고 해당 파일 이름을 검색합니다. 다른 리소스에서 참조하는 것을 확인할 수 있습니다.
16:25:48.005 [QUIET] [system.out] @drawable/add_schedule_fab_icon_anim : reachable=true
16:25:48.009 [QUIET] [system.out] @drawable/ic_plus_anim_016
이제 @drawable/add_schedule_fab_icon_anim
이 검색되는 이유를 알아야 합니다. 위쪽으로 검색해 보면 resources.txt
의 연결 가능한 루트 리소스 제목 아래에 나열된 리소스를 찾을 수 있습니다.
즉, add_schedule_fab_icon_anim
에 대한 코드 참조가 있습니다. 즉, 연결 가능 코드에서 R.drawable
ID가 발견되었습니다.
엄격한 검사를 사용하지 않는 한 동적으로 로드된 리소스의 이름을 구성하기 위해 사용될 수 있는 것처럼 보이는 문자열 상수가 있다면 리소스 ID가 연결 가능하다고 표시될 수 있습니다. 이 경우 리소스 이름의 빌드 출력을 검색하면 다음과 같은 메시지가 표시될 수 있습니다.
10:32:50.590 [QUIET] [system.out] Marking drawable:ic_plus_anim_016:2130837506
used because its format-string matches string pool constant ic_plus_anim_%1$d.
이 문자열 중 하나가 표시되고 주어진 리소스를 동적으로 로드하는 데 이 문자열이 사용되고 있지 않다는 확신이 들면 유지 파일에서 tools:discard
속성을 사용하여 빌드 시스템에 리소스를 삭제하라고 알립니다.