
While some small projects and monolithic applications may contain a single build file and source tree, it is often more common for a project to have been split into smaller, interdependent modules. The word "interdependent" is vital, as you typically want to link the many modules together through a single build.
Gradle supports this scenario through multi-project builds. This is sometimes referred to as a multi-module project.
소규모 프로젝트나 단일(monolithic) 어플리케이션은 대부분 하나의 빌드 파일과 소스 트리로 구성된다. 하지만, 프로젝트 규모가 커질수록 기능별로 코드를 분리하고, 모듈 간의 의존성을 효율적으로 관리하기 위해 멀티 모듈 구조를 적용하는 것이 일반적이다.
Gradle은 멀티 프로젝트 빌드(Multi-Project Build) 를 지원하며, 이를 멀티 모듈 프로젝트(Multi-Module Project)라고도 한다. 안드로이드는 Gradle을 공식 빌드 시스템으로 사용하기에 멀티 모듈 프로젝트 구조를 적용하여 기능별 모듈화, 빌드 속도 최적화, 코드 재사용성 증가 등 여러 장점을 그대로 사용할 수 있다.

Gradle에서는 멀티 프로젝트 빌드(Multi-Project Build) 를 구성할 때, 공통적인 빌드 로직을 효율적으로 관리하기 위해 두 가지 표준 방식을 제공한다.
buildSrc는 Gradle이 자동으로 감지하는 특별한 디렉터리로, 프로젝트의 공통 빌드 로직, 커스텀 태스크, 플러그인을 정의하는 공간이다.
Gradle은 buildSrc의 내용을 자동으로 컴파일하고, 모든 빌드 스크립트에서 사용할 수 있도록 Classpath에 추가한다.
이로써 반복되는 빌드 관련 로직을 한 곳에서 정의하고 관리할 수 있다.
.
├── gradle
├── gradlew
├── settings.gradle.kts
├── buildSrc
│ ├── build.gradle.kts
│ └── src/main/kotlin/shared-build-conventions.gradle.kts
├── mobile-app
│ └── build.gradle.kts
├── web-app
│ └── build.gradle.kts
├── api
│ └── build.gradle.kts
├── lib
│ └── build.gradle.kts
└── documentation
└── build.gradle.kts
buildSrc를 활용하면, 커스텀 빌드 로직(태스크, 플러그인 등)을 한 곳에 모아두고 모든 서브 프로젝트에서 buildSrc에 정의된 로직을 바로 사용할 수 있기 때문에, 코드 중복을 방지하고 유지보수를 쉽게 할 수 있다.
buildSrc 내부의 빌드 로직은 프로젝트의 다른 build.gradle.kts 파일과 완전히 분리되어 관리되기에 프로젝트의 메인 빌드 스크립트가 더 간결해지고, 각 역할별 기능에 집중할 수 있다.
Gradle은 buildSrc 디렉터리를 자동으로 감지하고, 그 안의 코드를 컴파일하여 프로젝트의 클래스패스에 포함시킨다.
이로써, buildSrc 내부에서 정의된 모든 클래스, 플러그인, 태스크는 별도의 설정 없이 간편하게 build.gradle.kts에서 바로 사용할 수 있다.
buildSrc 내부의 코드도 일반적인 Kotlin/Java 프로젝트처럼 테스트 가능하기에 Gradle API를 활용하여, 커스텀 빌드 로직이 의도한 대로 동작하는지 확인할 수 있다.
buildSrc 내에 플러그인 코드를 정의하면, 프로젝트 내에서 쉽게 사용할 수 있다.
The downside of using buildSrc is that any change to it will invalidate every task in your project and require a rerun.
buildSrc 를 사용한 멀티 모듈 프로젝트의 가장 큰 단점은 buildSrc내의 코드가 변경되면 전체 빌드를 다시 수행해야한다는 것이다.
그렇기에 프로젝트 규모가 크면 클 수록, 수정으로 인한 빌드 시간이 커지는 문제가 존재한다.
Composite Builds, also referred to as included builds, are best for sharing logic between builds (not subprojects) or isolating access to shared build logic (i.e., convention plugins).
Composite Build 는 하나의 Gradle 빌드 시스템에서 여러 개의 독립적인 빌드를 포함하고 실행하는 방식으로, 서브 프로젝트(subprojects)를 포함하는 것이 아니라 독립적인 빌드(builds)를 함께 관리하는 개념이다.
이를 통해 공통 빌드 로직을 공유하고, 여러 개의 프로젝트를 효율적으로 조합할 수 있다.
.
├── gradle
├── gradlew
├── settings.gradle.kts
├── build-logic
│ ├── settings.gradle.kts
│ └── conventions
│ ├── build.gradle.kts
│ └── src/main/kotlin/shared-build-conventions.gradle.kts
├── mobile-app
│ └── build.gradle.kts
├── web-app
│ └── build.gradle.kts
├── api
│ └── build.gradle.kts
├── lib
│ └── build.gradle.kts
└── documentation
└── build.gradle.kts
빌드를 포함시키는 방식이기에 build-logic의 위치는 상관없으며, 루트 프로젝트 바깥에도 위치할 수 있다.
pluginManagement {
includeBuild("build-logic1") // 내부에 있는 build-logic을 포함
includeBuild("../build-logic2") // 루트 프로젝트 외부에 있는 build-logic을 포함
}
build-logic과 buildSrc 모두 Gradle 빌드 로직을 공유한다는 공통점이 있지만, 차이점 또한 존재한다.
| 비교 항목 | buildSrc | build-logic (Composite Build) |
|---|---|---|
| 구성 방식 | Gradle이 자동으로 감지하여 포함됨 | includeBuild("<경로>")로 명시적으로 포함해야 함 |
| 빌드 로직 적용 방식 | 모든 서브 프로젝트에서 자동으로 인식 가능 | 명시적으로 포함된 프로젝트에서만 사용 가능 |
| 공유 가능 여부 | 하나의 프로젝트에서만 사용 가능 | 여러 프로젝트에서 공통 빌드 로직으로 사용 가능 |
| Gradle이 자동 감지 여부 | ✅ (자동 감지됨) | ❌ (명시적으로 includeBuild() 해야 함) |
| 빌드 시점 | 모든 빌드에서 항상 포함됨 | 필요할 때만 포함 가능 |
| 빌드 성능 | 변경될 때마다 전체 빌드 무효화 | 변경 사항이 있을 때만 빌드 |
| 사용 목적 | 프로젝트 내 공통 빌드 로직 관리 (단일 프로젝트) | 여러 프로젝트에서 재사용할 빌드 로직 관리 |
build-logic은 변경되었을 때, 사용되는 모듈만 다시 빌드되기에 buildSrc와 비교하여 빌드 성능을 개선할 수 있다. 그렇기에 Gradle 7.0 이후로는 공유 빌드 로직을 사용할 때는 buld-logic 방식이 권장된다.
또한, 하나의 루트 프로젝트에서만 사용할 수 있는 buildSrc에 비해 build-logic은 프로젝트에 포함되는 것이 아니기 때문에 서로 다른 루트 프로젝트에서 포함될 수 있다.