일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- 1차원 DP
- 2차원 dp
- 99클럽
- @BeforeAll
- @BeforeEach
- @Builder
- @Entity
- @GeneratedValue
- @GenericGenerator
- @NoargsConstructor
- @Query
- @Table
- @Transactional
- Actions
- Amazon EFS
- amazon fsx
- Android Studio
- ANSI SQL
- api gateway 설계
- api gateway 필터
- ApplicationEvent
- argocd
- assertThat
- async/await
- AVG
- AWS
- aws autoscaling
- aws eks
- aws iam role
- AWS KMS
- Today
- Total
기록
Spring Boot 멀티모듈 프로젝트 빌드 실패 - 루트 프로젝트의 bootJar 설정 누락 본문
1. 문제 개요
Spring Boot 기반 멀티모듈 프로젝트에서 전체 빌드 명령(./gradlew build) 수행 시, 다음과 같은 오류가 발생하며 빌드가 실패하는 현상이 발생하였다:
Execution failed for task ':bootJar'.
> Main class name has not been configured and it could not be resolved from classpath
해당 오류는 단일 모듈 환경에서는 보기 드문 현상이며, 멀티모듈 구조에서 특정 조건 하에 발생하는 구조적 문제에 해당한다.
2. 문제의 원인
2.1 멀티모듈 프로젝트의 구조
해당 Spring Boot 멀티모듈 프로젝트는 다음과 같은 구조를 가진다:
root/
├── build.gradle.kts ← 루트 프로젝트 (실행 대상 아님)
├── settings.gradle.kts
├── module-bootstrap/ ← 실행 진입점 (main 함수 존재)
├── module-common/ ← 공통 라이브러리
├── module-user/ ← 도메인 기능 모듈
└── ...
여기서 module-bootstrap만이 애플리케이션의 실제 실행 진입점이며, 다른 모듈들은 비실행용 구성요소에 해당한다.
2.2 bootJar 작업의 자동 생성 및 mainClass 요구
org.springframework.boot 플러그인을 적용한 모든 프로젝트(서브 및 루트 포함)는 Gradle 빌드 시 bootJar 작업을 생성하게 된다. 이 작업은 실행 가능한 Spring Boot 애플리케이션 JAR을 생성하기 위한 것이며, 필연적으로 애플리케이션의 진입점 클래스(mainClass)가 필요하다.
하지만 루트 프로젝트는 실행을 담당하지 않기 때문에 일반적으로 main() 함수를 포함하거나 @SpringBootApplication 애노테이션이 선언된 클래스가 존재하지 않는다. 그럼에도 불구하고 루트 프로젝트에 bootJar 작업이 활성화된 상태에서 전체 빌드를 수행하게 되면, mainClass를 자동 추론할 수 없어 빌드가 실패하게 된다.
3. 해결 방법
3.1 루트 프로젝트의 bootJar 작업 비활성화
루트 프로젝트의 build.gradle.kts 또는 build.gradle 파일 내에서 bootJar 생성을 명시적으로 비활성화해야 한다.
tasks.named<org.springframework.boot.gradle.tasks.bundling.BootJar>("bootJar") {
enabled = false
}
tasks.named<Jar>("jar") {
enabled = true
}
이 설정을 통해 루트 프로젝트는 실행 가능한 JAR을 생성하지 않으며, 대신 일반적인 라이브러리 JAR을 생성할 수 있다.
3.2 실행 대상 모듈의 mainClass 명시
실제로 실행을 담당하는 모듈(예: module-bootstrap)의 build.gradle.kts 파일 내에는 다음과 같이 mainClass를 명시적으로 설정해야 한다.
springBoot {
mainClass.set("com.example.bootstrap.BootstrapApplication")
}
여기서 com.example.bootstrap.BootstrapApplication은 @SpringBootApplication 애노테이션이 붙은 클래스의 FQCN(Fully Qualified Class Name)을 나타낸다.
4. 실무 적용을 위한 팁
4.1 실행 모듈과 라이브러리 모듈의 역할 구분
- bootJar는 오직 실행 가능한 애플리케이션 모듈에서만 활성화해야 하며, 나머지 모듈에서는 비활성화하는 것이 바람직하다.
- Gradle 설정 시 모든 하위 프로젝트에 일괄적으로 spring-boot 플러그인을 적용하기보다는, 실행 모듈에만 선택적으로 적용하는 전략도 고려할 수 있다.
4.2 명시적 모듈 빌드 수행 권장
전체 프로젝트를 대상으로 빌드를 수행하는 대신, 명시적으로 실행 대상 모듈만 빌드하는 방식이 불필요한 오류를 줄일 수 있다.
./gradlew :module-bootstrap:build
4.3 CI/CD 환경에서의 bootJar 대상 관리
CI 스크립트 또는 자동화된 빌드 환경에서는 루트 build.gradle.kts에 bootJar 비활성화가 누락되었을 경우, 개발 환경에서는 발생하지 않던 빌드 오류가 재현될 수 있다. 이를 방지하기 위해 초기 프로젝트 설정 시 반드시 bootJar 대상 범위를 명확히 하는 것이 중요하다.
5. 결론
Spring Boot 기반 멀티모듈 프로젝트에서 루트 프로젝트는 보통 실행 대상이 아니므로, bootJar를 비활성화하지 않으면 mainClass 누락 오류로 인해 전체 빌드가 실패할 수 있다. 이를 방지하기 위해서는:
- 루트 프로젝트의 bootJar 비활성화,
- 실행 모듈에서의 mainClass 명시,
- 명시적 빌드 대상 지정
이 세 가지를 반드시 실무에서 반영해야 한다.
이러한 구성을 통해 빌드 안정성을 확보하고, 멀티모듈 아키텍처 내 역할 분리를 명확히 유지할 수 있다.
'Web > Spring' 카테고리의 다른 글
Spring 프로필, Gradle, JVM 옵션: -Dspring.profiles.active (0) | 2025.04.26 |
---|---|
멀티 모듈 기반 영화 예매 서비스 설계기 : 테이블 및 엔티티 설계(1) - ERD 모델링 (0) | 2025.04.07 |
"JWT signature does not match" 오류의 원인과 해결 과정 (0) | 2025.04.03 |
멀티 모듈 기반 영화 예매 서비스 설계기 : 멀티 모듈 프로젝트 설계(3) - Layer 기반의 모듈 분리 (0) | 2025.04.01 |
멀티 모듈 기반 영화 예매 서비스 설계기 : 멀티 모듈 프로젝트 설계(2) - 헥사고날 아키텍처 적용 (0) | 2025.03.31 |