ProGuard/R8: Android 앱의 난독화 및 보호

저자: IT Sectr 게시일: 2026-02-14 읽는 시간: 8 분

ProGuardR8은 Android 애플리케이션을 위한 난독화, 축소화 및 최적화 도구입니다. 2002년에 만들어진 ProGuard는 오랫동안 Java 코드 보호의 사실상 표준이었습니다. R8은 그 후속 제품으로, Google이 개발했으며 AGP 3.4부터 Android Gradle Plugin에 내장되었습니다. 두 도구 모두 APK 크기를 줄이고, 데드 코드를 제거하며, 리버스 엔지니어링을 어렵게 만듭니다. Android Developers에 따르면, R8은 비슷한 난독화 품질로 ProGuard보다 2~3배 빠르게 빌드를 수행합니다.

핵심 사항

  • ProGuard — Java 바이트코드 난독화 및 최적화 도구, 2000년대부터 Android의 표준
  • R8 — Google의 ProGuard 후속 제품, AGP에 내장, 한 번의 패스로 난독화, 축소화, 최적화 수행
  • 난독화는 클래스와 메서드를 짧은 이름으로 바꾸어 앱의 리버스 엔지니어링을 어렵게 만듦
  • 축소화는 사용하지 않는 클래스, 메서드, 필드를 제거하여 최종 APK/AAB 크기를 줄임
  • ProGuard rules(.pro 파일)는 코드의 어떤 부분을 보존, 난독화 또는 제거할지 제어

ProGuard란?

ProGuard는 Java 바이트코드의 난독화, 축소화, 최적화 및 사전 검증을 위한 오픈소스 도구(Apache 2.0)입니다. 2002년 Eric Lafarge가 SourceForge 프로젝트의 일부로 개발했습니다. ProGuard는 컴파일된 Java 클래스(.class) 또는 JAR 아카이브를 입력으로 받아 동일한 형식의 처리된 클래스를 출력하지만, 크기는 더 작고 요소는 이름이 변경됩니다.

오랫동안 ProGuard는 리버스 엔지니어링으로부터 Android 애플리케이션을 보호하는 유일한 표준이었습니다. Google은 Android SDK에서의 사용을 공식적으로 권장했으며 SDK 도구 내의 proguard-android-optimize.txt 파일에 기본 구성을 제공했습니다. ProGuard는 독립형 도구로 작동했으며, Java 코드를 바이트코드로 컴파일한 후 DEX로 패키징하기 전에 실행되었습니다.

ProGuard 아키텍처

ProGuard는 4개의 순차적 단계로 구성됩니다: shrink(사용하지 않는 클래스 제거), optimize(바이트코드 최적화 — 인라인, 데드 코드 제거), obfuscate(클래스, 메서드, 필드를 짧은 이름으로 변경), preverify(JVM 호환성 확인). 각 단계는 구성 파일의 개별 규칙에 의해 제어됩니다.

난독화 단계에서 ProGuard는 매핑 파일(mapping.txt)을 생성하여 원래 이름을 난독화된 이름에 매핑합니다. 이 파일은 retrace 유틸리티를 통해 릴리스 빌드의 크래시 로그를 디코딩하는 데 중요합니다. 매핑 파일이 없으면 스택 트레이스는 a(), b(), c()의 문자 집합이 되어 원래 컨텍스트를 복원할 방법이 없습니다.

ProGuard 단계목적결과
Shrink호출 그래프 분석 및 데드 코드 제거APK 내 클래스 감소
Optimize메서드 인라인, 사용하지 않는 매개변수 제거코드 실행 속도 향상
Obfuscate클래스, 필드, 메서드 이름 변경리버스 엔지니어링 방지
PreverifyJVM용 StackMap 속성 추가Java 6+ 호환성

R8이란?

R8은 Google의 차세대 난독화 및 축소화 도구로, Android Studio 3.3(2018년 11월)에서 처음 도입되었고 AGP 3.4(2019년 8월)에서 표준이 되었습니다. ProGuard와 달리 R8은 Java 바이트코드를 DEX 형식으로 변환하는 D8/R8 컴파일러의 일부입니다. R8은 난독화, 축소화, 최적화의 모든 단계를 단일 패스로 수행하며, 도구 간에 중간 파일을 전달할 필요가 없습니다.

Google은 R8을 두 가지 목표로 개발했습니다: 빌드 속도 향상(ProGuard는 외부 도구로 작동)과 최신 Android 스택(Desugar, Core Library Desugaring, D8)과의 원활한 통합입니다. R8은 Kotlin과 Java로 작성되었으며 AOSP(Android Open Source Project)의 R8/Desugar 리포지토리의 일부입니다.

R8의 중요한 장점은 ProGuard 규칙과의 완전한 하위 호환성입니다. 기존 .pro 파일은 변경 없이 작동합니다. R8은 -whyareyoukeeping, -printconfiguration, -printmapping을 포함한 특정 ProGuard 지시문도 지원합니다. 즉, ProGuard에서 R8로의 전환은 투명합니다: AGP만 업데이트하면 됩니다.

kotlin
// build.gradle.kts — minifyEnabled를 통한 R8 활성화
android {
    buildTypes {
        getByName("release") {
            isMinifyEnabled = true
            isShrinkResources = true

            proguardFiles(
                // Android SDK의 기본 구성
                getDefaultProguardFile("proguard-android-optimize.txt"),
                // 사용자 정의 프로젝트 규칙
                "proguard-rules.pro"
            )
        }
    }
}

코드는 표준 릴리스 빌드 구성을 보여줍니다. 플래그 isMinifyEnabled = true는 난독화 및 최적화를 위해 R8을 활성화합니다. isShrinkResources = true는 사용하지 않는 리소스를 추가로 제거합니다. getDefaultProguardFile은 SDK에서 기본 규칙을 로드하고, proguard-rules.pro에는 프로젝트별 설정이 포함됩니다.

Android 코드 난독화

난독화는 소스 코드를 사람이 분석하기 어렵지만 완전한 기능을 유지하는 형태로 변환하는 프로세스입니다. Android 컨텍스트에서 난독화는 클래스, 메서드, 필드를 짧고 의미 없는 이름으로 변경하는 것을 의미합니다: com.example.app.auth.LoginManagera.a.a가 되고, 메서드 authenticateUsera가 되고, 필드 userTokenb가 됩니다.

난독화가 필요한 이유

Android APK 파일은 아카이버(ZIP, 7z, WinRAR)로 열 수 있는 아카이브입니다. 난독화가 없으면 공격자는 패키지 이름, 클래스, 메서드, 필드 등 애플리케이션의 전체 맵을 얻을 수 있습니다. jadx 또는 Bytecode Viewer와 같은 도구는 DEX 파일에서 거의 원본 Java 코드를 몇 초 만에 복원할 수 있습니다. 난독화는 코드를 무적으로 만들지는 않지만 진입 장벽을 크게 높입니다: 의미 있는 이름 대신 독자는 a(), b(), c()를 보게 됩니다.

일반적인 난독화 목표: 상업적 로직(알고리즘, 계산 공식) 보호, API 키 및 토큰 도난 방지, 리플렉션을 통한 클래스 대체 방지, APK 패치 및 수정(리패키지 공격) 방지. 실제로 작업의 70%는 이름 변경만으로 해결됩니다 — 이것이 ProGuard/R8이 사용되는 이유입니다.

ProGuard 규칙 예제

아래는 Retrofit, Gson, Parcelable을 사용하는 Android 프로젝트의 일반적인 proguard-rules.pro 파일입니다. -keep 규칙은 리플렉션을 통한 라이브러리 작동에 필요한 클래스와 메서드를 보존합니다. 이러한 규칙이 없으면 R8은 라이브러리가 문자열 이름으로 액세스하는 클래스를 제거하거나 이름을 변경합니다.

pro
# =====================
# Retrofit — 인터페이스 보존
# =====================
-keep,allowobfuscation,allowshrinking interface retrofit2.** { *; }
-keepattributes Signature, Exceptions

# =====================
# Gson — JSON 직렬화
# =====================
-keepclassmembers class * {
    @com.google.gson.annotations.SerializedName <fields>;
}
-keep class *.serialization.** {
    <fields>;
}

# =====================
# Parcelable — Creator
# =====================
-keepclassmembers class * implements android.os.Parcelable {
    public static final android.os.Parcelable$Creator CREATOR;
}

# =====================
# Logging — 릴리스에서 로그 제거
# =====================
-assumenosideeffects class android.util.Log {
    public static boolean isLoggable(String, int);
    public static int v(...);
    public static int d(...);
    public static int i(...);
    public static int w(...);
    public static int e(...);
}

# =====================
# Kotlin 데이터 클래스 — 생성자 보존
# =====================
-keepclassmembers class * {
    @kotlin.Metadata <fields>;
}

# =====================
# Activity — 진입점
# =====================
-keep class * extends android.app.Activity {
    @android.annotation.SuppressLint <methods>;
}

.pro 파일의 각 지시문은 특정 작업을 해결합니다. -keep은 전체 클래스가 제거되거나 이름이 변경되는 것을 방지합니다. -keepclassmembers는 클래스 멤버(필드 및 메서드)만 보호하지만 클래스 자체가 사용되지 않으면 제거를 허용합니다. -assumenosideeffects는 메서드 호출에 부작용이 없으며 안전하게 제거할 수 있음을 R8에 알립니다. -keepattributes 지시문은 바이트코드의 메타데이터(어노테이션, 시그니처, 예외)를 보존합니다.

Retrofit의 규칙 -keep,allowobfuscation,allowshrinking은 R8이 인터페이스 이름을 변경할 수 있도록 허용하지만 제거는 허용하지 않습니다. 이는 Retrofit이 동적 프록시(java.lang.reflect.Proxy)를 통해 인터페이스에 액세스하고, 제거하면 런타임에 ClassNotFoundException이 발생하기 때문에 필요합니다. 마찬가지로 Gson은 @SerializedName으로 어노테이션된 필드에 액세스하기 위해 리플렉션을 사용합니다 — -keepclassmembers가 없으면 필드가 사용하지 않는 것으로 제거됩니다.

축소화 및 ShrinkResources

축소화(shrinking)는 최종 빌드에서 사용하지 않는 코드와 리소스를 제거하는 프로세스입니다. ProGuard와 R8은 진입점(Activity, Service, BroadcastReceiver)에서 시작하여 호출 그래프를 분석하고 호출 체인을 통해 도달할 수 없는 클래스와 메서드를 제거합니다. ShrinkResources는 res/(layout, drawable, string, color)에서 사용하지 않는 리소스를 제거하는 추가 단계입니다.

축소화는 라이브러리가 있는 대규모 프로젝트에서 가장 큰 이점을 제공합니다. 일반적인 시나리오: 프로젝트가 연결된 라이브러리(예: Google Play Services)의 코드 10%만 사용하는 경우, 축소화 없이 모든 라이브러리 코드가 APK에 포함됩니다. 축소화를 사용하면 R8이 라이브러리 코드의 70~90%를 제거하고 실제로 사용되는 클래스와 메서드만 남깁니다. 이는 APK 크기, 로딩 시간 및 메모리 소비에 직접적인 영향을 미칩니다.

ShrinkResources 작동 방식

ShrinkResources 메커니즘은 코드 축소화와 함께 작동합니다. R8이 어떤 클래스가 사용되는지 확인한 후, 리소스 축소는 코드의 리소스 참조를 분석합니다: R.layout.main, R.drawable.icon, getString(R.string.title). 직접 또는 간접 참조가 없는 모든 리소스는 최종 APK 또는 AAB에서 제거됩니다. 이는 리소스 파일 resources.arsc와 res/ 폴더를 사용하여 수행됩니다.

중요한 세부 사항: 리소스는 getIdentifier() 또는 Resources.getResourceName()을 통해 문자열 이름으로 액세스할 수 있으며, R 클래스를 우회합니다. 이러한 경우 R8은 직접 링크를 보지 못하고 실제로 사용 중인 리소스를 제거할 수 있습니다. 이러한 리소스를 보호하기 위해 지시문 -keep class **.R$* { *; }이 있습니다 — R 클래스의 모든 식별자를 보존합니다.

xml
<!-- 예제: getIdentifier()를 통해서만 사용되는 리소스 -->
<string name="dynamic_title_welcome">환영합니다</string>
<string name="dynamic_title_share">공유</string>

<!-- 문자열로 액세스하는 Kotlin 코드 -->
<!-- val title = getString(resources.getIdentifier( -->
<!--     \"dynamic_title_${type}\", \"string\", packageName)) -->

이 경우 R8은 R 클래스에서 dynamic_title_welcome에 대한 정적 참조를 볼 수 없습니다. 액세스가 동적 이름으로 getIdentifier를 통해 이루어지기 때문입니다. 이러한 리소스를 보존하려면 proguard-rules.pro에 지시문 -keepclassmembers class **.R$string { *; }을 추가하세요 — 모든 R$string 클래스의 모든 필드 제거를 방지합니다.

지시문목적예제
-keep클래스와 모든 멤버 보존-keep class com.example.api.** { *; }
-keepclassmembers클래스 멤버만 보존-keepclassmembers class * { @SerializedName <fields>; }
-keepattributes바이트코드 메타데이터 보존-keepattributes *Annotation*, Signature
-assumenosideeffects부작용 없는 호출 제거-assumenosideeffects class Log { d(...); }
-dontwarn경고 억제-dontwarn com.example.legacy.**

R8 vs ProGuard: 주요 차이점

R8이 ProGuard의 후속 제품임에도 불구하고 아키텍처, 성능 및 동작에서 도구 간에 근본적인 차이점이 있습니다. Google은 AGP 7.0부터 Android Gradle Plugin에서 ProGuard 지원을 공식적으로 중단했지만, R8에서 사용할 수 없는 특정 최적화 동작이 필요한 프로젝트에서는 ProGuard가 계속 사용되고 있습니다.

비교 표

특성ProGuardR8
개발자GuardSquare (Eric Lafarge)Google
출시 연도20022018 (2019년 안정화)
아키텍처4개의 개별 단계 (shrink → optimize → obfuscate → preverify)단일 패스: shrink + optimize + obfuscate 동시 수행
AGP 통합외부 도구, javac 후 실행D8 DEX 컴파일러에 내장
빌드 속도2~3배 느림단일 패스 및 네이티브 통합으로 더 빠름
Kotlin 지원제한적 (inline, lambdas, coroutines 문제)완전: coroutines, inline 함수, data class
매핑 파일mapping.txt (retrace와 호환)mapping.txt (동일 형식)
최적화 사용자 지정60개 이상의 옵션 -optimizationpasses, -optimizations제한적: 대부분의 최적화가 기본적으로 활성화
지원 상태R8로 대체됨 (AGP 7.0+에서 사용 안 함)활발한 개발 중, AOSP의 일부

R8이 빌드를 손상시킬 수 있는 경우

R8은 죽은 코드라고 판단되는 것을 제거하는 데 있어 ProGuard보다 더 적극적입니다. 이로 인해 디버그 빌드는 작동하지만 릴리스 빌드가 ClassNotFoundException 또는 NoSuchMethodException으로 크래시되는 상황이 발생합니다. 일반적인 경우: 클래스 이름으로 리플렉션을 사용하는 라이브러리(Gson, Moshi, Retrofit, Room, Dagger); ServiceLoader 또는 java.util.ServiceLoader 호출; 동적 프록시(java.lang.reflect.Proxy); 네이티브 메서드(JNI). 해결책은 리플렉션을 통해 호출되는 모든 클래스에 -keep을 추가하는 것입니다.

pro
# 일반적인 리플렉션 문제 — R8이 정적 링크를 인식하지 못함

# Room — DAO 및 마이그레이션 보존
-keep class * extends androidx.room.RoomDatabase { *; }
-keep class *.DatabaseMigrations { *; }

# Dagger / Hilt — 구성 요소 보존
-keep class * extends dagger.hilt.android.components.** { *; }

# JNI — 네이티브 메서드 이름 변경 안 함
-keepclasseswithmembernames class * {
    native <methods>;
}

# Data Binding — Binding 클래스 보존
-keep class *.databinding.** { *; }

규칙을 추가한 후에도 빌드가 계속 크래시되면 proguard-rules.pro에서 플래그 -printconfiguration full-config.txt를 사용하세요. R8은 어떤 규칙이 적용되고 어떤 클래스가 보존되는지 보여주는 전체 구성 파일을 생성합니다. 지시문 -whyareyoukeeping class com.example.MyClass도 유용합니다 — R8이 특정 클래스를 보존하기로 결정한 이유를 출력합니다.

ProGuard Rules 구성

ProGuard rules의 적절한 구성은 런타임 버그 없이 안정적인 난독화를 위한 핵심입니다. 아래는 새 프로젝트 또는 난독화가 오류를 일으키는 프로젝트를 위한 단계별 설정 프로세스입니다.

1단계: 기본 구성

표준 Android SDK 파일인 proguard-android-optimize.txt를 포함하여 시작하세요. 여기에는 기본 Android 구성 요소(Activity, Service, BroadcastReceiver, ContentProvider, View, Fragment)에 대한 규칙이 포함되어 있습니다. 이 파일은 SDK 폴더에 있습니다: $ANDROID_HOME/tools/proguard/proguard-android-optimize.txt. AGP를 사용하는 경우 getDefaultProguardFile이 자동으로 로드합니다.

2단계: 라이브러리

각 인기 라이브러리에는 권장 ProGuard 규칙이 있습니다. Retrofit, OkHttp, Glide, Fresco, Coil, Room, Dagger/Hilt, Kotlin Coroutines — 모두 특정 -keep 규칙이 필요합니다. 일반적으로 규칙은 AAR 라이브러리에 포함되어 있으며 소비자 가드 규칙을 통해 자동으로 연결됩니다. 라이브러리가 AAR 내에 proguard.txt 파일을 제공하는지 확인하세요 — 이는 규칙이 이미 고려되었음을 나타냅니다.

3단계: 릴리스 빌드 테스트

게시하기 전에 실제 기기 또는 에뮬레이터에서 릴리스 빌드를 테스트해야 합니다. 난독화 문제는 런타임에만 나타납니다. 확인 사항: 인증(로그인/등록), 네트워크에서 데이터 로드, 화면 간 탐색, 카메라 및 갤러리, 푸시 알림, Deeplinks, WebView. 릴리스 빌드의 각 크래시는 매핑 파일로 retrace를 사용하여 디코딩하고 누락된 -keep 규칙을 추가해야 합니다.

4단계: 매핑 파일 및 CI

매핑 파일은 build/outputs/mapping/release/mapping.txt에 생성됩니다. 이 파일은 반드시 보존해야 합니다: 이 파일 없이는 Google Play Console의 크래시 로그를 디코딩할 수 없습니다. mapping.txt를 버전 관리 시스템에 포함하거나 CI 아티팩트로 업로드하세요. Google Play Console은 uploading mapping.txt를 활성화한 상태로 AAB를 업로드할 때 매핑 파일을 자동으로 수락합니다.

아래는 proguard-rules.pro 파일의 각 규칙 그룹에 대한 주석이 포함된 완전한 난독화 설정 워크플로입니다.

pro
# ===========================================
# proguard-rules.pro — 전체 예제
# ===========================================

# --- 일반 설정 ---
-keepattributes *Annotation*, Signature, Exceptions, InnerClasses, EnclosingMethod
-dontpreverify

# --- Android 구성 요소 ---
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.Fragment
-keep public class * extends androidx.fragment.app.Fragment
-keep public class * extends android.view.View

# --- OkHttp / Retrofit ---
-dontwarn okhttp3.**
-dontwarn okio.**
-keep class retrofit2.** { *; }
-keepattributes Exceptions

# --- Gson / Moshi ---
-keepclassmembers class * {
    @com.google.gson.annotations.SerializedName <fields>;
}
-keep class com.google.gson.** { *; }

# --- Firebase ---
-keep class com.google.firebase.** { *; }
-keep class com.google.android.gms.** { *; }

# --- Kotlin Coroutines ---
-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}
-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}

# --- 직렬화 ---
-keepclassmembers class * implements java.io.Serializable {
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

# --- R8 전용: 강제 보존 ---
# (ProGuard는 이 지시문을 무시함)
-keep,allowobfuscation class * implements android.os.Parcelable {
    public static final android.os.Parcelable$Creator CREATOR;
}

구성 후 빌드를 실행하세요: ./gradlew assembleRelease. build/outputs/mapping/release/에 파일이 나타났는지 확인하세요: mapping.txt(원래 이름에서 난독화된 이름으로의 매핑), seeds.txt(-keep 규칙으로 보존된 클래스), usage.txt(축소화 중 제거된 클래스). 난독화 후 APK 크기는 연결된 라이브러리 수에 따라 20~50% 감소해야 합니다.

자주 묻는 질문

R8과 ProGuard의 차이점은 무엇인가요?

R8은 ProGuard의 후속 제품으로 Google이 개발했습니다. R8은 난독화, 축소화, 최적화를 단일 패스로 수행하며 ProGuard보다 2~3배 빠르고 Android Gradle Plugin에 직접 통합되어 있습니다. ProGuard는 4개의 개별 단계를 사용하며 외부 실행이 필요합니다. AGP 7.0부터 ProGuard는 사용되지 않으며 기본적으로 R8이 작동합니다.

R8을 사용할 때 ProGuard 규칙을 작성해야 하나요?

네, R8은 동일한 ProGuard 규칙(.pro 파일)을 사용합니다. -keep, -keepclassmembers, -keepattributes, -assumenosideeffects 지시문은 동일하게 작동합니다. 기본 규칙은 Android SDK의 proguard-android-optimize.txt에 있으며, 라이브러리별 규칙(Retrofit, Room, Gson)은 프로젝트의 proguard-rules.pro에 추가됩니다. 이러한 규칙이 없으면 R8은 리플렉션을 통해 작동하는 라이브러리에 필요한 클래스를 제거할 수 있습니다.

Android 프로젝트에서 R8을 활성화하려면 어떻게 하나요?

R8은 AGP 3.4부터 Android Gradle Plugin에서 기본적으로 활성화되어 있습니다. 축소화를 활성화하려면 build.gradle.kts의 release buildType 블록에서 isMinifyEnabled = true를 설정하세요. 추가 플래그 isShrinkResources = true는 사용하지 않는 리소스 제거를 활성화합니다. gradle.properties에서 android.enableR8=false를 통해 R8을 강제로 비활성화할 수 있지만 권장되지 않습니다 — R8이 더 빠르고 안정적입니다.

Android에서 코드 난독화란 무엇인가요?

난독화 — 클래스, 메서드, 필드를 짧고 의미 없는 이름(a, b, c)으로 변경하는 것입니다. 클래스 com.example.app.auth.LoginManager는 a.a.a가 되고, 메서드 authenticateUser는 a가 됩니다. 이는 애플리케이션의 리버스 엔지니어링을 어렵게 만들지만 실행 로직에는 영향을 미치지 않습니다. ProGuard와 R8은 -keep 규칙으로 보호되지 않은 요소만 이름을 변경합니다. 매핑 파일은 크래시 로그 디코딩을 위해 원래 이름과 난독화된 이름의 대응 관계를 보존합니다.

난독화된 애플리케이션의 크래시 로그를 디버그하려면 어떻게 하나요?

스택 트레이스를 디코딩하려면 retrace 유틸리티(ProGuard/R8 SDK의 일부)를 사용하세요. 명령: retrace mapping.txt crash-stacktrace.txt. 매핑 파일은 build/outputs/mapping/release/mapping.txt에 있습니다. Google Play Console은 AAB 게시 시 mapping.txt 업로드도 지원하며, 크래시 로그는 콘솔에서 자동으로 디코딩됩니다. 매핑 파일이 없으면 스택 트레이스에는 a.b.c()와 같은 난독화된 이름만 포함되어 디버깅에 무용지물입니다.

요약

  • ProGuard — 4개의 순차적 단계로 구성된 클래식 Java 바이트코드 난독화 및 최적화 도구
  • R8 — Google의 현대적 후속 제품, AGP에 내장, 단일 패스로 모든 단계를 2~3배 더 높은 성능으로 수행
  • 난독화는 클래스, 메서드, 필드를 짧은 이름으로 변경하여 리버스 엔지니어링을 어렵게 만들고 애플리케이션의 상업적 로직을 보호
  • 축소화는 사용하지 않는 코드와 리소스를 제거하여 일반적인 프로젝트에서 APK 크기를 20~50% 감소
  • ProGuard rules(.pro 파일)는 난독화 동작을 제어 — -keep, -keepclassmembers, -assumenosideeffects 지시문은 보존, 제거 또는 이름 변경할 요소를 지정
  • 매핑 파일(mapping.txt)은 retrace를 통해 릴리스 빌드의 크래시 로그를 디코딩하기 위한 매우 중요한 빌드 아티팩트
  • 테스트는 실제 기기에서 릴리스 빌드를 반드시 수행해야 함 — 난독화 문제는 런타임에만 나타나며 누락된 -keep 규칙 추가가 필요

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기