땃쥐네

[gradle] buildSrc에 빌드 관련 변수들 모아두기 본문

e.t.c/gradle

[gradle] buildSrc에 빌드 관련 변수들 모아두기

ttasjwi 2024. 5. 16. 15:26

 

 

이번 글에서는 Gradle에서 변수를 buildSrc 폴더에 모아두고 빌드 스크립트에서 사용할 수 있도록 해보겠다.

 

환경

- 필자는 Kotlin 사용, JDK는 21을 사용하고 있으나 그 이전 버전을 사용해도 무방

- IntelliJ Ultimate (Community 버전을 사용해도 무방)

 

buildSrc 폴더 생성, build.gradle.kts 생성

plugins {
    `kotlin-dsl`
}

repositories {
    mavenCentral()
}

 

프로젝트 루트 경로에 buildSrc 폴더를 생성한다.

이곳에 build.gradle.kts 파일을 추가한 뒤 위 스크립트를 작성하자.

 

gradle 공식문서의 설명에 따르면, gradle은 buildSrc 디렉터리를 발견하면 이 코드를 자동으로 컴파일 및 테스트하고 빌드 스크립트의 클래스 패스에 넣는다고 한다.

 

이 때 설정에서 kotlin-dsl 플러그인을 추가하지 않으면 디렉터리 하위에 코틀린 파일을 작성하여 추가하더라도 빌드 스크립트의 코틀린 코드를 gradle에 통합할 수 없게 되므로 kotlin-dsl을 활성화해야한다.(플러그인을 지워서 gradle을 reload해보니 사용할 수 없었다...) 또, 이 플러그인을 끌어올 수 있도록 repositories로 mavenCentral을 지정했다.

 

설정을 추가하고 gralde 설정을 reload한다.

 

이제 이 아래에, src/main/kotlin 아래에 코틀린 코드를 작성하여 설정에 사용할 수 있다.


설정값 구성 예

개인적으로 사용하는 구성의 예고, 정답은 없다.

 

object ProjectProperties {

    const val GROUP_NAME = "com.ttasjwi"
    const val PROJECT_VERSION = "0.0.1"
    const val JAVA_VERSION = "21"
}

 

ProjectProperties 에는 프로젝트의 기본 메타데이터, 자바 버전을 명시하여 사용할 수 있게 한다.

 

enum class Plugins(val id: String, val version: String) {

    KOTLIN_JVM(
        id = "org.jetbrains.kotlin.jvm",
        version = "1.9.23"
    ),

    KOTLIN_SPRING(
        id = "org.jetbrains.kotlin.plugin.spring",
        version = "1.9.23"
    ),

    KOTLIN_KAPT(
        id = "org.jetbrains.kotlin.kapt",
        version = "1.9.23"
    ),

    KOTLIN_JPA(
        id = "org.jetbrains.kotlin.plugin.jpa",
        version = "1.9.23"
    ),

    SPRING_BOOT(
        id = "org.springframework.boot",
        version = "3.2.5"

    ),

    SPRING_DEPENDENCY_MANAGEMENT(
        id = "io.spring.dependency-management",
        version = "1.1.4"
    )
}

 

Plugins 에는 enum으로 플러그인의 id 및 플러그인 id 들을 모아 관리한다.

 

object Dependencies {

    const val KOTLIN_REFLECT = "org.jetbrains.kotlin:kotlin-reflect"
    const val KOTLIN_JACKSON = "com.fasterxml.jackson.module:jackson-module-kotlin"

    const val SPRING_BOOT_TEST = "org.springframework.boot:spring-boot-starter-test"
    const val SPRING_BOOT_DATA_JPA = "org.springframework.boot:spring-boot-starter-data-jpa"
    const val SPRING_BOOT_WEB = "org.springframework.boot:spring-boot-starter-web"

    const val MYSQL_DRIVER = "com.mysql:mysql-connector-j"

    const val QUERYDSL = "com.querydsl:querydsl-jpa:${DependencyVersions.QUERYDSL}:jakarta"
    const val QUERYDSL_PROCESSOR = "com.querydsl:querydsl-apt:${DependencyVersions.QUERYDSL}:jakarta"

    const val P6SPY = "com.github.gavlyukovskiy:p6spy-spring-boot-starter:${DependencyVersions.P6SPY}"
}
internal object DependencyVersions {
    const val QUERYDSL = "5.0.0"
    const val P6SPY = "1.9.1"
}

 

의존 라이브러리의 이름과 버전은 Dependencies 를 이용하여 관리한다.

대부분의 라이브러리는 스프링부트의 Dependency Management Plugin에 의해 버전이 관리되지만, 관리되지 않거나 특별한 이유로 버전을 직접 관리해야할 때는 DependencyVersions 쪽에 버전을 모아두고 관리한다.

 

이때 DependencyVersions는 internal object로 하여 외부에서 접근할 수 없게하고, 외부에서는 Dependencies에 기입된 의존성만 꺼내서 쓰도록 한다.

 


build.gradle.kts에 적용

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id("org.springframework.boot") version "3.2.5"
    id("io.spring.dependency-management") version "1.1.4"
    kotlin("jvm") version "1.9.23"
    kotlin("plugin.spring") version "1.9.23"
    kotlin("plugin.jpa") version "1.9.23"
}

group = "com.ttasjwi"
version = "0.0.1-SNAPSHOT"

java {
    sourceCompatibility = JavaVersion.VERSION_21
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-data-jpa")
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    runtimeOnly("com.mysql:mysql-connector-j")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs += "-Xjsr305=strict"
        jvmTarget = "21"
    }
}

tasks.withType<Test> {
    useJUnitPlatform()
}

 

우선, 기존의 루트 프로젝트 build.gradle.kts 파일이다.

아까 buildSrc에 모아서 선언한 변수를 사용해보도록 하자.

 

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id(Plugins.KOTLIN_JVM.id) version Plugins.KOTLIN_JVM.version
    id(Plugins.KOTLIN_SPRING.id) version Plugins.KOTLIN_SPRING.version
    id(Plugins.KOTLIN_JPA.id) version Plugins.KOTLIN_JPA.version

    id(Plugins.SPRING_BOOT.id) version Plugins.SPRING_BOOT.version
    id(Plugins.SPRING_DEPENDENCY_MANAGEMENT.id) version Plugins.SPRING_DEPENDENCY_MANAGEMENT.version
}

group = ProjectProperties.GROUP_NAME
version = ProjectProperties.PROJECT_VERSION

java {
    sourceCompatibility = JavaVersion.valueOf("VERSION_${ProjectProperties.JAVA_VERSION}")
}

repositories {
    mavenCentral()
}

dependencies {
    implementation(Dependencies.SPRING_BOOT_DATA_JPA)
    implementation(Dependencies.SPRING_BOOT_WEB)
    implementation(Dependencies.KOTLIN_JACKSON)
    implementation(Dependencies.KOTLIN_REFLECT)
    runtimeOnly(Dependencies.MYSQL_DRIVER)
    testImplementation(Dependencies.SPRING_BOOT_TEST)
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs += "-Xjsr305=strict"
        jvmTarget = ProjectProperties.JAVA_VERSION
    }
}

tasks.withType<Test> {
    useJUnitPlatform()
}

 

buildSrc 아래에 등록한 enum, object를 사용하여 build.gradle에서 사용할 수 있도록 해봤다.


뭔 장점이?

 

여기까지 놓고보면 어차피 build.gradle 파일 하나에서만 쓰니까 별 의미 없는 행위로 보일 수 있다.

하지만 추후 프로젝트 규모가 커지고 복잡해지면서 프로젝트를 멀티모듈로 분리해나간다거나 할 경우 빛을 발하게 되지 않을까 생각해본다.

 

새로운 모듈을 설정할 때, 각 모듈별로 똑같은 의존성을 중복 기입해야하는 일이 생길 수 있는데, 하드코딩으로 똑같은 값 을 적지 않고 buildSrc 아래에 등록한 변수를 통해 등록할 수 있기 때문에 휴먼 에러(사람의 실수)를 줄일 수 있고, 버전 관리 등을 한 모듈에 응집시켜둘 수 있는 장점이 있다.

 

 

개인적으로는 방식으로 자주 쓰는 의존 라이브러리 이름, 버전 등을 buildSrc에 모아두고 이후 프로젝트 새로 만들 때마다 재사용, 변형하기도 좋다고 생각한다.


 

Comments