본문 바로가기

Android/Gradle

[Android] 공통된 Gradle Code를 빼내어 관리해보자.

728x90

이전 게시글

2022.02.08 - [Android/Gradle] - [Android] Multi Module에서 Gradle 공통화를 해보자.

 

에서도 공통된 Gradle Code를 빼내어서 공통화시킨다는 동일한 주제로 글을 작성했었다.

하지만, 해당 글에서 해결하지 못했던 부분에 대해 해결하게 되어서 글을 다시 작성하게 되었다.


우선,

이전 게시글에서는 중복된 코드가 들어간 common.gradle을 만들고,

Project 범위의 gradle에서 추가하는 방식을 사용했다.

 

이 과정에서 dependencies와 compileSdkVersion과 같이 빼내지 못하는 코드들이 있었고,

해당 코드들은 중복된 부분이 있다고 하더라도 각각의 module 범위의 gradle에 작성하여 사용하였다.

 

여기서,

Project 범위의 Gradle은 하위 모든 Module 범위의 Gradle에서 공통되게 적용되는 부분이기 때문에 당연히 해당 부분에 넣는 것 외에는 생각하지를 못했었다.

 

그 말은 즉,  

common.gradle을 Project 범위의 Gradle에 apply 하는 것이 아니라, 각 Module 범위의 gradle에 apply 하는 방식으로 적용을 해볼 수 있고, 결과적으로 해당 방법으로 해결이 가능했다는 것이다.

 

android {
    compileSdkVersion compileSdk_Version
    buildToolsVersion buildTools_Version

    defaultConfig {
        if (isApplicationPlugin) {
            applicationId "com.android.application"
        }
        minSdkVersion minSdk_Version
        targetSdkVersion targetSdk_Version
        versionCode versionCode
        versionName versionName

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    dataBinding {
        enabled = true
    }
    ...
}

 

common.gradle의 일부이다.

이전 게시글에서는 들어오지 못했던 compileSdkVersion, minSdkVersion 등의 값도 포함되어 있는 것을 확인할 수 있을 것이다.

 

그러면 이제 이것을 module 범위의 gradle에서 apply를 해보자.

 

apply from : '../common.gradle'

 

어디서 많이 본 형태일 것이다.

 

plugins {
    id("com.android.application")
    id 'kotlin-android'
    id 'kotlin-kapt'
}

 

보통 module 범위의 gradle 상단에 이와 같이 plugin이 설정되어 있는 모습을 보았을 것이다.

이것은 풀어서 쓰면,

 

apply plugin : 'com.android.application'
apply plugin : 'kotlin-android'
apply plugin : 'kotlin-kapt'

 

이와 같은 코드가 되는 것이다.

즉,

apply를 통해서 적용을 할 것인데 plugin은 플러그인을, from은 이하에 쓰는 경로에 있는 것을 적용하여 사용할 수 있다는 뜻이다.

 

여기서 '../common.gradle' 과 같이 사용하는 이유는 다음 프로젝트 구조를 보면 알 수 있을 것이다.

 

 

Module범위의 gradle의 위치와 Project범위의 gradle의 위치를 보면, 하나의 상위 폴더에 위치한 것을 볼 수 있다.

즉, ../ 를 사용하여 현재보다 하나 상위에 위치한 폴더를 명시적으로 표시해주고, 그곳에서 ~.gradle을 지정해주면 되는 것이다.

 

다시 코드로 돌아와서,

위에 사용된 android { .. }를 제외하고 dependencies에 관련한 gradle도 따로 빼주도록 하자.

 

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
    implementation 'androidx.core:core-ktx:1.7.0'
    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'com.google.android.material:material:1.5.0'

    //rxjava
    implementation "io.reactivex.rxjava2:rxjava:2.2.17"
    implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.8.1'
    implementation "io.reactivex.rxjava2:rxkotlin:2.3.0"
}
dependencies {
    // Truth
    testImplementation "com.google.truth:truth:$truthVersion"
    androidTestImplementation "com.google.truth:truth:$truthVersion"
    // Mockito
    testImplementation "org.mockito:mockito-core:$mockitoVersion"
    testImplementation "org.mockito:mockito-inline:$mockitoVersion"
    androidTestImplementation "org.mockito:mockito-android:$mockitoVersion"
    // Test Implement
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test:runner:1.4.0'
    androidTestImplementation 'androidx.test:rules:1.4.0'

    // Espresso
    androidTestImplementation "androidx.test.espresso:espresso-core:$espressoVersion"
    // Espresso-contrib for DatePicker, RecyclerView, Drawer actions, Accessibility checks, CountingIdlingResource
    androidTestImplementation("androidx.test.espresso:espresso-contrib:$espressoVersion") {
        exclude group: 'org.checkerframework', module: 'checker'
    }

    // Koin Test
    testImplementation "org.koin:koin-test:$koinVersion"
}

 

모든 module 범위의 gradle에 공통적으로 들어가 있는 부분 test에 관련된 dependencies를 모아둔 gradle 2개를 만들어 보았다.

 

 

그리고 해당 gradle을 적용하게 되면,

 

apply plugin : 'com.android.application'
apply plugin : 'kotlin-android'
apply plugin : 'kotlin-kapt'

android {
    defaultConfig {
        applicationId "com.android.application"
    }
}

apply from : '../android.gradle'
apply from : '../core-dependencies.gradle'
apply from : '../test-dependencies.gradle'

dependencies {
    // multiModule
    implementation project(':domain')
    implementation project(':data')
    implementation project(':core')
    implementation project(':moviesearch')
    implementation project(':move')

    // koin
    implementation("org.koin:koin-android:$koinVersion")
    implementation "org.koin:koin-androidx-viewmodel:$koinVersion"

    ...
}

 

와 같은 모습으로 module범위의 gradle을 만들 수 있을 것이다.

 

이때, ext로 선언한 버전 변수들이 작성되어있는 gradle도 별도로 생성한다면 관리하기에 편할 것으로 보인다.

 

ext {
    // build
    compileSdk_Version = 31
    targetSdk_Version = 31
    buildTools_Version = "30.0.3"
    minSdk_Version = 23
    versionCode = 1
    versionName = "1.0.0"

    ...
}

 

이런 식으로 선언한 gradle은 모든 Module범위의 gradle에서 사용되는 변수이기 때문에 해당 gradle은 Project범위의 gradle에 적용하도록 하자.

 

buildscript {
    repositories {
        google()
        mavenCentral()
    }

    apply from : 'ext-version.gradle'

    dependencies {
        classpath "com.android.tools.build:gradle:4.2.1"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

 

이와 같이 적용해주면 위에 작성한 것과 같이 변수들을 사용할 수 있을 것이다.


글을 쓰다 보니 코드 때문에 길어진 느낌이 있지만,

결과적으로 apply from : '../~.gradle' 이라는 코드를 추가하여 공통적으로 사용되는 코드를 빼내어 관리할 수 있다는 것이다.

 

해당 방식을 도입하여 gradle에서 공통된 코드를 제거하니 수정이 필요하다면 하나만 수정하면 되는 등 관리 및 관련한 오류가 줄어들어 편해질 것으로 보이고 코드량도 많이 줄어든 것 같다.

 

apply plugin : 'com.android.library' 
apply plugin : 'kotlin-android'

apply from : '../android.gradle'
apply from : '../core-dependencies.gradle'

 

극단적으로, 이와 같이 4줄만 사용하여 gradle을 표현할 수 있고 말이다.

 

어째서 모든 Module gradle에서 적용되는 코드가 들어가는 Project Gradle에 선언했을 때 적용이 되지 않는 것들이 있었는지에 대한 의문을 해결되지 않았지만,

다른 방법을 통해 원하는 바를 이룰 수 있어서 다행이라고 생각한다.

 

Gradle에 대한 내용은 아직 스터디를 많이 하지 않아서인지 많은 부분이 부족한 것으로 보인다.

따라서 나중에 기회가 된다면 gradle도 스터디를 진행하여 어떠한 이유로 저런 문제가 발생했는지, 아니면 어느 부분이 잘 못 되었던 것인지 알아봐야겠다.

 

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

https://github.com/HeeGyeong/ModuleArchitecture

 

GitHub - HeeGyeong/ModuleArchitecture

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

github.com

 

 

728x90