본문 바로가기
Android

안드로이드 멀티모듈 환경에서 R8/ProGuard 난독화

by oldogz 2025. 7. 9.

 

Google Play Console에 앱 번들을 업로드하면 다음과 같은 경고를 확인할 수 있습니다. 난독화와 관련된 경고로 지난 빌드 과정을 이해하면서 이해했던 코드 축소, 난독화, 최적화와 관련된 내용입니다.

중요: 앱의 출시 빌드에는 항상 최적화를 사용 설정해야 하지만 테스트나 라이브러리에는 사용 설정하지 않는 것이 좋습니다. 테스트와 함께 R8을 사용하는 방법에 관한 자세한 내용은 최적화 테스트 및 문제 해결을 참고하세요. 라이브러리에서 R8을 사용 설정하는 방법에 관한 자세한 내용은 라이브러리 작성자를 위한 최적화를 참고하세요.

 

공식문서의 권장 사항으로 앱의 출시 빌드에는 항상 최적화가 적용되어야 한다고 합니다. 해당 경고는 R8을 사용하여 난독화된 코드를 가독화할 수 있는 mapping.txt 파일을 찾을 수 없을 때 발생합니다.

경고: APK를 출시하는 경우 mapping.txt 파일이 APK와 자동으로 번들로 묶이지 않습니다. Android 스튜디오는 매핑 파일을 /build/outputs/mapping/ 디렉터리에 저장합니다. 매핑 파일은 프로젝트를 빌드할 때마다 덮어쓰므로 새 버전을 게시할 때마다 복사본을 저장해야 합니다.

 

APK 파일을 업로드할 경우 비정상 종료나 ANR을 분석하기 위해 mapping.txt 파일을 직접 업로드해야 합니다. 하지만, 최근 안드로이드는 APK 파일을 업로드할 수 없고, 앱 번들을 업로드해야 합니다. 앱 번들에는 자동으로 mapping.txt 파일이 포함되므로 따로 mapping.txt 파일을 업로드하지 않아도 앱 번들을 업로드하면 함께 난독화된 코드도 Google Play Console에서 오류를 쉽게 디버그 할 수 있습니다.

 

이번 글에서는 안드로이드에서 난독화를 적용하는 과정을 정리하였습니다.

 

R8 / proguard를 사용한 난독화

과거에는 난독화와 최적화를 위해 ProGuard라는 별도의 도구를 사용하였습니다. 자바 바이트코드(.class)는 ProGuard를 거쳐 처리된 후, D8 컴파일러를 통해 .dex파일로 변환되는 단계를 거쳤습니다.

 

현재는 구글이 개발한 차세대 코드 최적화 도구인 R8 컴파일러를 사용하게 됩니다. gradle에서 난독화 옵션을 켜면 D8 컴파일러 대신 R8이 동작하게 됩니다.

 

R8은 기존의 ProGuard가 하던 난독화 및 축소 기능과 D8 컴파일러가 하던 DEX 변환 기능을 하나로 합친 것으로 다음과 같은 작업을 모두 수행합니다.

  • 코드 축소: 사용되지 않는 클래스, 메서드, 필드를 제거합니다.
  • 난독화: 클래스, 메서드, 필드의 이름을 짧고 의미 없는 이름(예: a, b, c)으로 변경하여 리버스 엔지니어링을 어렵게 만듭니다.
  • 최적화: 코드를 분석하여 더 효율적으로 동작하도록 구조를 개선합니다.
  • DEX 변환: 위 과정들을 거친 최적화된 바이트코드를 안드로이드 런타임이 실행할 수 있는 .dex 파일로 변환합니다.

R8을 사용하여 코드 축소, 난독화, 최적화를 거치면 다양한 장점이 있습니다.

  • 앱 용량 감소 : 설치 파일 크기 감소
    • 사용되지 않는 클래스, 메서드, 필드 제거: 프로젝트에 포함했지만 실제로는 아무 곳에서도 쓰이지 않는 코드가 제거됩니다.
    • 라이브러리의 불필요한 부분 제거: 외부 라이브러리를 포함하면 전체 부분이 dex파일에 포함됩니다. 코드 축소를 사용하면 앱이 사용하는 기능과 관련된 코드만 남기고 나머지는 모두 삭제합니다.
    • 앱의 최종 설치 파일 크기가 눈에 띄게 줄어듭니다. 사용자의 데이터 부담을 덜어주어 다운로드 전환율을 높이고, 기기 저장 공간을 아낄 수 있습니다.
  • 성능 향상 : 더 빠르고 효율적인 코드
    • 코드 구조 개선: 불필요한 if-else 분기를 제거하거나, 더 이상 사용되지 않는 클래스를 합치는 등의 작업을 수행합니다.
    • 메서드 인라이닝: 짧고 자주 호출되는 메서드를 호출 지점에 직접 삽입하여 메서드 호출에 드는 오버헤드를 줄여줍니다.
    • 앱 시작 시간을 단축하고, UI 렌더링을 부드럽게 만들어 사용자 경험을 향상시킬 수 있습니다.
  • 보안 강화: 소스코드 난독화
    • 리버스 엔지니어링 방어: 해커가 앱을 디컴파일하더라도 코드의 구조와 로직을 파악하기 매우 어렵게 만듭니다. 중요한 메서드 이름이 a, b, c로 바뀌어 있다면, 비즈니스 로직을 분석하는 데 엄청난 시간과 노력이 필요하게 됩니다.
    • 지적 재산권 보호: 고유한 알고리즘이나 핵심 기술이 외부에 쉽게 노출되는 것을 방지하는 효과적인 방어가 됩니다.

 

안드로이드에서 난독화 적용하기

// app/build.gradle.kts

android {
    buildTypes {
        getByName("release") {
            isMinifyEnabled = true // 난독화 활성화
            isShrinkResources = true // 사용하지 않는 리소스 제거 활성화
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
}

 

앱 모듈에 릴리즈 빌드 타입에 설정합니다.

중요: 앱의 출시 빌드에는 항상 최적화를 사용 설정해야 하지만 테스트나 라이브러리에는 사용 설정하지 않는 것이 좋습니다.

 

디버그 빌드에서는 난독화를 적용하지 않는 것이 일반적입니다. 난독화의 목적이 코드 보호와 최적화에 있는 반면, 테스트의 목적은 빠른 개발과 안정성 검증에 있기 때문입니다. 난독화 과정이 추가되면 난독화와 코드 축소를 담당하는 R8이 앱의 모든 코드를 분석하고, 사용하지 않는 코드를 제거하며, 이름을 변경하는 복잡한 작업을 수행합니다. 이 과정은 빌드 시간을 상당히 증가시킵니다. 코드를 약간 수정하고 결과를 바로 확인해야 하는 개발 단계에서는 불편하기 때문입니다.

 

proguard-rules.pro

proguard-rules.pro는 R8 컴파일러가 코드를 최적화할 때 따라야 할 사용자 지정 규칙을 정의하는 설정 파일입니다. 이 파일을 통해 개발자는 난독화 과정에서 어떤 코드를 보존하고, 어떤 경고를 무시할지 등을 세밀하게 제어할 수 있습니다.

 

멀티 모듈 환경에서의 난독화

난독화는 각 모듈 개별적으로 수행됩니다. mapping.txt 파일 역시 별도로 생성됩니다. 그렇기 때문에 난독화의 범위를 제대로 설정하지 않으면 Unresolved reference의 오류가 발생하며 다른 모듈에서 난독화를 수행한 클래스나 메서드를 알 수 없게 됩니다.

Library classes are shrunk
Starting with Android Gradle Plugin 8.4, if an Android library project is minified, shrunk program classes will be published for inter-project publishing. This means that if an app depends on the shrunk version of the Android library subprojects, the APK will include shrunk Android library classes. You may need to adjust library keep rules in case there are missing classes in the APK.
In case you are building and publishing an AAR, local jars that your library depends on will be included unshrunk in the AAR, which means code shrinker won't run on them.
To revert to previous behavior, set android.disableMinifyLocalDependenciesForLibraries in the gradle.properties file and file a bug. Future versions of AGP will remove this flag remove this flag.

 

AGP 8.4+부터는 라이브러리에서 isMinifyEnabled = true를 설정하는 것을 기술적으로 금지하지는 않지만, 그렇게 했을 때 발생하는 새로운 동작 방식과 그에 따른 위험성을 설명합니다.

 

AGP 8.4+부터 라이브러리에서 isMinifyEnabled = true를 설정하면, 해당 라이브러리 모듈이 먼저 독립적으로 난독화됩니다. 그리고 app 모듈은 이미 난독화가 끝난 결과물을 가져다 쓰게 됩니다. 그렇기 때문에 디버깅이 어려워지고, 규칙 관리가 복잡하며, 예상치 못한 충돌이 일어날 수 있습니다.

 

그렇기 때문에 난독화는 application 모듈 한 곳에서만 수행하는 것이 가장 안전합니다. library 모듈은 isMinifyEnabled를 false로 설정하고 필요한 규칙만 consumerProguardFiles(...)을 사용하여 내보냅니다.

  application 모듈 library 모듈
컴파일 AAR/JAR 불러와 병합 각 모듈 단독 컴파일
코드 축소·난독화 활성화 (isMinifyEnabled=true) 기본적으로 비활성화 권장 (isMinifyEnabled=false)
규칙 전달 proguardFiles 로 직접 지정 consumerProguardFiles 로 AAR 안에 포함
// library/build.gradle.kts

android {
    buildTypes {
        release {
            isMinifyEnabled = false // 라이브러리 내부에서는 비활성
            consumerProguardFiles("consumer-rules.pro") // 외부로 전달할 규칙
        }
    }
}

 

라이브러리 모듈에서 isMinifyEnabled를 false로 설정하고, consumerProguardFiles(...)를 통해 규칙을 외부로 전달하면, 빌드 시 app 모듈은 모든 라이브러리 모듈로부터 consumer-rules.pro 파일을 자동으로 수집하여 최종 난독화에 반영합니다.

 

proguard-rules.pro과 consumer-rules.pro 자세히 알아보기

proguard-rules.pro와 consumer-rules.pro는 R8 컴파일러가 코드를 최적화할 때 따라야 할 사용자 지정 규칙을 정의하는 설정 파일입니다.

// R8이 참조할 규칙 파일 목록 지정
proguardFiles(
    getDefaultProguardFile("proguard-android-optimize.txt"),
    "proguard-rules.pro"
)

 

proguard-android-optimize.txt: 안드로이드 SDK가 기본적으로 제공하는 규칙 파일입니다. 대부분의 안드로이드 프레임워크 클래스가 문제없이 작동하도록 보장하는 규칙들이 들어있습니다.

 

proguard-rules.pro: 바로 이 파일을 직접 작성하고 관리하는 사용자 정의 규칙 파일입니다. 앱의 고유한 로직, 사용하는 라이브러리, 데이터 클래스 등을 보호하기 위한 규칙을 여기에 추가합니다.

  • -keep : 코드를 보존하는 가장 중요한 규칙
  • -dontwarn : 특정 경고 무시하기
  • -keepattributes : 추가 정보 유지하기

이러한 규칙을 주요 사용 사례는 다음과 같습니다:

  • 어노테이션에 의존하는 Gson/Retrofit 모델 클래스
  • 컴파일 시점에 생성되는 클래스를 사용하는 Glide 모듈
  • 특정 기본 인터페이스나 내부 프레임워크 클래스를 온전히 유지해야 할 때

Gson R8 / ProGuard

 

최근 대부분의 라이브러리는 업데이트되면서 이러한 규칙을 포함하고 있습니다. 앱 모듈에서 라이브러리에 포함된 규칙들을 수집하여 적용합니다.

 

하지만 라이브러리가 규칙을 포함하지 않거나, 포함되더라도 직접 규칙을 추가해야 할 부분이 있다면, 직접 규칙을 추가하고 관리해야 할 수 있습니다.

 

이런 식으로 모듈이 많아지고 사용하는 라이브러리가 많아질수록 규칙 관리가 매우 혼란스러워질 수 있습니다.

app/
  ├── proguard-rules.pro
  ├── retrofit-proguard-rules.pro
  └── glide-proguard-rules.pro
libraryA/
  └── consumer-rules.pro
libraryB/
  └── consumer-rules.pro
  
proguardFiles(
    getDefaultProguardFile("proguard-android-optimize.txt"),
    "proguard-rules.pro",
    "retrofit-proguard-rules.pro",
    "glide-proguard-rules.pro"
)

 

서드파티 라이브러리 규칙을 별도로 적용하여 라이브러리 별로 더 간단하게 관리할 수 있을 것 같습니다.

 

출력파일 확인

 

빌드 후 생성되는 다음 파일들을 통해 난독화 결과를 확인할 수 있습니다.

  • configuration.txt: 최종적으로 병합된 전체 ProGuard 설정입니다.
  • mapping.txt: 클래스 이름이 어떻게 매핑되었는지 보여줍니다.
  • resources.txt: 제거된 리소스 목록입니다.
  • seeds.txt: 제거되지 않고 유지된 클래스 목록입니다.
  • usage.txt: 제거된 클래스 목록입니다.

configuration.txt를 확인해 보면, 직접 작성하지 않은 규칙들 외에도 라이브러리에서 받은 consumer-rules.pro도 포함되어 있는 것을 확인할 수 있었습니다.

 

analyze APK

좌측 debug APK, 우측 release APK

 

안드로이드 스튜디오에서 Build → analyze APK... 를 사용하면 APK를 파일을 분석할 수 있습니다. AppLink Alarm 프로젝트를 통해 난독화와 최적화 과정이 얼마나 효과적인지 비교해 보았습니다.

 

난독화 및 최적화 과정이 포함되지 않은 debug 빌드에서는 APK 크기가 26.1 MB입니다. 반면 release 빌드에서는 APK 크기가 5.2MB5배 정도 감소하였습니다.

 

또한 classes.dex 파일 역시 debug 빌드에서는 24개나 있지만, release 빌드에서는 1개의 classes.dex파일만 존재하게 되며 코드가 매우 축소되었습니다. 이로 인해 앱 로딩 속도와 성능도 개선될 것으로 보입니다.

 

 

참고자료

https://developer.android.com/topic/performance/app-optimization/library-optimization?hl=ko

 

라이브러리 작성자를 위한 최적화  |  App quality  |  Android Developers

라이브러리가 Android 최적화와 호환되는지 확인합니다.

developer.android.com

https://developer.android.com/studio/projects/android-library?hl=ko#Considerations

 

Android 라이브러리 만들기  |  Android Studio  |  Android Developers

Android 라이브러리를 생성하는 방법을 알아보세요.

developer.android.com

https://developer.android.com/topic/performance/app-optimization/test-and-troubleshoot-the-optimization?hl=ko

 

최적화 테스트 및 문제 해결  |  App quality  |  Android Developers

앱 CUJ를 테스트하고 최적화 전후에 앱 성능을 측정합니다.

developer.android.com

https://developer.android.com/build/releases/past-releases/agp-8-4-0-release-notes

 

Android Gradle 플러그인 8.4.0 (2024년 4월)  |  Android Developers

Android Gradle 플러그인 8.4.0 출시 노트

developer.android.com

https://developer.android.com/topic/performance/app-optimization/enable-app-optimization?hl=ko

 

앱 최적화 사용 설정  |  App quality  |  Android Developers

R8을 사용 설정하여 앱 크기와 속도를 최적화하는 방법을 알아보세요.

developer.android.com

https://developer.android.com/topic/performance/app-optimization/add-keep-rules?hl=ko

 

보관 규칙 추가  |  App quality  |  Android Developers

R8 보관 규칙을 작성하는 방법을 알아보세요.

developer.android.com

https://drjansari.medium.com/mastering-proguard-in-android-multi-module-projects-agp-8-4-r8-and-consumable-rules-ae28074b6f1f

 

Mastering ProGuard in Android Multi-Module Projects: AGP 8.4+, R8, and Consumable Rules

1. Introduction + What is ProGuard?

drjansari.medium.com

https://hyeonlog-developer.tistory.com/174

 

[Android/공부] 안드로이드 소스 코드 난독화 R8 / Proguard

1. 코드 난독화 필요성안드로이드 앱을 개발 후 APK 실행 파일을 추출할 수 있다. 또한 추출한 APK를 바탕으로 앱의 소스코드가 분석 가능하도록 디컴파일 할 수 있다.이는 테스트 및 리버스 엔지

hyeonlog-developer.tistory.com

https://www.androidhuman.com/2016-10-10-common_proguard_rules

 

Proguard를 사용한 코드 난독화 - 자주 사용하는 라이브러리의 난독화 규칙, 규칙 분리 관리하기

#Android, #Kotlin, and #Tesla

www.androidhuman.com

 

 

 

'Android' 카테고리의 다른 글

Android 빌드 과정 이해하기  (2) 2025.07.09