Gradle ์นํธ์ํธ ํต์ฌ ๋ช
๋ น์ด ๋ฐ ์ค์ ๊ฐ์ด๋
Gradle Wrapper(gradlew) ๋ช
๋ น์ด, Kotlin/Groovy DSL, ์์กด์ฑ ์ค์ฝํ, ๋ฉํฐ ๋ชจ๋ ๋ฐ ์ฑ๋ฅ ์ต์ ํ ๋ ํผ๋ฐ์ค
## 1. Gradle Wrapper (gradlew) ํต์ฌ ๋ช
๋ น์ด
```bash
# 1. ๋น๋ ๋ฐ ํด๋ฆฐ
./gradlew build # ํ๋ก์ ํธ ์ ์ฒด ์ปดํ์ผ, ํ
์คํธ ๋ฐ JAR ์ํฐํฉํธ ๋น๋
./gradlew clean build # build/ ๋๋ ํ ๋ฆฌ ์์ ์ญ์ ํ ์๋ก ๋น๋
./gradlew build -x test # ํ
์คํธ ์คํ์ ๊ฑด๋๋ฐ๊ณ ๋น ๋ฅธ ๋น๋ ์ํ
# 2. ์คํ ๋ฐ ์ปดํ์ผ๋ง ์ํ
./gradlew bootRun # Spring Boot ์ ํ๋ฆฌ์ผ์ด์
๋ก์ปฌ ์คํ
./gradlew classes testClasses # ์คํ/ํจํค์ง ์์ด ์์ค ์ฝ๋ ์ปดํ์ผ๋ง ๊ฒ์ฆ
# 3. ๋ฐ๋ชฌ(Daemon) ํ๋ก์ธ์ค ๊ด๋ฆฌ
./gradlew --status # ์คํ ์ค์ธ Gradle ๋ฐ๋ชฌ ์ํ ๋ฐ PID ํ์ธ
./gradlew --stop # ๋ฐฑ๊ทธ๋ผ์ด๋์ ์์ฃผํ๋ ๋ชจ๋ Gradle ๋ฐ๋ชฌ ์ข
๋ฃ (๋ฉ๋ชจ๋ฆฌ ์ ๋ฆฌ)
# 4. ์ฑ๋ฅ & ํธ๋ฌ๋ธ์ํ
์ต์
./gradlew build --parallel # ๋ฉํฐ ๋ชจ๋ ๋ณ๋ ฌ ๋น๋๋ก ๋น๋ ์๊ฐ ๋ํญ ๋จ์ถ
./gradlew build --refresh-dependencies # ์๊ฒฉ ์ ์ฅ์ ์์กด์ฑ ์บ์ ๊ฐ์ ์ฌ๋ค์ด๋ก๋
./gradlew build --info --stacktrace # ์๋ฌ ๋ฐ์ ์ ์์ธ ์คํํธ๋ ์ด์ค ์ถ๋ ฅ
```
## 2. ์์กด์ฑ ์ค์ฝํ (Dependency Configurations)
```groovy
dependencies {
// 1. implementation: ๋ด๋ถ ๊ตฌํ์ฉ (์ปดํ์ผ ํด๋์คํจ์ค ์ ํ X, ๋น๋ ์๋ ๋ฐ ์บก์ํ ์ต์ )
implementation 'org.springframework.boot:spring-boot-starter-web'
// 2. api: ์ธ๋ถ ๋
ธ์ถ์ฉ (์ด ํ๋ก์ ํธ๋ฅผ ์ฐธ์กฐํ๋ ๋ค๋ฅธ ๋ชจ๋๋ก ์์กด์ฑ ์ ์ด ์ ํ)
api 'com.google.guava:guava:33.0.0-jre'
// 3. compileOnly: ์ปดํ์ผ ์์๋ง ํ์, ์ต์ข
๋ฐํ์/๋ฐฐํฌ JAR์์๋ ์ ์ธ
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok' // ์ด๋
ธํ
์ด์
ํ๋ก์ธ์ ๋ฑ๋ก
// 4. runtimeOnly: ์ปดํ์ผ ์์ ์๋ ๋ถํ์ํ๊ณ ๋ฐํ์์๋ง ๋์ ๋ก๋ (DB ๋๋ผ์ด๋ฒ ๋ฑ)
runtimeOnly 'com.mysql:mysql-connector-j'
runtimeOnly 'com.h2database:h2'
// 5. testImplementation: ํ
์คํธ ์ฝ๋(src/test) ์ปดํ์ผ ๋ฐ ์คํ ์์๋ง ์ฌ์ฉ
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.2'
}
```
## 3. Kotlin DSL vs Groovy DSL ๋ฌธ๋ฒ ๋น๊ต
```kotlin
// ==================== Kotlin DSL (build.gradle.kts) ====================
plugins {
java
id("org.springframework.boot") version "3.2.4"
id("io.spring.dependency-management") version "1.1.4"
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(21))
}
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
testImplementation(kotlin("test"))
}
```
```groovy
// ==================== Groovy DSL (build.gradle) ====================
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.4'
id 'io.spring.dependency-management' version '1.1.4'
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
}
```
## 4. ์์กด์ฑ ๋ถ์ & ์ถฉ๋ ํด๊ฒฐ (Dependency Insight)
```bash
# 1. ํ๋ก์ ํธ ์ ์ฒด ์์กด์ฑ ํธ๋ฆฌ ์ถ๋ ฅ
./gradlew dependencies
# 2. ํน์ ๋น๋ ๊ตฌ์ฑ์ ์์กด์ฑ๋ง ํํฐ๋งํ์ฌ ์ถ๋ ฅ
./gradlew dependencies --configuration compileClasspath
./gradlew dependencies --configuration runtimeClasspath
# 3. ํน์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ ํฌํจ๋์๋์ง, ์ถฉ๋ ๋ฐ ๋ฒ์ ์ ํ ๊ฒฝ๋ก ์ถ์
./gradlew dependencyInsight --dependency log4j-core
./gradlew dependencyInsight --dependency jackson-databind --configuration compileClasspath
```
```groovy
// 4. ํน์ ์ ์ด ์์กด์ฑ(Transitive Dependency) ๊ฐ์ ์ ์ธ(Exclude)
dependencies {
implementation('org.springframework.boot:spring-boot-starter-web') {
// ๋ด์ฅ Tomcat์ ์ ์ธํ๊ณ ๋ค๋ฅธ WAS(Undertow ๋ฑ)๋ฅผ ์ธ ๋
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
}
}
```
## 5. ํ์คํฌ(Task) ๊ด๋ฆฌ & ์ปค์คํ
ํ์คํฌ ์์ฑ
```bash
# ์คํ ๊ฐ๋ฅํ ๋ชจ๋ ํ์คํฌ ๋ชฉ๋ก ๋ฐ ์ค๋ช
ํ์ธ
./gradlew tasks
./gradlew tasks --all # ํ์ ์ธ๋ถ ํ์คํฌ๊น์ง ๋ชจ๋ ๋์ด
./gradlew help --task build # ํน์ ํ์คํฌ ์์ธ ๋์๋ง
```
```kotlin
// Kotlin DSL (build.gradle.kts) ์ปค์คํ
ํ์คํฌ ๋ฑ๋ก
tasks.register("printProjectInfo") {
group = "custom"
description = "ํ๋ก์ ํธ ๊ธฐ๋ณธ ๋ฉํ์ ๋ณด๋ฅผ ์ฝ์์ ์ถ๋ ฅํฉ๋๋ค."
doLast {
println("ํ๋ก์ ํธ ์ด๋ฆ: ${project.name}")
println("ํ์ฌ ๋ฒ์ : ${project.version}")
}
}
// ํ์คํฌ ์์กด ๊ด๊ณ ์ง์ (A ์คํ ์ B ๋ฐ๋์ ์ ํ)
tasks.named("build") {
dependsOn("printProjectInfo")
}
```
## 6. ํ
์คํธ(Test) ์คํ & ๋ฆฌํฌํธ
```bash
# 1. ๋ชจ๋ ํ
์คํธ ์คํ
./gradlew test
# 2. ํน์ ํ
์คํธ ํด๋์ค ๋๋ ๋ฉ์๋๋ง ์ง์ ์คํ
./gradlew test --tests UserServiceTest
./gradlew test --tests UserServiceTest.findUserById_Success
./gradlew test --tests *ServiceTest # ์์ผ๋์นด๋ ํจํด ๋งค์นญ
# 3. ํ
์คํธ ์คํจ ์ ๋๋จธ์ง ํ
์คํธ ์ฆ์ ์ค๋จ
./gradlew test --fail-fast
# 4. ํ
์คํธ ์ฑ๊ณต ์ฌ๋ถ์ ์๊ด์์ด ๋ฌด์กฐ๊ฑด ์ฌ์คํ (์บ์ ๋ฌด์)
./gradlew test --rerun-tasks
```
```groovy
// JUnit 5 (Jupiter) ํ๋ซํผ ํ์ฑํ ๋ฐ ํ
์คํธ ๋ก๊น
์ค์
tasks.named('test') {
useJUnitPlatform()
testLogging {
events 'passed', 'skipped', 'failed'
showStandardStreams = true // System.out ์ถ๋ ฅ ์ฝ์ ํ์
}
}
// ํ
์คํธ ์๋ฃ ํ HTML ๋ฆฌํฌํธ ์์ฑ ์์น:
// build/reports/tests/test/index.html
```
## 7. JAR ํจํค์ง & ์ํฐํฉํธ ๋น๋
```groovy
// Spring Boot ํ๊ฒฝ์์ ์คํ ๊ฐ๋ฅํ Fat-JAR vs ์์ JAR ์ ์ด
bootJar {
archiveBaseName = 'my-service' // ์์ฑ๋ ํ์ผ๋ช
: my-service-1.0.0.jar
archiveVersion = '1.0.0'
}
// ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๋ ์ผ๋ฐ ์น ์ ํ๋ฆฌ์ผ์ด์
์ ๊ฒฝ์ฐ plain jar ๋นํ์ฑํ ๊ถ์ฅ
jar {
enabled = false // my-service-1.0.0-plain.jar ์์ฑ ๋ฐฉ์ง
}
// ์์ค ์ฝ๋ ๋ฐ javadoc JAR ํจ๊ป ์์ฑํ๊ธฐ
java {
withSourcesJar()
withJavadocJar()
}
```
## 8. ๋ฉํฐ ๋ชจ๋ ํ๋ก์ ํธ ๊ตฌ์ฑ (Multi-Project)
```groovy
// settings.gradle (๋ฃจํธ ์ค์ ํ์ผ์์ ํ์ ๋ชจ๋ ๋ฑ๋ก)
rootProject.name = 'ecommerce-platform'
include 'core-domain'
include 'api-server'
include 'admin-server'
include 'batch-worker'
```
```groovy
// ๋ฃจํธ build.gradle (๋ชจ๋ ์๋ธ ๋ชจ๋ ๊ณตํต ์ค์ )
subprojects {
apply plugin: 'java'
apply plugin: 'io.spring.dependency-management'
repositories {
mavenCentral()
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.2'
}
}
// ์๋ธ ๋ชจ๋(api-server/build.gradle)์์ ๋ค๋ฅธ ๋ชจ๋ ์ฐธ์กฐ
dependencies {
implementation project(':core-domain') // ๋ก์ปฌ ๋ชจ๋ ์์กด์ฑ ์ฃผ์
}
```
## 9. ๋น๋ ์๋ ์ต์ ํ (gradle.properties)
```properties
# ํ๋ก์ ํธ ๋ฃจํธ ๋๋ ~/.gradle/gradle.properties ์ ์ถ๊ฐ
# 1. JVM ํ ๋ฉ๋ชจ๋ฆฌ ๋ฐ Metaspace ํ์ฅ
org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError
# 2. ๋ฉํฐ์ฝ์ด CPU ๋ณ๋ ฌ ํ์คํฌ ์คํ (๋ฉํฐ ๋ชจ๋ ์ ํ์)
org.gradle.parallel=true
# 3. ๋น๋ ์บ์ ํ์ฑํ (๋ณ๊ฒฝ๋์ง ์์ ํ์คํฌ ๊ฒฐ๊ณผ ์ฌ์ฌ์ฉ)
org.gradle.caching=true
# 4. ํ์ผ ์์คํ
๊ฐ์ ๊ธฐ๋ฅ ํ์ฑํ (ํ์ผ ๋ณ๊ฒฝ ์ถ์ ์๊ฐ ๋จ์ถ)
org.gradle.vfs.watch=true
# 5. ์ค์ ์บ์ ํ์ฑํ (Gradle 8+ ๋น๋ ์์ ์๊ฐ ํ๊ธฐ์ ๋จ์ถ)
org.gradle.configuration-cache=true
```
## 10. ์ค๋ฌด ํธ๋ฌ๋ธ์ํ
& ๊ฟํ (Gotchas)
```bash
# 1. Gradle Wrapper ์์ฒด ๋ฒ์ ์
๊ทธ๋ ์ด๋ (์ต์ 8.x ์ ์ฉ)
./gradlew wrapper --gradle-version 8.7 --distribution-type bin
# 2. "Could not find or load main class org.gradle.wrapper.GradleWrapperMain"
# -> gradlew ์คํ ์คํฌ๋ฆฝํธ๋ง ์๊ณ gradle/wrapper/gradle-wrapper.jar ํ์ผ์ด gitignore ๋ฑ์ผ๋ก ์ ์ค๋ ๊ฒฝ์ฐ
gradle wrapper # ์์คํ
์ ์ค์น๋ ๋ก์ปฌ gradle๋ก wrapper ๋ณต๊ตฌ
# 3. Windows ํ๊ฒฝ gradlew ์คํ ๊ถํ ๋ถ์ฌ (Linux/Mac/CI)
git update-index --chmod=+x gradlew
# 4. ๊ผฌ์ธ ์์กด์ฑ ๋ก์ปฌ ์บ์ ๋๋ ํ ๋ฆฌ ์๋ ์ญ์ (์ตํ์ ์๋จ)
# Mac/Linux: rm -rf ~/.gradle/caches/
# Windows: Remove-Item -Recurse -Force ~/.gradle/caches/
```
์๊ฒฌ ๋ฐ ์ง๋ฌธ
0์์ง ๋ฑ๋ก๋ ์๊ฒฌ์ด ์์ต๋๋ค. ์ฒซ ๋ฒ์งธ ๋๊ธ์ ๋จ๊ฒจ๋ณด์ธ์!
๋๊ธ ์์
๋๊ธ ์ญ์