기본 설정으로 앱 최적화를 사용 설정하면 R8은 성능 이점을 극대화하기 위해 광범위한 최적화를 실행합니다. R8은 클래스, 필드, 메서드 이름 바꾸기, 이동, 삭제를 비롯하여 코드에 상당한 수정을 가합니다. 이러한 수정으로 인해 오류가 발생하는 경우 유지 규칙에서 선언하여 R8이 수정하지 않아야 하는 코드 부분을 지정해야 합니다.
유지 규칙이 필요한 일반적인 시나리오
R8은 코드에서 모든 직접 호출을 식별하고 보존합니다. 그러나 R8은 간접 코드 사용을 볼 수 없으므로 앱에 필요한 코드를 삭제하여 비정상 종료를 일으킬 수 있습니다. 유지 규칙을 사용하여 R8에 간접적으로 사용되는 코드를 보존하도록 지시합니다. 유지 규칙이 필요할 가능성이 높은 몇 가지 일반적인 상황은 다음과 같습니다.
- 리플렉션으로 액세스되는 코드: R8은 클래스, 필드 또는 메서드가 리플렉션으로 액세스되는 시점을 식별할 수 없습니다. 예를 들어 R8은
Class.getDeclaredMethod()를 사용하여 이름으로 조회된 메서드 또는Class.getAnnotation()으로 가져온 주석을 식별할 수 없습니다. 이러한 경우 R8은 이러한 메서드와 주석의 이름을 바꾸거나 완전히 삭제하여 런타임에ClassNotFoundException또는NoSuchMethodException을 일으킬 수 있습니다. - Java 네이티브 인터페이스 (JNI)에서 호출되는 코드: 네이티브 (C 또는 C++) 코드가 Java 또는 Kotlin 메서드를 호출하거나 Java 또는 Kotlin 코드가 JNI로 C++ 코드를 호출할 때 호출은 메서드 이름의 동적 문자열 조회를 기반으로 합니다. R8은 동적 문자열 기반 메서드 호출을 볼 수 없으므로 최적화로 인해 코드가 손상될 수 있습니다.
이것은 유지 규칙이 필요한 시나리오의 전체 목록은 아니지만 이러한 시나리오에서는 유지 규칙이 필요할 수 있는 대부분의 사례를 다룹니다.
자체 코드에서 리플렉션을 사용하거나 JNI에서 호출되는 경우 유지 규칙을 수동으로 작성하는 대신 Jetpack 유지 주석으로 코드를 주석 처리할 수 있습니다. Gradle 플러그인은 빌드 시 주석에서 유지 규칙을 생성합니다.
앱에 유지 규칙을 추가하는 방법
유지 규칙 구성은 사용하는 AGP 버전에 따라 다릅니다.
대규모 앱에는 일반적으로 여러 라이브러리 모듈에 코드가 있습니다. 이러한 경우 특정 라이브러리 모듈 내에서 적용되는 코드와 함께 유지 규칙을 배치하는 것이 좋습니다. 라이브러리의 유지 규칙을 유지하는 데 있어 중요한 차이점은 라이브러리 모듈의
build.gradle.kts (또는 build.gradle) 파일 내에서 이러한 규칙을 선언하는 방법입니다. 자세한 내용은 라이브러리
작성자를 위한 최적화를 참고하세요.
AGP 버전 9.3 이상
src/<variant>/keepRules 디렉터리의 접미사가 .keep인 파일에 규칙을 추가합니다. 예를 들어 src/main/keepRules/custom-rules.keep입니다. AGP 9.3 이상에 업데이트된 DSL을 사용하면 코드 및 리소스 최적화가 모두 사용 설정되며 기본적으로 포함되어 있으므로 명시적으로 생략하지 않는 한 기본 Android 유지 규칙 파일(proguard-android-optimize.txt)을 명시적으로 정의할 필요가 없습니다.
Kotlin
android {
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
}
}
}
}
Groovy
android {
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
}
}
}
}
기본 Android 플랫폼 유지 규칙 생략 (고급)
AGP는 기본 Android 플랫폼 규칙 집합을 제공합니다. 프로젝트 구성에서 이러한 규칙을 생략하고 모든 유지 규칙을 직접 관리하려면 optimization.keepRules.includeDefault를 false로 설정합니다.
Kotlin
android {
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
keepRules {
includeDefault = false // The file with optimization
// rules for the Android platform is included by
// default. To omit this file, set this option to false.
}
}
}
}
}
Groovy
android {
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
keepRules {
includeDefault = false // The file with optimization
// rules for the Android platform is included by
// default. To omit this file, set this option to false.
}
}
}
}
}
AGP 버전 9.3 미만의 기존 DSL
앱 모듈의 루트 디렉터리에 있는 proguard-rules.pro 파일에 규칙을 추가합니다. 파일이 이미 있을 수 있지만 없는 경우 만듭니다. 파일의 규칙을 적용하려면 모듈 수준
build.gradle.kts (또는 build.gradle) 파일에서 파일을 선언해야 합니다.
기본적으로 빌드 파일에는 proguard-android-optimize.txt 파일도 포함됩니다. 이 파일에는 대부분의 Android 프로젝트에 필요한 규칙이 포함되어 있으므로 빌드 파일에 그대로 두어야 합니다. 이 파일은 proguard-common.txt 파일을 기반으로 하며 콘텐츠를 공유합니다.
기존 DSL (Kotlin)
android {
buildTypes {
release {
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
// Default file with default optimization rules.
getDefaultProguardFile("proguard-android-optimize.txt"),
...
)
}
}
}
기존 DSL (Groovy)
android {
buildTypes {
release {
minifyEnabled = true
shrinkResources = true
// Default file with default optimization rules.
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
...
}
}
}
유지 규칙 추가
유지 규칙을 추가할 때는 전역 옵션을 포함하고 자체 유지 규칙을 정의할 수 있습니다.
전역 옵션: 전역 옵션은 전체 코드베이스에서 R8 이 작동하는 방식에 영향을 미치는 일반적인 지시어입니다. 자세한 내용은 전역 옵션을 참고하세요.
유지 규칙: 유지 규칙은 앱을 실수로 손상시키지 않고 코드 최적화를 극대화하는 적절한 균형을 맞추기 위해 신중하게 설계해야 합니다. 유지 규칙을 작성하는 방법은 유지 규칙 추가를 참고하세요.
라이브러리 작성자를 위한 유지 규칙
유지 규칙의 전역 옵션과 구문을 알아본 후 자세한 내용은 라이브러리 작성자를 위한 최적화를 참고하세요.