R8로 Unity 코드 축소 및 최적화

Unity의 핵심 게임 로직은 C# (IL2CPP로 컴파일됨)로 작성되지만 Android 빌드에는 UnityPlayerActivity 수명 주기 이벤트, Google Play 서비스, 결제, 광고, 소셜 SDK를 처리하기 위한 상당한 양의 자바 및 Kotlin 바이트 코드 (classes.dex)가 포함됩니다.

Android Gradle 플러그인 (AGP)의 기본 코드 축소기 및 최적화 도구인 R8을 사용 설정하면 사용되지 않는 클래스와 메서드가 삭제되고 바이트 코드가 최적화됩니다. 이렇게 하면 앱 다운로드 크기가 줄어들 뿐만 아니라 메모리 매핑 (mmap) DEX 페이지의 런타임 메모리 사용량과 기준 Java 프로세스 오버헤드가 줄어들어 실제 메모리 압박과 로우 메모리 킬러 (LMK) 종료가 완화됩니다. Google Play는 Android vitals의 DEX 코드 최적화 측정항목을 통해 게임의 DEX 최적화 수준도 모니터링합니다.

기본 동작 및 Unity 버전 지원

Unity에서 새 프로젝트를 만들 때 출시 및 디버그 빌드 모두에서 코드 축소가 기본적으로 사용 중지 (false)됩니다.

Unity는 Unity 2020.1.0f1에서 R8을 선택적 전환으로 처음 도입했습니다. Unity 2022.2.0f1 (Unity 2021.3.41f1 LTS로 백포팅됨)부터 Unity는 번들 도구 모음을 AGP 7.1.2 이상으로 업그레이드하고 기존 ProGuard 지원을 삭제했으며 축소가 사용 설정될 때마다 R8을 독점적으로 실행합니다.

Unity 버전 번들 AGP 기본 출시 버전 R8 지원 및 필수 구성
2019.4 LTS 이하 3.4 이전 사용 중지됨 (false) 지원되지 않음 (기존 ProGuard만 해당)
2020.1.0f1~2021.3.40f1 3.4~4.0 사용 중지됨 (false) 선택사항 (기본값은 ProGuard) Minify(축소) > Release(출시)와 Use R8(R8 사용)을 모두 사용 설정합니다.
2021.3.41f1 이상 (2021 LTS) 7.1+ 사용 중지됨 (false) R8만 해당. Minify > Release를 사용 설정하여 R8을 자동으로 실행합니다.
2022.2.0f1~Unity 6 이상 7.1~8.x 사용 중지됨 (false) R8만 해당. Minify > Release를 사용 설정하여 R8을 자동으로 실행합니다.

플레이어 설정에서 R8 사용 설정

출시 빌드에 R8 코드 축소 및 최적화를 사용 설정하려면 다음 단계를 따르세요.

  1. Unity 에디터에서 Edit(수정) > Project Settings(프로젝트 설정)를 열고 Player(플레이어)를 선택합니다.
  2. Android 탭을 선택하고 Publishing Settings(게시 설정) > Build(빌드)를 펼칩니다.
  3. Minify 섹션에서 Unity 버전에 맞는 옵션을 구성합니다.
    • Unity 2021.3.41f1 이상 및 2022.2.0f1 이상: Release를 선택합니다. Unity는 minifyReleaseWithR8 Gradle 작업 중에 R8을 자동으로 실행합니다.
    • Unity 2020.1.0f1~2021.3.40f1: Release와 Use R8을 모두 선택합니다.

C# 편집기 스크립트를 사용하여 빌드를 자동화하는 경우 PlayerSettings.Android를 통해 다음 속성을 구성합니다.

using UnityEditor;

public static class AndroidBuildConfig
{
    public static void EnableR8ForRelease()
    {
        PlayerSettings.Android.minifyRelease = true;

        // Required only in Unity 2020.1.0f1 to 2021.3.40f1 and 2022.1 or earlier
        // (In Unity 2021.3.41f1+ and 2022.2+, R8 is always used when minification is enabled)
#if !UNITY_2022_2_OR_NEWER
        PlayerSettings.Android.minifyWithR8 = true;
#endif
    }
}

JNI 및 리플렉션에 대한 유지 규칙 추가

AndroidJavaClass 또는 AndroidJavaObject를 사용하여 C# 스크립트에서 동적으로 호출되는 Java 클래스 및 메서드에는 정적 Java 호출 사이트가 없습니다. 명시적인 유지 규칙이 없으면 R8은 이러한 클래스를 사용되지 않는 것으로 간주하여 삭제하거나 이름을 바꿀 수 있습니다.

커스텀 Java 브리지를 보존하려면 다음 안내를 따르세요.

  1. Project Settings(프로젝트 설정) > Player(플레이어) > Android > Publishing Settings(게시 설정) > Build(빌드)에서 Custom Proguard File(맞춤 Proguard 파일)을 사용 설정합니다.
  2. 생성된 Assets/Plugins/Android/proguard-user.txt 파일을 엽니다.
  3. JNI를 통해 액세스하거나 서드 파티 플러그인에 필요한 클래스에 -keep 규칙을 추가합니다.
# Keep custom Java classes invoked from C# using JNI bridges
-keep class com.example.yourgame.** { *; }

# Keep callback interfaces passed between C# and Java
-keep interface com.example.yourgame.IPluginCallback { *; }

일반적인 문제 해결

이 섹션에서는 Unity에서 R8을 사용할 때 발생하는 일반적인 빌드 및 런타임 문제를 해결하는 방법을 설명합니다.

빌드 오류 Missing classes detected while running R8개

AGP 7.0 이상 (2021.3.41f1+ 및 2022.2+)을 사용하는 Unity 버전에서는 R8이 엄격한 누락 클래스 검사를 시행합니다. 이 오류로 인해 빌드가 실패하면 빌드 출력 디렉터리 (Library/Bee/Android/Prj/.../build/outputs/mapping/release/missing_rules.txt 또는 Temp/gradleOut/... 아래)에서 생성된 missing_rules.txt 파일을 검사하고 필요한 종속 항목 또는 규칙을 proguard-user.txt에 추가합니다. 유지 규칙 작성에 관한 자세한 내용은 유지할 코드 맞춤설정을 참고하세요.

서드 파티 플러그인과의 R8 전체 모드 호환성

AGP 8.0 이상 (Unity 6 이상)에서는 R8 전체 모드가 기본적으로 사용 설정되어 더 적극적인 최적화를 실행합니다. 리플렉션 문제로 인해 기존 Android 플러그인이 런타임에 실패하면 플러그인의 ProGuard 규칙을 업데이트하거나 R8을 호환성 모드로 되돌립니다.

  1. Publishing Settings(게시 설정) > Build(빌드)에서 Custom Gradle Properties Template(맞춤 Gradle 속성 템플릿)을 사용 설정합니다.
  2. Assets/Plugins/Android/gradleTemplate.properties을 열고 다음 속성을 추가합니다.
android.enableR8.fullMode=false