본 글은 멀티모듈 빌드와 관련된 gradle의 핵심 기능을 다룹니다.
단순 라이브러리 의존용으로 사용하는 걸 넘어, 직접 모듈을 만드는데 필요한 기본 지식을 다루니, 관심있다면 docs를 직접 읽어보시는것도 추천드립니다.
- 주요 주제
- gradle의 디렉토리 구조
- Project Root Directory
- 멀티 모듈의 구조
- Gradle의 빌드 라이프사이클
- settings.gradle
- build.gradle
- gradle의 디렉토리 구조
Gradle의 프로젝트 루트 디렉토리
- gradle은 다음 두가지 디렉토리를 사용한다.
- Gradle User Home Directory
- Project Root Directory
Gradle User Home Directory
- Gradle의 글로벌 설정, 초기화 스크립트, 캐시 및 로그 파일이 저장된 디렉토리이다.
- 자세한 내용은 해당 문서를 참고하도록 하자.
Gradle-managed Directories
By default, the Gradle User Home (~/.gradle or C:\Users\ \.gradle ) stores global configuration properties, initialization scripts, caches, and log files. It can be set with the environment variable GRADLE_USER_HOME. Not to be confused with the GRADLE_HOME
docs.gradle.org
사실 우리가 정확하게 이해해야 하는 것은 Gradle의 프로젝트 디렉토리 구조이다.
지금부터 gradle의 프로젝트 루트 디렉토리 구조에 대해 알아보자.
Project Root Directory
- 프로젝트 루트 디렉토리란, 프로젝트의 모든 소스 파일이 들어있는 디렉토리를 의미한다.
- 여기에는 Gradle이 생성하는 .gradle, build 뿐만 아니라, Gradle config 디렉토리(gradle/)도 포함된다.
1. .gradle 폴더
Gradle이 생성한 프로젝트별 캐시 디렉토리이다.
2. 버전별 캐시 (예: incremental build 지원)
3. build
Gradle이 모든 빌드 아티팩트를 생성하는 이 프로젝트의 빌드 디렉토리이다.
4. wrapper
gradle wrapper의 JAR 파일과 config을 포함한다.
5. gradle.properties
프로젝트 별 Gradle config property가 담겨 있다.
6. gradlew, gradlew.bat
gradle wrapper를 사용하여 빌드를 실행하기 위한 스크립트가 담겨 있다.
./gradlew 사용 시 사용하게 되는 스크립트이다.
7. settings.gradle
하위 프로젝트의 목록이 정의된 전체 프로젝트 설정 파일이다.
8. sub-project 폴더
각 프로젝트가 포함하는 하나 이상의 하위 프로젝트를 의미한다.
해당 서브 프로젝트가 여러개 있을 때, 멀티 모듈 프로젝트라고 부른다.
각 하위 프로젝트는 프로젝트의 디렉토리 이름으로 구분된다.
9. build.gradle
각 하위 프로젝트가 빌드할 때 사용하는 gradle 빌드 스크립트이다.
이를 통해, 해당 모듈이 참조하는 다른 모듈이 무엇인지를 명시적으로 관리할 수 있다.
본격적으로 멀티 모듈 프로젝트의 구조에 대해 살펴보자.
멀티 모듈의 구조
Gradle은 멀티 모듈 빌드를 지원한다.
일부 소규모 프로젝트와 모놀리식 애플리케이션은 단일 빌드 파일과 소스 트리를 포함할 수 있지만, 일반적으로 프로젝트는 더 작고 "상호 의존적"인 모듈로 분할된다.
최종적으론, 여러 모듈을 단일 빌드를 통해 연결해야 한다.
멀티 모듈의 구조
예를 들어, 다음과 같은 프로젝트를 생각해보자.
다음과 같은 프로젝트의 경우, 디렉토리 구조는 다음과 같게 될 것이다.
1. settings.gradle
- 해당 settings.gradle 파일에는 모든 하위 프로젝트가 포함되어 있어야 한다.
2. build.gradle
- 각 하위 프로젝트마다 별도의 build.gradle 파일이 있어야 한다.
멀티 모듈의 표준
- buildSrc를 사용한 멀티 모듈 빌드
- 모노레포 내에서 여러 모듈 간 의존성 관리를 중앙에서 간편히 관리하고 싶을 때 사용한다.
- 주로 모놀리식 아키텍처에서 멀티모듈을 가져갈 때 사용하게 된다.
Sharing Build Logic between Subprojects
Gradle’s recommended way of organizing build logic is to use its plugin system. We can write a plugin that encapsulates the build logic common to several subprojects in a project. This kind of plugin is called a convention plugin. While writing plugins i
docs.gradle.org
- composite build
- 여러 독립적인 프로젝트를 동시에 개발하고 테스트해야 할 때 사용한다.
- 주로 MSA 환경에서 사용하게 된다.
Composite Builds
Most builds can be included in a composite, including other composite builds. There are some restrictions. In a regular build, Gradle ensures that each project has a unique project path. It makes projects identifiable and addressable without conflicts. In
docs.gradle.org
기본 관리 방법
- 멀티 모듈의 경로 지정은 콜론(:) 기호를 통해 이용 가능하다.
- 루트 프로젝트의 경우, 프로젝트 내 유일한 콜론(:)이 붙지 않은 프로젝트이다.
좀 더 자세한 내용은 해당 링크를 참고하길 바란다.
Structuring Projects with Gradle
As your project grows, naming and consistency get increasingly more important. To keep your builds maintainable, we recommend the following: Keep default project names for subprojects: It is possible to configure custom project names in the settings file.
docs.gradle.org
잠깐, Task와 Plugin이란?
task
- Gradle이 사용하는 최소 작업 단위를 의미한다.
- gradle이 수행하는 모든 일은 작업의 집합으로 이루어진다.
작업의 종류
작업은 실제로 다음 두가지로 분류할 수 있다.
- 실행 가능한 작업(Actionable Tasks)
- 빌드 과정에서 실제 작업을 수행하는 태스크를 의미한다.
- 대표적인 예로
compileJava
,jar
,test
등이 있다.
- 생명주기 작업 (Lifecycle Tasks)
- 자체적으로는 별도의 액션을 가지지 않고, 다른 태스크들에 대한 의존성을 정의하며, 여러 작업을 한번에 실행하는 관문 역할을 하는 태스크를 의미한다.
- 대표적인 예로
build
,check
,assemble
등이 있다.
plugin
- kotlin/groovy로 구현한 작업 단위의 집합.
- 외부 라이브러리를 사용 혹은 특정 기능을 하나로 묶어 관리하고 싶을 때 사용한다.
gradle 빌드의 라이프사이클
./gradlew build
를 입력했을 때 발생하는 동작의 생명주기를 이해해보자.- 초기화 (Initialization)
- Gradle이 빌드에 참여할 프로젝트를 결정하고, 각 프로젝트에 대한 Project 인스턴스를 생성한다.
- 구성 (Configuration)
- Gradle이 빌드에 포함된 모든 프로젝트의 빌드 스크립트를 사용하여
Project
객체를 구성한다. - Gradle은 실행할 Task 들의 순서를 결정한다.
- Gradle이 빌드에 포함된 모든 프로젝트의 빌드 스크립트를 사용하여
- 실행 (Execution)
- Gradle이 선택된 작업들을 각각 순서대로 실행한다.
실제 예제로 Gradle의 라이프사이클을 알아보자.
예제: settings.gradle
- 프로젝트 초기화 시 수행할 작업을 추가해두었다.
- 여기서는 println을 통해 문자열을 콘솔에 출력하는 일을 지정했다.
예제: build.gradle
- task.register("task1") 을 통해 task1 작업 등록 시 해야할 일을 지정했다.
- task.register("task2") 을 통해 task2 작업 등록 시 해야할 일을 지정했다.
- task.named("task1") 을 통해 task1 작업 실행 시 수행하는 일을 지정했다.
- task.named("task2") 을 통해 task2 작업 실행 시 수행하는 일을 지정했다.
예제 실행 결과
1. 초기화
- Gradle은 settings.gradle 파일을 통해 빌드에 사용할 프로젝트를 파악하고 각 프로젝트에 대해 Project 객체를 생성한다.
2. 구성
- Gradle은 각 프로젝트의 build.gradle을 통해 작업을 구성한다.
- Gradle은 모든 가용 작업에 대한 의존 그래프를 생성하여, 의존성 관계를 풀어낸다.
3. 실행
- Gradle은 커맨드 라인에 전달된 작업과 그 사전 작업들을 모두 실행한다.
이때, task2관련 작업은 수행되지 않았다.
- 이는 task2의 경우 필요하지 않은 작업이었기 때문에, Gradle에서 task2의 등록과 수행을 회피했다.
- 이를 "task configuration avoidance" 라고 한다.
참고) groovy는 JVM 위에서 실행되는 프로그래밍 언어이다.
형태만 Java와 다를 뿐, Java와 유사하게 동작한다고 생각해도 좋다.
참고) Project 객체가 가진 정보와 관련된 설정은 Configuration 시점에 수행해야 한다.
Project 객체의 값이 필요하다면, Configuration Time에 필요한 Project 객체의 값을 적절한 Task의 속성으로 부여해야 한다.
따라서 위와 같이 Execution Time에 Project 객체에 직접 접근하는 것은 불가능하다. 먼저 다음과 같이 register 시점에 새로 필드를 만들어 값을 대입해준 뒤 위와 같이 해당 필드에서 원하는 값을 찾아 써야 한다.
settings.gradle 작성
settings.gradle이란?
- settings.gradle은 모든 Gradle 빌드의 진입점이다.
- gradle은 프로젝트를 전부 빌드하기 전에 settings 인스턴스(객체)를 생성하고, settings.gradle 파일을 실행시킨다.
- settings.gradle은 본질적으로 Gradle API를 사용하는 DSL이다.
- 따라서, settings.gradle과 settings 인스턴스 사이에는 일대일 대응이 있다.
settings 객체
settings 객체란, gradle이 빌드를 수행할 때 사용할 설정 정보를 갖고 있는 객체이다.
대표적으로 가지고 있는 속성은 다음과 같다.
대표적으로 사용되는 메소드는 다음과 같다.
- include()
- 주어진 프로젝트를 빌드에 추가한다.
- includeBuild()
- 지정된 경로에 복합 빌드의 빌드를 포함한다.
- gradle은 하위 프로젝트를 디렉터리의 이름으로 식별한다.
- 좀 더 자세한 설명은 해당 링크에서 찾을 수 있다.
Settings - Gradle DSL Version 8.14
Declares the configuration required to instantiate and configure the hierarchy of Project instances which are to participate in a build. There is a one-to-one correspondence between a Settings instance and a settings.gradle settings file. Before Gradle ass
docs.gradle.org
settings.gradle 구조
1. pluginManagement
플러그인의 위치를 정의한다.
2. plugins
setting 플러그인을 적용한다.
3. rootProject.name
루트 프로젝트 이름을 정의한다.
4. dependencyResolutionManagement
종속성 해결 전략을 정의한다.
5. include("프로젝트-폴더")
빌드에 하위 프로젝트를 추가한다.
실제로는 settings.gradle로 조작하는 것보다, settings 객체를 직접 다루는 것이 훨씬 많은 선택지를 가지고 있다.
만약 다양한 기능을 사용하고 싶다면, groovy 내에서 직접 settings 객체를 조작하는 "플러그인으로 구현"하는 것이 좋다.
build.gradle 작성
Project 객체란?
Project 객체란 settings 객체와 마찬가지로 Gradle API 중 하나로, 프로젝트의 정보를 관리하는 객체이다.
- 대표적으로 가지고 있는 속성은 다음과 같다.
- 대표적으로 사용되는 메소드는 다음과 같다.
이렇게만 봐선 이해하기 어려우니, build.gradle을 읽기 위해 해당 빌드 스크립트의 구조에 대해 살펴보자.
빌드 스크립트(build.gradle)의 구조
- plugins
빌드에 플러그인을 적용한다. - repositories
종속성이 발견될 수 있는 위치를 정의한다.
이 DSL에선 Maven Central Repository를 메인 리포지토리로 정의했다. - dependencies
종속성을 추가한다. - “pluginName”(플러그인 이름)
속성을 설정한다.
1번에서 선언한 "플러그인의 id"로 해당 플러그인에 대한 속성을 설정할 수 있다. - tasks.named/task.register
작업을 등록하고 구성한다.
dependsOn() 메소드를 통해, 다른 작업과의 종속성을 추가할 수도 있다.
dependencies 블록의 속성 작성 방법
참고 자료
- Gradle 공식 문서
- Task에 대하여
- Plugin에 대하여
- 좀 더 깊게 이해해보고 싶다면, 해당 튜토리얼을 따라가보는 것을 추천한다.
'Article - 깊게 탐구하기 > 개발 꿀팁' 카테고리의 다른 글
[Gradle] Gradle - 기본 구조 알아보기 (0) | 2025.05.13 |
---|---|
패키지 구조 선택 방법 (0) | 2025.04.27 |
개인 프로젝트로 학습하는 방법 (0) | 2025.03.31 |
기본적인 문제 해결 방법 (0) | 2025.03.28 |
책 읽는 방법 (0) | 2025.03.24 |