라이브러리 작성자를 위한 최적화

라이브러리 작성자는 앱 개발자가 고품질 최종 사용자 환경을 유지하면서 라이브러리를 앱에 쉽게 통합할 수 있도록 해야 합니다. 라이브러리가 추가 설정 없이 Android 최적화와 호환되는지 확인하거나 라이브러리가 Android에서 사용하기에 적합하지 않을 수 있음을 문서화해야 합니다.

이 문서는 게시된 라이브러리의 개발자를 대상으로 하지만 대규모 모듈식 앱의 내부 라이브러리 모듈 개발자에게도 유용할 수 있습니다.

앱 개발자이고 Android 앱 최적화에 관해 알아보려면 앱 최적화 사용 설정을 참고하세요. 사용하기 적합한 라이브러리에 관해 알아보려면 라이브러리 현명하게 선택하기를 참고하세요.

리플렉션 대신 codegen 사용

가능하면 리플렉션 대신 코드 생성 (codegen)을 사용하세요. 코드 생성과 리플렉션은 모두 프로그래밍할 때 상용구 코드를 피하는 일반적인 접근 방식이지만 코드 생성은 R8과 같은 앱 최적화 도구와 더 호환됩니다.

  • codegen을 사용하면 빌드 프로세스 중에 코드가 분석되고 수정됩니다. 컴파일 시간 이후에는 큰 수정이 없으므로 최적화 도구는 궁극적으로 필요한 코드와 안전하게 삭제할 수 있는 코드를 알 수 있습니다.
  • 리플렉션을 사용하면 코드가 런타임에 분석되고 조작됩니다. 코드는 실행될 때까지 실제로 완성되지 않으므로 최적화 도구는 안전하게 삭제할 수 있는 코드를 알 수 없습니다. 런타임 중에 리플렉션을 통해 동적으로 사용되는 코드가 삭제되어 사용자에게 앱 비정상 종료가 발생할 수 있습니다.

많은 최신 라이브러리는 리플렉션 대신 codegen을 사용합니다. Room, Dagger2 등에서 사용하는 공통 진입점은 KSP를 참고하세요.

반성이 허용되는 경우

반사를 사용해야 하는 경우 다음 중 하나에만 반사해야 합니다.

  • 특정 타겟팅 유형 (특정 인터페이스 구현자 또는 서브클래스)
  • 특정 런타임 주석을 사용하는 코드

이러한 방식으로 리플렉션을 사용하면 런타임 비용이 제한되고 타겟팅된 소비자 유지 규칙을 작성할 수 있습니다.

이러한 구체적이고 타겟팅된 리플렉션 형식은 Android 프레임워크 (예: 활동, 뷰, 드로어블 확장)와 AndroidX 라이브러리 (예: WorkManager ListenableWorkers 또는 RoomDatabases 구성)에서 모두 볼 수 있는 패턴입니다. 반면 Gson은 Android 앱에서 사용하기에 적합하지 않습니다의 개방형 반사는 적절하지 않습니다.

소비자 유지 규칙 작성

라이브러리는 앱 유지 규칙과 동일한 형식을 사용하는 '소비자' 유지 규칙을 패키징해야 합니다. 이러한 규칙은 라이브러리 아티팩트 (AAR 또는 JAR)에 번들로 묶이며 라이브러리가 사용될 때 Android 앱 최적화 중에 자동으로 사용됩니다.

AAR 라이브러리

AAR 라이브러리의 소비자 규칙을 추가하려면 Android 라이브러리 모듈의 빌드 스크립트에서 consumerProguardFiles 옵션을 사용합니다. 자세한 내용은 라이브러리 모듈 만들기 가이드를 참고하세요.

Kotlin

android {
    defaultConfig {
        consumerProguardFiles("consumer-proguard-rules.pro")
    }
    ...
}

Groovy

android {
    defaultConfig {
        consumerProguardFiles 'consumer-proguard-rules.pro'
    }
    ...
}

JAR 라이브러리

JAR로 제공되는 Kotlin/Java 라이브러리와 규칙을 번들로 묶으려면 규칙 파일을 최종 JAR의 META-INF/proguard/ 디렉터리에 이름과 함께 배치합니다. 예를 들어 코드가 <libraryroot>/src/main/kotlin에 있는 경우 소비자 규칙 파일을 <libraryroot>/src/main/resources/META-INF/proguard/consumer-proguard-rules.pro에 배치하면 규칙이 출력 JAR의 올바른 위치에 번들로 묶입니다.

규칙이 META-INF/proguard 디렉터리에 있는지 확인하여 최종 JAR이 규칙을 올바르게 번들로 묶었는지 확인합니다.

다양한 축소 도구 지원 (고급)

특정 압축 도구 버전뿐만 아니라 대상별 압축 도구 (R8 또는 ProGuard)에 맞게 규칙을 조정할 수 있습니다. 이렇게 하면 라이브러리가 새 압축기 버전을 사용하는 프로젝트에서 최적으로 작동하는 동시에 이전 압축기 버전이 있는 프로젝트에서 기존 규칙을 계속 사용할 수 있습니다.

타겟팅된 축소 규칙을 지정하려면 아래에 설명된 대로 AAR 또는 JAR 라이브러리 내 특정 위치에 이를 포함해야 합니다.

In an AAR library:
    consumer-proguard-rules.pro (legacy location)
    classes.jar
    └── META-INF
        └── com.android.tools (targeted shrink rules location)
            ├── r8-from-<X>-upto-<Y>/<R8-rules-file>
            └── proguard-from-<X>-upto-<Y>/<ProGuard-rules-file>

In a JAR library:
    META-INF
    ├── proguard/<ProGuard-rules-file> (legacy location)
    └── com.android.tools (targeted shrink rules location)
        ├── r8-from-<X>-upto-<Y>/<R8-rules-file>
        └── proguard-from-<X>-upto-<Y>/<ProGuard-rules-file>

즉, 타겟팅된 축소 규칙은 JAR의 META-INF/com.android.tools 디렉터리 또는 AAR의 classes.jarMETA-INF/com.android.tools 디렉터리에 저장됩니다.

이 디렉터리 아래에는 r8-from-<X>-upto-<Y> 또는 proguard-from-<X>-upto-<Y> 형식의 이름을 가진 여러 디렉터리가 있을 수 있으며, 이는 디렉터리 내의 규칙이 어떤 버전의 어떤 압축 도구용으로 작성되었는지 나타냅니다. -from-<X> 및 -upto-<Y> 부분은 선택사항이며, <Y> 버전은 배타적이며, 버전 범위는 연속적이어야 합니다.

예를 들어 r8-upto-8.0.0, r8-from-8.0.0-upto-8.2.0r8-from-8.2.0는 유효한 타겟팅 축소 규칙 집합을 형성합니다. r8-from-8.0.0-upto-8.2.0 디렉터리의 규칙은 버전 8.0.0부터 버전 8.2.0(제외)까지 R8에서 사용됩니다.

Android Gradle 플러그인은 이 정보를 바탕으로 일치하는 R8 디렉터리에서 규칙을 선택합니다. 라이브러리가 타겟팅된 축소 규칙을 지정하지 않으면 Android Gradle 플러그인이 기존 위치(AAR의 경우 proguard.txt, JAR의 경우 META-INF/proguard/<ProGuard-rules-file>)에서 규칙을 선택합니다.