Spring

Gradle 설정 알아보기 (1편)

recent0 2025. 2. 16. 22:02

0. 서론


0.1 왜 이걸 찾아보게 되었는가?

  • 멀티 모듈 아키텍처에서 의존성을 정리하면서 다양한 개념들이 나왔지만 필요한 것만 골라서 찾아봄
  • 그 당시에는 어떤 역할을 하는지 간단하게 알아보고 사용했기에 잠시만 기억하고, 기억에 남아 있지 않음
  • 하지만 계속 사용할거라고 생각했기 때문에 한번 정리가 필요하다고 생각

0.2 정리하고자 하는 내용

  • gradle의 역할 및 특징
  • build.gradle에서 볼 수 있는 설정들
  • 의존성과 관련된 implementation, compileOnly, runtimeOnly, runtimeClasspath은 2편에서 다룰 예정

 

1. Gradle


1.1 Gradle 역할 및 특징

  • 코드 컴파일 및 패키징
    • Java, Kotlin, Groovy 등의 소스코드를 컴파일하고 JAR 또는 WAR 파일로 패키징
  • 빌드 스크립트 기반 자동화
    • build.gradle 파일을 이용해 빌드 과정(테스트, 배포 등)을 자동화
    • 필요한 플러그인과 테스크 쉽게 추가 가능
  • 테스트 자동화 지원
    • Junit, TestNG 등의 테스트 프레임워크와 연동하여 자동화 테스트 실행
  • 멀티 모듈 지원
  • 의존성 관리

1.2 Gradle, Maven 비교

Gradle과 Maven의 차이점을 정리하면 다음과 같이 간단하게 정리할 수 있습니다.

증분 빌드

  • 변경된 파일만 빌드하는 특징이 있기 때문에 불필요한 작업이 줄어듦
  • 예를 들어 A.java, B.java가 있을 때 이 두 파일을 빌드한 후 A.java를 수정한 후 재빌드할 때 B.java는 다시 컴파일하지 않음
  • Gradle을 사용하면 전체 빌드시간이 줄어들 수 있음. 반면 Maven은 무조건 전체 재빌드함

데몬 프로세스

  • 백그라운드에서 실행되는 빌드 최적화 프로세스
  • Gradle은 백그라운드에서 실행되는 데몬 프로세스를 사용해서 빌드 속도를 향상
  • 데몬 프로세스는 Gradle을 실행할 때마다 새로 시작되지 않고, 이미 실행 중인 프로세스를 재사용해서 빌드 속도를 높임

병렬 빌드

  • 멀티코어 CPU를 활용하여 여러 작업을 동시에 실행할 수 있음
  • 병렬로 빌드하고 싶으면 아래와 같이 빌드할 때 parallel 옵션을 포함
./gradlew build --parallel

캐싱

  • 이전에 빌드한 결과를 캐싱해서 동일한 작업을 실행하지 않도록 최적화
  • 다운로드한 라이브러리를 캐싱하기 때문에 불필요한 통신 최소화

스크립트 문법

  • Maven은 pom.xml 기반으로 설정
  • Gradle은 Groovy/Kotlin DSL을 사용하여 상대적으로 Maven 보다 편리하게 관리
  •  

2. Gradle 구성 요소 


2.1 Plugins

Plugin이란?

  • Gradle 빌드 시스템의 기능을 확장하는 모듈
  • Gradle이 기본적으로 제공하는 기능 외에도 특정 작업을 쉽게 사용할 수 있도록 도와주는 추가 기능

Plugins 예시

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.1.0'
    id 'io.spring.dependency-management' version '1.1.0'
}
  • 위와 같이 자바와 스프링 부트 설정 플러그인을 추가하면 다음과 같은 기능을 사용할 수 있음
  • Java plugin 예시 테스크: compileJava, test, jar
  • Spring Boot 예시 테스크 : bootRun, bootJar

Java plugin을 추가했을때 추가된 테스크 예시

2.2 Configurations

configurations란?

  • 새로운 의존성 그룹을 정의하거나 기존 설정을 확장할 때 사용
  • 이를 통해 의존성을 조금 더 유연하게 관리할 수 있음

configurations 사용 예시

1. 새로운 Configuration 정의 

  • 아래와 같이 utilConfig라는 의존성 그룹을 정의해서 사용할 수 있음
configurations {
    utilConfig
}

dependencies {
    utilConfig 'org.apache.commons:commons-lang3:3.12.0'
}

 

2. 기존 Configuration 확장

  • compileOnly 설정이 기존에 설정된 annotationProcessor를 상속
  • 기본적으로 anntationProcessor와 compileOnly는 분리되어 있음
  • Lombok을 사용한다고 했을 때 아래와 같이 사용할 수 있는데, 어노테이션 프로세서가 동작하지 않음
  • 이유는 annotationProcessor가 compileOnly와 별개라서, compileOnly에서는 Lombok의 프로세서를 인식 못함
  • 그렇기 때문에 compileOnly 설정이 annotationProcessor를 상속받아 문제를 해결할 수 있음
configurations {
    compileOnly {
		extendsFrom annotationProcessor
	}
}

dependencies {
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
}

 

3. 특정 Configuration 제외

  • 아래 예시와 같이 implementation Configuration slf4j 라이브러리를 사용하지 않도록 할 수 있음
configurations {
    implementation {
        exclude group: 'org.slf4j', module: 'slf4j-log4j12'
    }
}

2.3 Repositories

repositories 역할

  • repositories는 의존성을 어디서 다운로드할지 지정하는 역할을 함
  • 즉 라이브러리를 가져올 저장소를 설정할 수 있음

repositories 사용 예시

  • 가장 흔하게 사용할 수 있는 Maven Central 저장소로부터 라이브러리를 가져오는 mavenCentral()이 있음
  • 사내에 Nexus 서버를 두고 Nexus로부터 라이브러리를 가져올 수도 있음
repositories {
	//가지고오는 라이브러리 저장소 주소 -> https://repo1.maven.org/maven2/ 
	mavenCentral()
}

repositories {
    maven {
        url "https://nexus.test.com/repository/test/"
    }
}

 

2.4 dependencies

dependencies 역할

  • 프로젝트에 필요한 의존성을 관리할 수 있는 설정

dependencies 사용 예시

  • 아래와 같이 implementation, compileOnly, runtimeOnly 등등 다양한 의존성 설정을 통해 구성할 수 있음
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    runtimeOnly 'com.mysql:mysql-connector-j'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

2.5 allprojects, subprojects

allprojects, subprojects의 역할

  • 멀티모듈을 사용하고 있는 경우에 루프 프로젝트에서 하위 프로젝트를 설정할 수 있는 방법이다.
  • allProjects는 루트 프로젝트와 하위 프로젝트에 모두 설정을 적용할 때 사용
  • subProjects는 하위 프로젝트에만 설정을 적용할 때 사용

allprojects, subprojects 사용 예시

  • api 모듈이 있고, 여기 하위 모듈로 공통적으로 DTO나 유틸 클래스를  관리하는 core 모듈, domain 코드를 관리하는 domain 모듈이 있다고 가정
  • 모듈마다 라이브러리를 당겨서 사용하고 싶기 때문에 allProjects에서는 어떤 repositories를 사용할지 정할 수 있도록 구성
  • subprojects에서는 lombok, apache common langs 라이브러리를 공통적으로 사용하도록 설정해 모든 모듈에서 lombok과 apache common langs 라이브러리를 이용 가능
allprojects {
    repositories {
        mavenCentral()
    }
}

subprojects {
    apply plugin: 'java'
    apply plugin: 'io.spring.dependency-management'

    dependencies {
        compileOnly 'org.projectlombok:lombok'
        annotationProcessor 'org.projectlombok:lombok'
        testCompileOnly 'org.projectlombok:lombok'
        testAnnotationProcessor 'org.projectlombok:lombok'
        implementation 'org.apache.commons:commons-lang3:3.12.0'
    }
}

 

2.6 project

project의 역할

  • project는 각 모듈을 정의하고 설정하는 기본 단위
  • 멀티모듈 프로젝트에서는 여러 개의 project가 존재하고, 이를 build.gradle에서 설정할 수 있음

project 사용 예시

  • 멀티 모듈 아키텍처이고 크게 api 모듈, domain 모듈, core 모듈이 있다고 가정
  • 각 api 모듈은 다음과 같은 역할을 가짐
    • api와 서비스를 관리하는 모듈을 api 모듈
    • 공통 DTO나 유틸 클래스를  관리하는 core 모듈
    • domain 코드를 관리하는 domain 모듈
  • 각 api 가 최상위 모듈이고 아래에 core 모듈과, domain 모듈을 의존하고 있다고 했을 때 project에서 다음과 같이 모듈을 구성할 있음
project(':main-api') {
    dependencies {
        implementation project(':core')
        implementation project(':domain')
    }
}

 

 

3. 글을 마치며


이번에는 build.gradle에서 코드 블럭을 가지고 있는 설정들에 대해 알아보았습니다. 다음 2편에서는 dependencies 설정에서 볼 수 있는 의존성 설정들에 대해 정리해 보겠습니다. 읽어주셔서 감사합니다.