본문 바로가기

Android/Gradle

[Gradle] 빌드 변형 구성을 사용하여 하나의 앱을 나눠보자.

728x90

Developer 페이지를 확인해보면, 빌드 구성 개요를 토대로 단일 프로젝트에서 다양한 버전의 앱을 생성하기 위해 빌드 변형을 구성하는 방법과 관리하는 방법을 설명해주고 있다.

 

기본적으로 사용하고 있던 Debug와 Release 외에도 원하는 대로 커스텀하여 앱을 나누어서 사용이 가능한데,

이번에는 해당 방법에 대해 알아보고자 한다.


우선,

가장 간단한 방법으로 앱을 나눠보도록 하자.

 

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
}

 

Module 범위의 gradle에서 buildTypes를 확인해보면, 별 다른 작업을 하지 않은 경우 위처럼 작성되어있는 것을 확인할 수 있다.

 

기본적으로 우리는 Debug 모드와 Release 모드를 사용하고 있으며, Dveloper 사이트의 예제에서 볼 수 있듯이 Staging 타입까지 추가해 보도록 하자.

buildTypes안에 release가 선언되어있는 것 처럼 debug와 staging을 추가해보자.

 

debug {
    debuggable true
}

staging {
    initWith debug
}

 

이처럼 추가를 해주고 debug와 staging으로 빌드를 해보면 앱이 나누어지지 않고 하나의 앱으로 빌드되는 것을 확인할 수 있다.

staging에 사용한 initWith 속성을 사용하게 되면 다른 빌드 유형에서의 구성을 가져올 수 있는데, initWith debug로 선언하였으므로 debug의 빌드 속성을 가져온다는 의미가 된다.

 

 

여기서, 안드로이드 스튜디오에서 왼쪽 아래편을 보면 Build Variants를 확인할 수 있는데, 그곳에서 위의 사진처럼 빌드 타입에 따라 설정을 바꿔서 빌드를 진행할 수 있다.

 

앱을 나누기 위해서는 앱의 ID 값이 달라야 한다.

위에 선언한 빌드 구성을 보면, debug와 staging의 구성이 완전히 동일하기 때문에 타입만 바뀔 뿐 동일하게 하나의 app으로 빌드가 된다.

따라서, applicationIdSuffix 속성을 사용하여 앱 ID의 맨 뒤에 값을 추가하여 빌드 타입에 따라 다른 앱 ID를 가질 수 있도록 추가한다.

 

debug {
    debuggable true
    applicationIdSuffix '.dev'
}

staging {
    initWith debug
    applicationIdSuffix '.staging'
}

 

이렇게 빌드 구성을 하고 각각 빌드를 진행하게 되면 같은 이름을 가진 2개의 앱이 만들어지게 된다.

이름이 같기 때문에 어느것이 debug인지, staging인지 정확하게 판단할 수 없으므로 각 빌드 구성에 따라 앱 이름을 다르게 설정할 수 있도록 한다.

 

debug {
    debuggable true
    applicationIdSuffix '.dev'
    resValue "string", "app_name", "clean_Dev"
}

staging {
    initWith debug
    applicationIdSuffix '.staging'
    resValue "string", "app_name", "clean_Staging"
}

 

Manifest에서 앱의 이름을 설정할 수 있는데, 해당 속성 값을 빌드 타입에 따라서 다르게 저장하는 방식으로 사용하는 것이다.

 

android:label="@string/app_name"

 

이처럼 label 값을 app_name이라는 string을 사용하도록 하고, 각 빌드 속성에 app_name에 대한 string 값을 각각 다르게 설정을 해준다.

 

 

이처럼 속성 값을 추가한 후, 각각 빌드를 해보면 드디어 다른 이름의 두 가지 앱이 만들어지게 된다.

 

앱 아이콘도 빌드 타입에 따라 변경을 하고 싶은 경우,

 

manifestPlaceholders = [
        appIcon : "@drawable/ic_launcher_dev"
]

 

 

해당 속성 값과 사용할 아이콘의 경로를 넣어서 사용하면 된다.

 


BuildType으로 빌드 유형에 따라 위와 같이 앱을 나눌 수 있고,

Flavors를 사용하여 앱의 버전에 따라 앱을 나눌 수 있는 방법도 존재한다.

 

flavorDimensions "sample" , "test"
productFlavors {
    demo {
        dimension "sample"
        applicationIdSuffix '.demo'
    }

    pro {
        dimension "test"
        applicationIdSuffix '.pro'
    }
}

 

flavorDimensions는 각 Flavors에서 선언할 dimension의 List를 작성해 주면 되고, 각 flavors에서는 기준에 맞는 dimension을 넣어주면 된다.

여기서 Dimensions는 앱의 버전에 따라 앱을 나누고 관리하는 목적에 맞도록 사용하면 된다.

 

위의 코드를 보면 sample과 test를 선언하고 각각 flavor에 사용을 하였는데,

하나의 Dimensions만 사용하는 경우, flavorDimensions에만 선언하고 각 Flavors에서는 선언하지 않아도 상관없다.

 

 

위와 같이 설정을 하고 Variants를 확인해 보면, 이처럼 총 6가지의 빌드 타입이 나오게 된다.

즉, Flavor로 선언 한 유형 * Build Type의 유형의 수만큼 빌드가 가능해지는 것이다.

 

여기서도 마찬가지로 앱 ID에 따라서 앱이 구분되기 때문에, Flavor에서도 ApplicatonIdsuffix를 추가해 주었는데, flavor과 buildType 둘 다 suffix로 추가가 되는 경우

Application ID는 package.flavor.build 순서대로 만들어지게 된다.

 

즉,

 

com.android.application.demo.dev

 

이와 같은 형태로 만들어진다.

 

뿐만 아니라, productFlavors에서는 versionNameSuffix 속성도 지원을 해주는데, 이것을 사용하게 되면 1.0.0-demo와 같은 형태로 version Name이 만들어진다.

 

flavorDimensions "sample"
productFlavors {
    demo {
        applicationIdSuffix '.demo'
        versionNameSuffix '-demoo'

        versionCode 10000
        versionName "10.0.0"
    }

    pro {
        applicationIdSuffix '.pro'
        versionNameSuffix '-proo'

        versionCode 20000
        versionName "20.0.0"
    }
}

 

최종적으로 필자는 이와 같이 Flavors를 선언해 주었는데,

flavor에 따라서 versionCode, Name을 다르게 설정을 해주었고, suffix를 통해 확인이 가능하도록 만들어 주었다.

 

Log.d("BuildConfigCheck" , "BuildConfig.FLAVOR ? ${BuildConfig.FLAVOR}")
Log.d("BuildConfigCheck" , "BuildConfig.APPLICATION_ID ? ${BuildConfig.APPLICATION_ID}")
Log.d("BuildConfigCheck" , "BuildConfig.BUILD_TYPE ? ${BuildConfig.BUILD_TYPE}")
Log.d("BuildConfigCheck" , "BuildConfig.DEBUG ? ${BuildConfig.DEBUG}")

val packageData = packageManager.getPackageInfo(packageName, 0)
Log.d("BuildConfigCheck" , "packageData.versionName ? ${packageData.versionName}")
Log.d("BuildConfigCheck" , "packageData.versionCode ? ${packageData.versionCode}")

 

MainActivity에서 이와 같이 Log를 추가해주고 값을 확인해보도록 하자.

 

demo - debug

 

pro - staging

 

이런 식으로 하나의 프로젝트지만 확인할 수 있는 값이 다르게 출력되게 된다.

 

따라서, 필요에 따라 구분되는 값을 사용하여 BuildType이나 Flavor에 따라 다른 설정 값을 주거나 하여 필요시마다 값을 추가/변경하는 것이 아닌 미리 구현해 두고 손쉽게 변경을 가능하도록 구현할 수 있다.


필자는 지금까지 BuildType에 Suffix를 추가하여 디버그냐 릴리즈냐의 구분만 두고 사용을 했었고, 이것을 flavor를 나눠서 사용하고 있다고 생각하고 있었다.

 

해당 부분을 찾아보다가 지금까지 잘못 알고 사용하고 있었다는 것을 알게 되었고, 간단하게나마 사용하는 방법에 대해 정리를 해보았다.

 

Build Type이나 Flavor에 따라 분기 처리하여 코드를 작성하거나 하는 작업이 필요할까?라는 생각이 들긴 하지만, 정확하게 정해진 정책 같은 것이 있다면 미리 분기 처리를 해두고 작업을 하면 편할 것이라고 생각이 들었다.

 

간단하게 지금 떠오르는 것만 해도, QA에 전달하는 apk라던지, FE팀에서 로컬에 붙어서 테스트하기 위한 환경을 만들어 둔다던지 작업을 해두고 요청 시 간단하게 Variant만 변경하여 빌드해서 주면 될 것으로 보인다.

 

Developer 사이트를 확인해 보면 좀 더 확장해서 사용할 수 있는 설정들이 보이는데,

아직까지는 그 정도의 설정은 필요하다고 느끼지는 못하였고 지금 작성한 글만큼의 기본적인 정보만 알고 있어도 편하게 사용할 수 있을 것으로 보인다.

 

물론, 추후에 다른 옵션을 추가하여 사용하게 된다면 그에 따른 글을 한번 더 작성해 볼 예정이다.

 

해당 게시글에 사용한 예제는 Github에 올려두었다.

https://github.com/HeeGyeong/ModuleArchitecture

 

GitHub - HeeGyeong/ModuleArchitecture

Contribute to HeeGyeong/ModuleArchitecture development by creating an account on GitHub.

github.com

 

728x90