최신 Android 개발에서 작고 빠르며 안전한 애플리케이션을 제공하는 것은 기본적인 사용자 기대치입니다. 이를 달성하기 위한 Android 빌드 시스템의 기본 도구는 R8 최적화 도구입니다. 이 도구는 축소, 코드 이름 바꾸기 또는 압축, 앱 최적화를 위해 불필요한 코드 및 리소스 삭제를 처리하는 컴파일러입니다.
R8을 사용 설정하는 것은 앱 출시를 준비하는 데 중요한 단계이지만, 개발자가 '유지 규칙' 형식으로 안내를 제공해야 합니다.
이 도움말을 읽은 후 YouTube에서 R8 최적화 도구를 사용 설정, 디버깅, 문제 해결하는 방법에 관한 Performance Spotlight Week 동영상을 확인하세요.
Keep 규칙이 필요한 이유
Keep 규칙을 작성해야 하는 이유는 핵심적인 충돌에서 비롯됩니다. R8은 정적 분석 도구이지만 Android 앱은 JNI (Java Native Interface)를 사용하여 네이티브 코드 안팎에서 리플렉션이나 호출과 같은 동적 실행 패턴에 의존하는 경우가 많습니다.
R8은 직접 호출을 분석하여 사용된 코드의 그래프를 빌드합니다. 코드에 동적으로 액세스하면 R8의 정적 분석에서 이를 예측할 수 없으며 해당 코드를 사용되지 않음으로 식별하고 삭제하여 런타임 비정상 종료가 발생합니다.
유지 규칙은 R8 컴파일러에 대한 명시적인 지침으로, '이 특정 클래스, 메서드 또는 필드는 런타임에 동적으로 액세스되는 진입점입니다. 직접적인 참조를 찾을 수 없더라도 유지해야 합니다."
Keep 규칙에 관한 자세한 내용은 공식 가이드를 참고하세요.
보관 규칙 작성 위치
애플리케이션의 맞춤 유지 규칙은 텍스트 파일로 작성됩니다. 일반적으로 이 파일의 이름은 proguard-rules.pro이며 앱 또는 라이브러리 모듈의 루트에 있습니다. 이 파일은 모듈의 build.gradle.kts 파일의 release 빌드 유형에 지정됩니다.
release {
isShrinkResources = true
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro",
)
}올바른 기본 파일 사용
getDefaultProguardFile 메서드는 Android SDK에서 제공하는 기본 규칙 집합을 가져옵니다. 잘못된 파일을 사용하면 앱이 최적화되지 않을 수 있습니다. proguard-android-optimize.txt를 사용해야 합니다. 이 파일은 표준 Android 구성요소의 기본 유지 규칙을 제공하고 R8의 코드 최적화를 사용 설정합니다. 오래된 proguard-android.txt는 유지 규칙만 제공하며 R8의 최적화를 사용 설정하지 않습니다.
이는 심각한 성능 문제이므로 Android 스튜디오 Narwhal 3 기능 출시부터 잘못된 파일을 사용하는 개발자에게 경고를 표시하기 시작했습니다. 또한 Android Gradle 플러그인 버전 9.0부터는 오래된 proguard-android.txt 파일이 더 이상 지원되지 않습니다. 따라서 최적화된 버전으로 업그레이드해야 합니다.
보관 규칙 작성 방법
유지 규칙은 세 가지 주요 부분으로 구성됩니다.
- 옵션 (예:
-keep또는-keepclassmembers) - 선택적 수정자(예:
allowshrinking) - 일치시킬 코드를 정의하는 클래스 사양
전체 문법과 예시는 보관 규칙 추가 가이드를 참고하세요.
Keep 규칙 안티패턴
권장사항뿐만 아니라 안티패턴에 대해서도 알아두는 것이 중요합니다. 이러한 안티패턴은 오해나 문제 해결을 위한 지름길에서 비롯되는 경우가 많으며 프로덕션 빌드의 성능에 치명적일 수 있습니다.
전체 옵션
이러한 플래그는 출시 빌드에서 절대 사용해서는 안 되는 전역 전환입니다. 문제를 격리하기 위한 임시 디버깅용으로만 사용됩니다.
-dontotptimize를 사용하면 R8의 성능 최적화가 효과적으로 사용 중지되어 앱이 느려집니다.
-dontobfuscate를 사용하면 모든 이름 바꾸기가 사용 중지되고 -dontshrink를 사용하면 데드 코드 삭제가 사용 중지됩니다. 이러한 전역 규칙은 모두 앱 크기를 늘립니다.
더 나은 앱 사용자 환경을 위해 프로덕션 환경에서는 이러한 전역 플래그를 사용하지 않는 것이 좋습니다.
지나치게 광범위한 보관 규칙
R8의 이점을 무효화하는 가장 쉬운 방법은 지나치게 광범위한 유지 규칙을 작성하는 것입니다. 아래와 같은 유지 규칙은 이 패키지의 모든 클래스 또는 모든 하위 패키지를 축소, 난독화, 최적화하지 않도록 R8 최적화 도구에 지시합니다. 이렇게 하면 전체 패키지에 대한 R8의 이점이 완전히 사라집니다. 대신 좁고 구체적인 유지 규칙을 작성해 보세요.
-keep class com.example.package.** { *;} // WIDE KEEP RULES CAUSE PROBLEMS반전 연산자 (!)
반전 연산자 (!)는 규칙에서 패키지를 제외하는 강력한 방법인 것 같습니다. 하지만 그렇게 간단하지는 않습니다. 예를 들어보겠습니다
-keep class !com.example.my_package.** { *; } // USE WITH CAUTION이 규칙은 'com.example.package에 클래스를 유지하지 않음'을 의미한다고 생각할 수 있습니다. 하지만 실제로는 'com.example.package에 없는 전체 애플리케이션의 모든 클래스, 메서드, 속성을 유지'한다는 의미입니다. 이 사실이 놀랍다면 R8 구성에 부정문이 있는지 확인하는 것이 좋습니다.
Android 구성요소의 중복 규칙
또 다른 일반적인 실수는 앱의 Activities, Services 또는 BroadcastReceivers에 유지 규칙을 수동으로 추가하는 것입니다. 이는 불필요합니다. 기본 proguard-android-optimize.txt 파일에는 이러한 표준 Android 구성요소가 즉시 작동하는 데 필요한 관련 규칙이 이미 포함되어 있습니다.
또한 많은 라이브러리에서 자체 유지 규칙을 제공합니다. 따라서 이러한 항목에 대한 자체 규칙을 작성할 필요가 없습니다. 사용 중인 라이브러리의 Keep 규칙에 문제가 있는 경우 라이브러리 작성자에게 문의하여 문제가 무엇인지 확인하는 것이 좋습니다.
Keep 규칙 권장사항
금지사항을 알아봤으니 이제 권장사항을 살펴보겠습니다.
좁은 범위의 보관 규칙 작성
좋은 보관 규칙은 최대한 좁고 구체적이어야 합니다. 필요한 것만 보존하고 나머지는 모두 R8에서 최적화하도록 허용해야 합니다.
| 규칙 | 품질 |
|---|---|
| 낮음: 전체 패키지와 하위 패키지를 유지합니다. |
| 낮음: 전체 클래스를 유지하지만 여전히 너무 광범위할 수 있음 |
-keepclassmembers class com.example.MyClass {
private java.lang.String secretMessage;
public void onNativeEvent(java.lang.String);
} | 높음: 특정 클래스의 관련 메서드 및 속성만 유지됩니다. |
공통 상위 요소 사용
여러 데이터 모델에 대해 별도의 유지 규칙을 작성하는 대신 공통 기본 클래스 또는 인터페이스를 타겟팅하는 하나의 규칙을 작성합니다. 아래 규칙은 이 인터페이스를 구현하는 클래스의 모든 멤버를 유지하도록 R8에 지시하며 확장성이 뛰어납니다.
# Keep all fields of any class that implements SerializableModel
-keepclassmembers class * implements com.example.models.SerializableModel {
<fields>;
}주석을 사용하여 여러 클래스 타겟팅
커스텀 주석 (예: @Serialize)을 만들고 이를 사용하여 필드를 보존해야 하는 클래스에 '태그'를 지정합니다. 이는 깔끔하고 선언적이며 확장성이 뛰어난 또 다른 패턴입니다. 사용 중인 프레임워크의 기존 주석에 대한 유지 규칙을 만들 수도 있습니다.
# Keep all fields of any class annotated with @Serialize
-keepclassmembers class * {
@com.example.annotations.Serialize <fields>;
}적절한 보관 옵션 선택하기
유지 옵션은 규칙에서 가장 중요한 부분입니다. 잘못 선택하면 최적화가 불필요하게 사용 중지될 수 있습니다.
| Keep 옵션 | 기능 |
-keep | 클래스 및 선언에 언급된 멤버 가 삭제되거나 이름이 변경되지 않도록 합니다. |
-keepclassmembers | 지정된 구성원이 삭제되거나 이름이 변경되지 않도록 하지만, 수업 자체는 삭제할 수 있습니다(단, 다른 방식으로 삭제되지 않은 수업에 한함). |
-keepclasseswithmembers | 조합: 지정된 모든 멤버가 있는 경우에만 클래스와 그 멤버를 유지합니다. |
유지 옵션에 관한 자세한 내용은 유지 옵션 문서를 참고하세요.
수정자로 최적화 허용
allowshrinking 및 allowobfuscation와 같은 수정자는 광범위한 -keep 규칙을 완화하여 최적화 기능을 R8에 다시 부여합니다. 예를 들어 기존 라이브러리에서 전체 클래스에 -keep를 사용하도록 강제하는 경우 축소 및 난독화를 허용하여 일부 최적화를 회수할 수 있습니다.
# Keep this class, but allow R8 to remove it if it's unused and allow R8 to rename it. -keep,allowshrinking,allowobfuscation class com.example.LegacyClass
추가 최적화를 위한 전역 옵션 추가
유지 규칙 외에도 R8 구성 파일에 전역 플래그를 추가하여 최적화를 더욱 촉진할 수 있습니다.
-repackageclasses는 R8에 모든 난독화된 클래스를 단일 패키지로 이동하도록 지시하는 강력한 옵션입니다. 이렇게 하면 중복 패키지 이름 문자열이 삭제되어 DEX 파일의 공간이 크게 절약됩니다.
-allowaccessmodification를 사용하면 R8이 액세스 권한을 확대 (예: private에서 public로)하여 더 적극적인 인라인을 사용 설정할 수 있습니다. 이제 proguard-android-optimize.txt를 사용할 때 기본적으로 사용 설정됩니다.
경고: 라이브러리 작성자는 이러한 전역 최적화 플래그를 소비자 규칙에 추가해서는 절대 안 됩니다. 앱 전체에 강제로 적용되기 때문입니다.
이를 더욱 명확히 하기 위해 Android Gradle 플러그인 버전 9.0부터는 라이브러리의 전역 최적화 플래그를 완전히 무시할 예정입니다.
라이브러리 권장사항
모든 Android 앱은 어떤 방식으로든 라이브러리를 사용합니다. 라이브러리 권장사항에 대해 알아보겠습니다.
라이브러리 개발자
라이브러리에서 리플렉션 또는 JNI를 사용하는 경우 소비자에게 필요한 유지 규칙을 제공해야 합니다. 이러한 규칙은 consumer-rules.pro 파일에 배치되며, 이 파일은 라이브러리의 AAR 파일 내에 자동으로 번들로 묶입니다.
android {
defaultConfig {
consumerProguardFiles("consumer-rules.pro")
}
...
}라이브러리 소비자
문제가 있는 보관 규칙 필터링하기
문제가 있는 유지 규칙이 포함된 라이브러리를 사용해야 하는 경우 AGP 9.0부터 build.gradle.kts 파일에서 이를 필터링할 수 있습니다. 이렇게 하면 R8이 특정 종속 항목에서 오는 규칙을 무시합니다.
release {
optimization.keepRules {
// Ignore all consumer rules from this specific library
it.ignoreFrom("com.somelibrary:somelibrary")
}
}가장 좋은 보관 규칙은 보관 규칙이 없는 것입니다.
궁극적인 R8 구성 전략은 유지 규칙을 작성할 필요가 없도록 하는 것입니다. 많은 앱에서 리플렉션보다 코드 생성을 선호하는 최신 라이브러리를 선택하여 이를 달성할 수 있습니다. 코드 생성을 사용하면 최적화 도구는 런타임에 실제로 사용되는 코드와 삭제할 수 있는 코드를 더 쉽게 결정할 수 있습니다. 또한 동적 리플렉션을 사용하지 않으면 '숨겨진' 진입점이 없으므로 유지 규칙이 필요하지 않습니다. 새 라이브러리를 선택할 때는 항상 리플렉션보다 코드 생성을 사용하는 솔루션을 선호합니다.
라이브러리를 선택하는 방법에 관한 자세한 내용은 현명한 라이브러리 선택을 참고하세요.
R8 구성 디버깅 및 문제 해결
R8이 유지해야 하는 코드를 삭제하거나 APK가 예상보다 큰 경우 이러한 도구를 사용하여 문제를 진단하세요.
중복 및 전역 유지 규칙 찾기
R8은 수십 개의 소스에서 규칙을 병합하므로 '최종' 규칙 집합이 무엇인지 알기 어려울 수 있습니다. proguard-rules.pro 파일에 이 플래그를 추가하면 전체 보고서가 생성됩니다.
# Outputs the final, merged set of rules to the specified file -printconfiguration build/outputs/logs/configuration.txt
이 파일을 검색하여 중복 규칙을 찾거나 문제가 있는 규칙 (예: -dontoptimize)을 포함된 특정 라이브러리로 추적할 수 있습니다.
R8에 질문: 이 콘텐츠를 유지하는 이유는 무엇인가요?
삭제될 것으로 예상한 클래스가 앱에 여전히 있는 경우 R8에서 그 이유를 알려줄 수 있습니다. 다음 규칙을 추가하면 됩니다.
# Asks R8 to explain why it's keeping a specific class class com.example.MyUnusedClass -whyareyoukeeping
빌드 중에 R8은 해당 클래스를 유지하게 한 정확한 참조 체인을 출력하므로 참조를 추적하고 규칙을 조정할 수 있습니다.
전체 가이드는 R8 문제 해결 섹션을 참고하세요.
다음 단계
R8은 Android 앱 성능을 향상하는 강력한 도구입니다. 효과성은 정적 분석 엔진으로서의 작동에 대한 올바른 이해에 달려 있습니다.
특정 구성원 수준 규칙을 작성하고, 상위 항목과 주석을 활용하고, 올바른 보관 옵션을 신중하게 선택하면 필요한 항목을 정확하게 보관할 수 있습니다. 가장 발전된 방식은 리플렉션 기반의 이전 라이브러리 대신 최신 코드 생성 기반 라이브러리를 선택하여 규칙의 필요성을 완전히 없애는 것입니다.
실적 스포트라이트 주간을 따라가면서 YouTube에서 오늘의 스포트라이트 주간 동영상을 확인하고 R8 챌린지를 계속 진행하세요. R8 사용 설정 또는 문제 해결에 관한 질문은 #optimizationEnabled를 사용하세요. 최선을 다해 도와드리겠습니다.
이제 직접 혜택을 확인해 보세요.
지금 바로 앱에 R8 전체 모드를 사용 설정해 보세요.
- 개발자 가이드에 따라 앱 최적화를 사용 설정하세요.
proguard-android.txt를 계속 사용하는지 확인하고proguard-android-optimize.txt로 바꿉니다.- 그런 다음 효과를 측정합니다. 차이를 느끼는 데 그치지 말고 확인하세요. GitHub의 Macrobenchmark 샘플 앱에서 코드를 조정하여 시작 시간을 전후로 측정하여 성능 향상을 측정합니다.
앱 성능이 크게 개선될 것으로 기대합니다.
소셜 태그 #AskAndroid를 사용하여 질문을 남겨주세요. Google 전문가가 일주일 내내 질문을 모니터링하고 답변해 드립니다.
내일은 기준 프로필과 시작 프로필을 사용한 프로필 기반 최적화에 대해 이야기하고, 지난 출시에서 Compose 렌더링 성능이 어떻게 개선되었는지 공유하고, 백그라운드 작업의 성능 고려사항을 공유할 예정이니 기대해 주세요.
-
제품 소식에이전트형 개발이 가속화됨에 따라 Android 엔지니어링은 흥미로운 새로운 영역에 도달하고 있습니다. 즉, 보조 코드 완성에서 개발자의 지시에 따라 엔드 투 엔드로 실행되는 에이전트로 전환되고 있습니다. 사용하는 모델과 에이전트를 완전히 자유롭게 선택하고 유연하게 사용할 수 있습니다.
Jason Buchel • 읽는 데 3분 소요 -
제품 소식오늘 Google은 '단순한 스토어 이상의 가치'라는 비전을 다음 단계로 발전시키는 방법을 공유했습니다. 월간 활성 사용자 수가 2억 5천만 명이 넘는 개인 홈 베이스인 내 페이지 탭부터 7억 개 이상의 게이머 프로필을 연결하는 통합 게임 플랫폼에 이르기까지 Google Play는 사용자가 있는 곳이라면 어디에서나 사용자를 만나고 있습니다.
Paul Feng • 읽는 데 3분 소요 -
제품 소식Google은 Googlebook을 통해 사용자가 자신을 표현하고 이러한 도구를 이용할 수 있도록 지원하게 되어 기쁩니다.
Cyrus Stoller • 읽는 데 2분 소요
Android 개발 관련 최신 정보를 이메일로 받아 보세요.