봄날은 갔다. 이제 그 정신으로 공부하자

MultiDex 1편 - 64K 제한과 Multidex 설정 방법 본문

Android jetpack

MultiDex 1편 - 64K 제한과 Multidex 설정 방법

길재의 그 정신으로 공부하자 2021. 1. 25. 11:11

android는 앱 및 앱이 참조하는 라이브러리에서 메서드가 65,536개를 초과하면 앱이 android 빌드 아키텍처의 제한에 도달했음을 알리는 아래와 같은 빌드 오류를 발생시킵니다.

trouble writing output:
Too many field references: 131000; max is 65536.
You may try using --multi-dex option.

 

65536(64K)이라는 숫자는 단일 DEX(Dalvik Executable) 바이트 코드 파일 내에서 코드가 호출할 수 있는 참조의 총 갯수를 나타냅니다. 

즉, 이 에러는 Dalvik이 바이크 코드내에서 호출할 수 있는 참조의 총 갯수를 초과했기 때문에 빌드 에러를 리턴하는 것 입니다.

 

이번 글에서는 Muldidex 사용하여 65536(64K) 함수 호출 제한을 넘는 방법을 설명합니다.

Mukltidex를 사용하면 앱에서 다중 DEX 파일을 빌드하고 읽을 수 있습니다.

 

64K 참조 제한

android 앱(APK) 파일에는 Dalvik Executable(DEX) 파일 형식의 실행 가능한 바이트 코드 파일이 포함되며, DEX 파일에는 앱을 실행하기 위해 사용되는 컴파일된 코드가 포함됩니다. 

Dalvik Executable 사양은 단일 DEX 파일 내에서 참조될 수 있는 메서드의 총 개수를 65,536으로 제한하며 여기에는 Android 프레임워크 메서드, 라이브러리 메서드, 자체 코드에 있는 메서드가 포함됩니다. 

65,536은 64 X 1024이므로 이 제한을 '64K 참조 제한'이라고 부릅니다.

 

초창기 Android 소스도 64K 제한을 넘지 않았으므로 64K 제한은 아무런 문제가 되지 않는 것처럼 느껴졌습니다.

하지만 android 시간이 지나면서 앱들이 개발 효율성 증대를 위해 앱에 여러개의 라이브러리를 연동하게 되고 이제 왠만한 앱들은 64K 제한에 걸리는 문제가 발생하게 됩니다.

 

구글에서도 이러한 문제를 인식하고 있었고 이를 해결하기 위해 발빠르게 대처해 2014년 10월 16일 발표한 Android 5.0(API 레벨 21 / 롤리팝) 이상부터는 Dalvik이 아닌 ART 런타임을 사용해 여러개의 DEX 파일을 로드하는 것을 지원하도록 하였습니다.

 

그러므로 개발하는 앱의 minSdkVersion이 21 이상 이라면 ART 런타임에 의해 멀티 DEX가 기본으로 지원되므로 번거롭게 Multidex를 사용하지 않아도 괜찮습니다.

하지만 개발하는 앱의 minSdkVersion이 21 미만 이라면 조금 번거롭더라도 Multidex를 사용하는 것이 좋습니다.

 

앱의 버전별 사용자 확인 방법

build.gradle파일을 열어서 minSdkVersion을 21로 수정한다고 모든 문제가 해결되는 것은 아닙니다. ㅠ_ㅠ

 

아직 마켓에 배포를 확인하지 않은 앱이라면

버전별 사용자를 확인하고 고려하여 적절한 범위(?)에서 최대한 많은 사용자가 포함되도록 하는 것이 좋습니다.

예전에 android 개발자 페이지에서 버전별 사용자를 알려주었었는데 어느 순간부터 해당 페이지가 사라졌습니다.

대신 android studio에서 새 프로젝트 생성을 누르고 앱 생성 시 아래와 같이 MIN SDK 버전별 사용자 수를 알려줍니다.

방법을 사용해 개발하는 앱의 지원할 있는 대략적인 device 점유율을 있습니다.

 

마켓에 배포된 앱이라면

현재 앱 사용자의 버전별 점유율을 확인해야 합니다.

만약 minSdkVersion을 올려버리면 minSdkVersion 버전에서 제외된 사용자는 신규로 등록한 앱이 아닌 이전에 마켓에 등록한 앱을 계속 다운받게 되기 때문 입니다.

그러므로 마켓에 배포된 앱은 minSdkVersion을 올리는 것에 신중을 기해야 합니다. minSdkVersion 버전을 올린 후 새로운 기능을 추가하거나 서버 API를 새로운 버전의 앱에 맞게 변경하게 되면 대참사가 발생하기 때문 입니다.

 

minSdkVersion 버전은 앱을 사용하는 사용자도 고려해야 하기 때문에 신중을 기해야 합니다.

현재 앱의 버전별 사용자를 확인하는 방법은 여러가지 방법이 있겠지만 앱에 Analytics가 적용되었다면 Firebase의 Analytics를 사용하여 버전별 사용자 파악이 가능합니다. 우선 Firebase의 Analytics에 접속하여 분석 허브를 선택한 후 측정 기준에 OS 버전을 선택하면 앱의 버전별 사용자 수를 파악할 수 있습니다.

앱 특성에 따라 사용자의 재접속 기간이 다르겠지만 분석 기간은 최소 30일 정도를 설정하는 것을 추천 드립니다.

 

Android 5.0 미만에서 멀티 DEX 지원

위에서 언급하였지만 리마인드 차원에서 다시 설명하자면 Android 5.0(API 수준 21) 이전의 플랫폼 버전에서는 앱 코드 실행을 위해 Dalvik 런타임을 사용합니다. 

기본적으로 Dalvik에서는 APK당 하나의 classes.dex 바이트 코드 파일로 앱을 제한합니다. 

 

종속성 추가

이 제한을 해결하기 위해 멀티덱스 라이브러리를 모듈 수준 build.gradle 파일에 추가할 수 있습니다.

android {
    defaultConfig {
        ...
        minSdkVersion 15
        targetSdkVersion 28
        multiDexEnabled true
    }
    ...
}

dependencies {
  implementation "androidx.multidex:multidex:2.0.1"
}

 

만약 AndroidX를 사용하지 않는다면 다음의 지원 중단된 지원 라이브러리 종속 항목을 대신 추가합니다.

dependencies {
  implementation 'com.android.support:multidex:1.0.3'
}

 

앱에 Multidex 설정

앱에 Multidex를 설정하는 방법은 아래와 같이 세가지 방법이 있습니다.

 

Application 클래스를 재정의하지 않는 경우

아래와 같이 manifest.xml 파일을 수정해줍니다.

<?xml version="1.0" encoding="utf-8"?>

    package="com.example.myapp">
    <application
            android:name="androidx.multidex.MultiDexApplication" >
        ...
    </application>
</manifest>

 

Application 클래스를 재정의하는 경우

아래와 같이 MultiDexApplication을 상속 받도록해줍니다.

class MyApplication : MultiDexApplication() {.
    ..
}

 

Application 클래스를 재정의하지만 MultiDexApplication을 상속 받을 수 없는 경우

아래와 같이 attachBaseContext() 함수를 재정의하여 MultiDex.install(this)를 호출하여 멀티덱스를 사용 설정할 수 있습니다.

class MyApplication : SomeOtherApplication() {
    override fun attachBaseContext(base: Context) {
        super.attachBaseContext(base)
        MultiDex.install(this)
    }
}

 

이제 앱을 빌드할 때 Android 빌드 도구는 기본 DEX 파일(classes.dex)과 지원하는 DEX 파일(classes2.dexclasses3.dex 등)을 필요에 따라 구성합니다.  그 후 빌드 시스템이 모든 DEX 파일을 APK로 패키징합니다.

런타임 시, 멀티덱스 API는 특수 클래스 로더를 사용하여 메서드에 사용 가능한 모든 DEX 파일을 검색합니다.

 

마무리

다음 글에서는 멀티덱스 라이브러리의 제한사항과 개발빌드에서 Multidex 최적화하는 방법에 대해 설명하도록 하겠습니다.

Comments