Gradle 멀티 프로젝트에서 컨벤션 플러그인으로 의존성 관리
Multi-project Structure
빠른 이해를 위해 아래처럼 구성해 보았습니다.
예제 소스는 Github에 올려두었습니다.
├── gradle │ ├── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ └── libs.versions.toml // 1. 버전 카탈로그 │ ├── build-logic // 2. 빌드 플러그인을 위한 프로젝트 │ ├── src │ │ └── main │ │ └── kotlin │ │ ├── io.github.ijmo.kotlin-application-conventions.gradle.kts │ │ ├── io.github.ijmo.kotlin-common-conventions.gradle.kts │ │ └── io.github.ijmo.kotlin-library-conventions.gradle.kts │ ├── build.gradle.kts │ └── settings.gradle.kts │ ├── app // 3. 서브 프로젝트 │ └── build.gradle.kts ├── library // 3. 서브 프로젝트 │ └── build.gradle.kts │ ├── gradlew ├── gradlew.bat └── settings.gradle.kts // 4. 빌드 플러그인을 include
1. 버전 카탈로그
├── gradle │ ├── wrapper │ │ └── ... │ └── libs.versions.toml ...
버전을 관리하기 위한
libs.versions.toml
을 추가했습니다.의존 라이브러리 목록도 여기서 관리를 할 수 있으나, 저는 버전만 넣어보았습니다.
[versions]
kotlin = "1.9.20"
springBoot = "3.2.0"
springCloud = "2023.0.0"
2. 빌드 플러그인을 위한 프로젝트
├── build-logic │ ├── src │ │ └── main │ │ └── kotlin │ │ ├── io.github.ijmo.kotlin-application-conventions.gradle.kts │ │ ├── io.github.ijmo.kotlin-common-conventions.gradle.kts │ │ └── io.github.ijmo.kotlin-library-conventions.gradle.kts │ ├── build.gradle.kts │ └── settings.gradle.kts ...
libs.versions.toml
을 읽어오도록 합니다. settings 파일 기준으로 상대경로를 입력했습니다.
dependencyResolutionManagement {
versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml"))
}
}
}
rootProject.name = "my-example-app-build-logic"
만들려는 플러그인에서 외부 플러그인을 사용하고 싶다면 빌드 스크립트에서 의존성을 추가해주어야 합니다. Spring Boot을 사용하기 위해
gradlePluginPortal
에 있는spring-boot-gradle-plugin
을 추가해 주었습니다.libs.versions.toml
에서 지정한 버전을 가져왔습니다.
plugins {
`kotlin-dsl`
}
repositories {
gradlePluginPortal()
}
val versionCatalog = extensions.getByType<VersionCatalogsExtension>().named("libs")
dependencies {
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:${versionCatalog.findVersion("kotlin").get()}")
implementation("org.springframework.boot:spring-boot-gradle-plugin:${versionCatalog.findVersion("springBoot").get()}")
}
gradle init
을 통해 프로젝트를 만들면 3가지 모델의 플러그인을 스캐폴딩 해줍니다. 파일 이름에서도 알 수 있듯이 프로젝트 공통으로 쓰이는 'common', 앱에서 쓰기 위한 'application', 라이브러리에서 쓰기 위한 'library' 로 나누어진 구조입니다.서브 프로젝트의 유형이 한 종류(앱 또는 라이브러리)이거나 모든 프로젝트가 같은 의존성을 가진다면 굳이 여러 파일로 나눌 필요없이 한 파일에 다 집어넣으면 되겠습니다.
파일이름은 제 기준으로 지었으니 적절하게 바꿔서 쓰시면 되겠습니다.
plugins {
id("org.jetbrains.kotlin.jvm")
}
repositories {
mavenCentral()
}
dependencies {
constraints {
implementation("org.apache.commons:commons-text:1.10.0")
}
}
testing {
suites {
val test by getting(JvmTestSuite::class) {
useJUnitJupiter("5.9.3")
}
}
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}
빌드 스크립트에서 의존성을 추가했었던 Spring Boot 플러그인을
plugins {}
안에서apply
해주었습니다.Spring BOM(Bill of Material)을 적용하기 위해
implementation(platform())
을 사용했습니다.여기서
dependencies {}
에 추가한 라이브러리는resolve
되어 classpath에 추가됩니다. 서브 프로젝트에서 사용하려면 해당 프로젝트의 빌드 스크립트에서dependencies {}
에 추가해야 합니다.
plugins {
id("io.github.ijmo.kotlin-common-conventions")
id("org.springframework.boot")
application
}
val versionCatalog: VersionCatalog = extensions.getByType<VersionCatalogsExtension>().named("libs")
val springBootVersion = versionCatalog.findVersion("springBoot").get()
val springCloudVersion = versionCatalog.findVersion("springCloud").get()
dependencies {
implementation(platform("org.springframework.boot:spring-boot-dependencies:$springBootVersion"))
implementation(platform("org.springframework.cloud:spring-cloud-dependencies:$springCloudVersion"))
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("io.projectreactor.kotlin:reactor-kotlin-extensions:1.2.2")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor:1.7.3")
implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("org.springframework.boot:spring-boot-starter-webflux")
testImplementation("io.projectreactor:reactor-test:3.6.0")
}
라이브러리 프로젝트를 위한 플러그인 입니다.
필요한 라이브러리를
dependencies {}
에 추가해주세요.
plugins {
id("io.github.ijmo.kotlin-common-conventions")
`java-library`
}
3. 빌드 플러그인을 include
├── settings.gradle.kts ...
만든 플러그인을
pluginManagement {}
을 통해 포함시켜 줍니다.서브 프로젝트도
include()
해줍니다.
pluginManagement {
includeBuild("build-logic")
}
rootProject.name = "my-example-app"
include("app", "library")
4. 서브 프로젝트
├── app │ └── build.gradle.kts ├── library │ └── build.gradle.kts ...
classpath에 추가된 패키지(라이브러리) 중에 각 프로젝트에 사용할 패키지를 빌드 스크립트에 추가합니다.
plugins {
id("io.github.ijmo.kotlin-application-conventions")
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("org.springframework.boot:spring-boot-starter-webflux")
testImplementation("io.projectreactor:reactor-test")
implementation(project(":library"))
}