[BACKEND] 구글이 채택한 Kotlin DSL

Block Odyssey Tech Blog
10 min readJul 19, 2023

--

https://android-developers.googleblog.com/2023/04/kotlin-dsl-is-now-default-for-new-gradle-builds.html

최근 구글은 Kotlin DSL을 Android용 Gradle 빌드 파일의 기본 스크립트로 사용한다고 밝혔습니다. 그래서 Kotlin DSL가 무엇이고 어떠한 장점이 있는지 정리도 하면서 공유해보고자 합니다.

우선 간략하게 Kotlin이 무엇인지에 대해 설명 드리겠습니다.

[ Kotlin 탄생 배경 ]

Kotlin은 Java 개발자들이 많이 사용하고 있는 IntelliJ IDEA를 만든 JetBrains사에서 개발한 프로그래밍 언어입니다. 구글은 2017년에 Kotlin을 공식 안드로이드 개발 언어로 채택했는데, 이러한 사실 자체만으로도 영향력이 크다고 볼 수 있습니다.

Kotlin은 Java와 마찬가지로 JVM에서 동작 가능한 애플리케이션을 만들 수 있습니다. 또한 Kotlin Native는 안드로이드 개발뿐만 아니라 iOS, MacOS, Windows 등 다양한 플랫폼에서 개발이 가능합니다.

[ Kotlin 특징 ]

  • JetBrains사에서 공개한 프로그래밍 언어
  • JVM 기반 언어로 Java와 상호 호환 100% 지원
  • 안전한 null 처리로 인한 프로그램 중단 예방
  • 확장 함수, 연산자 오버 로딩
  • 객체지향 프로그래밍과 함수형 프로그래밍 모두 가능
  • 간결한 코드 작성 (세미콜론 생략 가능)

[ 안드로이드 공식 언어 Kotlin ]

초기 안드로이드는 자바 언어를 이용해서 애플리케이션을 만들 수 있었습니다. 본래 제임스 고슬링(James Gosling)이 만들어 썬 마이크로 시스템에서 관리되던 자바는 2009년 오라클에 인수되었습니다. 이때까지만 해도 자바 언어 자체는 무료였습니다.

하지만 오라클에서 인수한 이후 유료화 정책을 시작했습니다. 구글은 이미 자바 언어의 JDK를 이용해서 많은 프레임워크를 개발한 상태였고 오라클은 이에 대해서 천문학적인 금액을 제시했습니다.

결국 오라클과 구글은 자바 언어를 두고 소송을 벌이게 되었습니다.

현재 자바 언어는 역시 무료입니다. 자바 언어를 사용하기 위해서는 JDK가 필요하고 이를 통해 만든 코드를 실행하는 JVM이 필요합니다. 오라클은 JDK와 JVM의 특정 기능을 사용할 경우 라이센스 비용을 지불하도록 정책을 시행하고 있습니다.

구글은 분쟁을 피하기 위해서 새로운 가상머신인 DalvikVM을 만들거나 새로운 SDK를 제작하는 등 조치를 취해왔고 결국 자바 언어를 대신할 수 있는 Kotlin을 안드로이드 공식 언어로 채택했습니다.

Expedia, Flipboard, Pinterest, Square 등 이미 개발 완료된 프로덕션 앱에 활용하기 위해 Kotlin을 도입했습니다.

{ Kotlin DSL이란? }

Kotlin DSL을 알아보기에 앞서 DSL이란 무엇인지부터 알아봅시다.

DSL은 Domain Specific Language의 약자로 특정 도메인에 국한되어 사용하는 언어를 말합니다. 즉, 특정 도메인에 대한 목적으로 만들어진 언어를 DSL이라고 할 수 있습니다.

또한 DSL의 반대 개념으로는 GPL(General Purpose Language)이 있습니다. GPL은 다양한 문제 및 도메인을 다룰 수 있는 범용적인 언어로 우리가 일반적으로 사용하는 C, C++, Python, PHP, JAVA, Kotlin, Swift, JavaScript 등의 프로그래밍 언어들이 이에 해당합니다.

그렇다면 Kotlin DSL은 무엇일까요?

말 그대로 Kotlin DSL은 Kotlin으로 작성된 도메인 특화된 언어라고 말할 수 있습니다.

Kotlin DSL은 여러 영역에서 사용되며 정적 타입 검사, lambda 함수, Extension 함수 등과 같은 Kotlin 언어의 장점을 살려 직관적인 DSL을 구축할 수 있게 해줍니다.

{ 왜 Kotlin DSL인가? }

Kotlin DSL은 다른 DSL에 비해 특정 도메인이나 작업에 대해 표현력이 뛰어나고 유연한 코드를 작성할 수 있도록 도와줍니다.

이는 간단한 예시 코드를 통해서 확인 가능합니다.

// React Native (build.gradle)

buildscript {
ext {
buildToolsVersion = "29.0.2"
minSdkVersion = 26
compileSdkVersion = 29
targetSdkVersion = 29
googlePlayServicesAuthVersion = "16.0.1"
}

// ...

dependencies {
classpath 'com.android.tools.build:gradle:4.0.1';
classpath 'com.google.gms:google-services:4.3.4';
// ...
}

// ...

}
// Kotlin DSL

android {
defaultConfig {
buildToolsVersion("29.0.2")
minSdkVersion(26)
compileSdkVersion(29)
targetSdkVersion(29)
googlePlayServicesAuthVersion("16.0.1")
}

// ...

dependencies {
classpath("com.android.tools.build:gradle:4.0.1");
classpath("com.google.gms:google-services:4.3.4");
// ...
}

// ...

}

간단하게 예시를 통해 React Native에 대해 보여드렸는데, 드라미틱하게 변경된 부분은 없으나 문법을 통해서 좀 더 간결하게 코드를 작성 할 수 있습니다. 무엇보다 오타나 잘못된 Method 호출을 컴파일 단계에서 확인 가능하며, 코드의 안정성 및 런타임 오류를 줄여줍니다.

Kotlin DSL은 Android 뿐만 아니라 Gradle 빌드, 웹 개발, 테스트와 같은 다양한 도메인에서 활용될 수 있습니다.

{ Kotlin DSL 장점 }

위의 예시를 통해 언급했듯이 코드가 간결해지고 가독성이 높아지며, 컴파일 시점에 오류를 잡을 수 있고 다양한 IDE 지원과 객체 지향 및 함수형 프로그래밍을 모두 지원합니다.

이에따라 유연하고 확장 가능한 구조의 구성이 가능하며, 커스터마이징에 용이해 특정 도메인의 요구사항에 맞게 코드를 구성할 수 있습니다. 특히 lambda 함수, Extension 함수, Higher-order 함수, Null 안전성 등 다양한 특징과 기능을 제공합니다.

단점으로는 learning curve가 높고 이로 인해 초기 구현 및 설정 시 추가적인 작업들이 필요하며, 언어의 기능으로 인해 제한적인 범위내에서의 확장이 가능하다는 점이 있습니다.

[ Kotlin DSL 사용하기 ]

Gradle 스크립트에서 Kotlin DSL을 사용하는 방법은 간단합니다.

기존 *.gradle 파일을 *.gradle.kts로 변경하면 됩니다.

build.gradle -> build.gradle.kts

// Kotlin DSL에서는 기본적으로 문자열은 모두 따옴표 (" ") 로 묶어 표현한다.

{ buildSrc로 버전 관리 가능 }

buildSrc 디렉토리를 만들고 Versions, build.gradle.kts를 추가 합니다.

// build.gradle.kts

import org.gradle.kotlin.dsl.`kotlin-dsl`

plugins{
`kotlin-dsl`
}

repositories{
jcenter()
}

build.gradle.kts에서는 해당 Versions을 참고합니다.

// Versions.kt

object Versions {
//app level
const val gradle = "4.0.1"
const val kotlin = "1.4.0"

//libs
val coreKtx = "1.2.0"
val appcompat = "1.3.0-alpha01"
val constraintLayout = "2.0.0-beta8"

//test
val junit = "4.12"
val extJunit = "1.1.1"
val espresso = "3.2.0"
}

또한 AppDependencies.kt를 생성해서 의존성 아티팩트 단위로도 버전 관리가 가능합니다.

// AppDependencies.kt

import org.gradle.api.artifacts.dsl.DependencyHandler

object AppDependencies {
//std lib
val kotlinStdLib = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${Versions.kotlin}"
// ...

//android ui
private val appcompat = "androidx.appcompat:appcompat:${Versions.appcompat}"
private val coreKtx = "androidx.core:core-ktx:${Versions.coreKtx}"
// ...

//test libs
private val junit = "junit:junit:${Versions.junit}"
private val extJUnit = "androidx.test.ext:junit:${Versions.extJunit}"
// ...

val appLibraries = arrayListOf<String>().apply{
add(kotlinStdLib)
add(coreKtx)
add(appcompat)
add(constraintLayout)
}
// ...

//util functions for adding the different type dependencies from build.gradle file
fun DependencyHandler.kapt(list: List<String>) {
list.forEach{dependency->
add("kapt", dependency)
}
}
// ...

AppDependencies 참조를 통해 의존성을 관리할 수 있습니다.

이외에 build.gradle → build.gradle.kts, settings.gradle → settings.gradle.kts 변경 등 기존 Gradle 빌드에서 Kotlin DSL로의 마이그레이션이 가능합니다.

초기 설정 및 마이그레이션만 진행하면서 Kotlin DSL를 많이 접해보진 않았지만, 지금까지 언급한 장점과 Kotlin이 Gradle의 기본 DSL로 빌드 스크립트가 편집되고 작성되는 만큼,

변화가 빠른 Android 생태계를 따라가기 위해 지금부터라도 적극적으로 활용할 수 있도록 고민을 해봐야 할 시기인 것 같습니다.

--

--