[Android] Refactoring: Gradle을 KTS로 마이그레이션 하기

ByWindow·2022년 10월 14일
1

Android

목록 보기
11/14
post-thumbnail
post-custom-banner

💡 Kotlin-dsl?


skydoves님의 Pokedex 프로젝트를 공부하던 중, Version Catalog라는 방법에 대해 알게 되었습니다. 저는 지금까지 Groovy 기반의 gradle 파일들로 라이브러리를 선언하고, project 단위의 gradle에서 각 라이브러리의 버전을 관리했었는데 Groovy 기반이 아니라 Kotlin 파일로 gradle을 관리할 수 있다는 것을 알게 되었습니다.
Android Developer 공식사이트에서도 Groovy -> KTS로 migration하는 방법을 소개하고 있습니다.
그렇게 더 공부하다가 알게 된 것이 Kotlin DSL입니다.

DSL?

Myungpyo Shim님의 포스팅을 참고했습니다.
DSL은 Domain Specific Language의 약자이며, 반대 의미로는 GPL Global Purpose Language가 있습니다.
특정 도메인에 국한되어 사용되는 언어라는 의미이며, Kotlin이 이런 DSL에 해당합니다. 앱을 개발하면서 프레임워크나 라이브러리를 사용할 때, 제공되는 언어를 사용하게 되는데 이때의 언어가 DSL입니다.

Groovy vs KTS

그럼 기존의 방식이 아니라 kts 파일로 gradle을 관리할 때의 장점은 무엇일까요?
사용해 본 후 제가 느낀 편한 점들입니다.

  • kotlin 파일이기 때문에 자동완성이 가능한 점
  • 여러 모듈에서 동일하게 필요한 라이브러리들이 있는데, 그런 것들을 for문으로 한번에 추가할 수 있다는 점
  • gradle에서 Kotlin 문법들을 사용할 수 있다는 점
  • 라이브러리 버전 뿐만 아니라 EndPoint가 변경되었을 때도 수정이 쉽다는 점

✨ 적용방법


개발환경
Android Studio : Dolphin
Gradle JDK : Android Strudio default JDK - 11.0.13
Gradle Plugin : 7.5.1

  1. 좌측 프로젝트 패널을 Project Files로 변경합니다.
  2. 안드로이드 스튜디오에서 File > New > Directory로 프로젝트 root에 buildSrc 폴더를 생성합니다.
  3. 해당 폴더를 우클릭 후, New > File로 build.gradle.kts 파일을 생성합니다.
  4. build.gradle.kts 파일 안에 아래와 같이 코드를 입력해줍니다.
import org.gradle.kotlin.dsl.`kotlin-dsl`

plugins {
    `kotlin-dsl`
}

repositories {
    mavenCentral()
}
  1. 폴더 안에 새로운 directory를 생성하는데, 디렉토리명은 src/main/java 로 설정합니다.

위의 단계를 마친 후, 프로젝트 패널을 Android로 변경하면 아래와 같은 모습이 됩니다.

  1. 다시 Project Files로 패널을 바꾸어 준 후, 5번에서 생성한 java 폴더 안에 자신의 앱 패키지와 동일하게 폴더를 생성해주고 Configuration object와 Dependencies kotlin파일을 생성합니다. (아래 그림을 참고해주세요.)
  2. Configuration 파일에는 app 단위 gradle의 android 내에 필요한 config 들을 정의합니다.

    꼭 위의 코드를 따라서 작성할 필요없이 현재 사용하시는 프로젝트의 SDK 설정대로 세팅해주시면 됩니다.
  3. Dependencies 파일에는 사용할 플러그인, 라이브러리와 각각의 버전을 작성해줍니다.
package com.idiot.e_state_twin_android

object Versions {
  ...
  const val kotlin = "1.7.10"
  const val agp = "7.2.1"
  const val ksp = "1.7.10-1.0.6"
  const val hilt = "2.42"
  const val jvmTarget = "1.8"
  const val material = "1.8.0-alpha01"
  const val sceneView = "0.9.0"
  const val appcompat = "1.5.0"
  const val androidxCore = "1.8.0"
  const val androidxFragment = "1.5.0"
  const val constraintLayout = "2.1.4"
  const val androidxNavigation = "2.5.0"
  const val androidxLifecycle = "2.5.0"
  const val androidxWork = "2.7.1"
  const val androidxRoom = "2.4.3"
  const val datastore = "1.0.0"
  ...
}

object Libraries {
  ...
  const val agp = "com.android.tools.build:gradle:${Versions.agp}"
  const val ksp = "com.google.devtools.ksp:symbol-processing-api:${Versions.ksp}"
  const val kotlin_gradlePlugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlin}"
  const val kotlin_serialization = "org.jetbrains.kotlin:kotlin-serialization:${Versions.kotlin}"
  const val navigation_safeargsPlugin = "androidx.navigation:navigation-safe-args-gradle-plugin:${Versions.androidxNavigation}"
  const val hilt_plugin = "com.google.dagger:hilt-android-gradle-plugin:${Versions.hilt}"
  const val material = "com.google.android.material:material:${Versions.material}"
  const val gson = "com.google.code.gson"
  const val sceneview = "io.github.sceneview:arsceneview:${Versions.sceneView}"
  const val google_service_auth = "com.google.android.gms:play-services-auth:${Versions.gms}"
  const val hilt_android = "com.google.dagger:hilt-android:${Versions.hilt}"
  const val hilt_compiler = "com.google.dagger:hilt-android-compiler:${Versions.hilt}"
  const val androidx_core = "androidx.core:core-ktx:${Versions.androidxCore}"
  ...
  }

위의 과정까지 마무리하셨다면 이제 gradle 파일에 방금까지 작성한 소스를 사용하시면 됩니다.

  1. 각 모듈들의 build.gradle 파일의 이름을 build.gradle.kts로 변경합니다.
  2. 이제 KTS 문법을 사용하여 gradle 파일을 수정해줍니다.
import com.idiot.e_state_twin_android.Libraries
import com.idiot.e_state_twin_android.Configuration

plugins {
  id("com.android.application")
  id("kotlin-android")
  id("kotlin-parcelize")
  id("androidx.navigation.safeargs.kotlin")
  id("kotlin-kapt")
  id("dagger.hilt.android.plugin")
}

android {
  compileSdk = Configuration.compileSdk
  defaultConfig {
    applicationId = "com.idiot.e_state_twin_android"
    minSdk = Configuration.minSdk
    targetSdk = Configuration.targetSdk
    versionCode = Configuration.versionCode
    versionName = Configuration.versionName

    testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

  }

  compileOptions {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
  }

  buildFeatures {
    dataBinding = true
    viewBinding = true
  }

  buildTypes {
    getByName("debug") {
      sourceSets {
        getByName("main") {
          java.srcDir(File("build/generated/ksp/debug/kotlin"))
        }
      }
    }

    getByName("release") {
      isMinifyEnabled = false
      proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")

      sourceSets {
        getByName("main") {
          java.srcDir(File("build/generated/ksp/release/kotlin"))
        }
      }
    }
  }

  kotlinOptions {
    jvmTarget = "1.8"
  }
}

dependencies {
  implementation(Libraries.hilt_android)
  kapt(Libraries.hilt_compiler)

  implementation(Libraries.timber)
  implementation(project(":utils"))
  // FEATURE
  implementation(project(":login"))

  testImplementation(Libraries.junit)

  androidTestImplementation(Libraries.androidx_junit)
  androidTestImplementation(Libraries.androidx_espresso)
}

👀 결론


  • 멀티모듈로 변경한 후, 여러 모듈에서 라이브러리를 관리하는 것이 번거러웠습니다. 하지만 KTS를 적용한 후 buildSrc 한 곳에서 모든 모듈에 적용 중인 라이브러리나 플러그인을 관리함으로써 기존의 작업을 많이 단축시킬 수 있었습니다.
  • gradle에서도 자동완성 기능과 import를 사용할 수 있어서 엄청 편합니다.
profile
step by step...my devlog
post-custom-banner

0개의 댓글