저번 포스트에서 멀티 모듈의 개념, 사용하는 이유, 어떻게 구성하는지에 대해 알아보았다.
이번 포스트에서는 멀티 모듈 프로젝트를 생성하는 과정에 대해 알아보자.
0. 모듈을 어떻게 구성할까?
멀티 모듈을 도입하기 전, 패키 프로젝트의 모듈을 어떻게 구성할지 고민해보았다.
몇 가지 레포들을 살펴본 결과 아래와 같이 모듈을 나누는 것을 볼 수 있었다. (참고한 레포 중 일부를 가져왔다.)
- Street Drop : api, batch, domain, admin, notification, search, common
- Melly : clients, core, infra, storage, support
- Toks : api, core, flyway
다양한 레퍼런스들을 참고하며 나는 모듈을 다음과 같이 구성하도록 결정하였다.
- api: api 관련 모듈
- infra: 인프라 구축 관련 모듈 (ex. AWS)
- domain: 도메인 모델 관련 모듈
- clients: 외부 연동 모듈 (ex. 카카오, 애플 로그인)
우선 4개의 모듈을 만들고 core, common, admin, batch 등 다른 모듈은 필요성을 느낄 때 추가해나갈 예정이다.
1. 프로젝트 생성 및 src 폴더 삭제
빌드 도구는 Gradle로 선택하여 Spring Boot 프로젝트를 하나 생성해준다.
Spring Boot 버전의 경우 3.2.1을 선택하였고, 의존성은 추가하지 않고 생성하였다.
루트 프로젝트는 하위 모듈을 관리하는 역할만 하고, 공통 코드의 경우 common 모듈에서 관리하기 때문에 src 폴더는 삭제해준다.
2. 모듈 추가
최상단 디렉토리에서 New > Module을 눌러 모듈을 추가하자
패키지와 모듈이 구분되도록 앞에 프로젝트명을 적어서 모듈을 만들어주었다.
아래와 같이 모듈이 만들어지고 모듈 내부에는 src 디렉토리와 build.gradle이 있다.
루트 프로젝트를 보면 setting.gradle에 서브 프로젝트(모듈) 정보가 자동으로 기입된 것을 볼 수 있다. 만약 없다면 include '(모듈명)'으로 추가해주자.
4. 루트 프로젝트와 서브 프로젝트 build.gradle 수정
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.1'
id 'io.spring.dependency-management' version '1.1.4'
}
java {
sourceCompatibility = '17'
}
// 루트 프로젝트를 포함해 하위 프로젝트 전체에 영향을 주는 설정
allprojects {
group = 'com.dilly'
version = '0.0.1-SNAPSHOT'
repositories {
mavenCentral()
}
// 공통 dependencies
dependencies {
}
}
// 해당 프로젝트에 포함된 모든 모듈에 영향을 주는 설정
subprojects {
apply plugin: 'java'
apply plugin: 'java-library'
apply plugin: 'org.springframework.boot'
// spring boot dependency를 사용하여 사용중인 부트 버전에서 자동으로 의존성을 가져온다
apply plugin: 'io.spring.dependency-management'
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
}
}
tasks.named('test') {
useJUnitPlatform()
}
bootJar.enabled = false
💡 bootJar vs jar
bootJar은 Main 클래스들과 의존성을 포함해 실행 가능한 jar를, jar는 메인 클래스들을 포함한 jar을 만든다.
실행 가능 여부, 즉 jar 파일이 실행 가능하려면 Main 클래스와 의존성들이 들어있는 Manifest 파일을 만드는지 여부가 두 명령어의 차이이다.
bootJar은 실행 가능한 jar을 생성하려고 시도하기 위해 main() 메서드가 필요하지만 루트 프로젝트는 main() 메서드가 필요 없으므로 enabled를 false로 해준다.
아래에서 API 서버를 실행해볼 것이므로, 즉 다른 모듈들은 main() 메서드를 만들지 않을 것이므로 bootJar는 false, jar는 true로 build.gradle에 추가해주자.
bootJar.enabled = false
jar.enabled = true
5. Application.java 파일 생성
프로젝트가 잘 구성되었는지 확인하기 위해 API 서버를 실행해보자.
서버를 실행하기 위해서 Application.java가 필요하므로, ApiApplication.java를 생성해주자.
@SpringBootApplication
public class ApiApplication {
public static void main(String[] args) {
SpringApplication.run(ApiApplication.class, args);
}
}
잘 실행되는 모습을 볼 수 있다 :)
Reference
- https://hello-judy-world.tistory.com/204
- https://velog.io/@soyeon207/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-%EB%A9%80%ED%8B%B0-%EB%AA%A8%EB%93%88-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%A7%8C%EB%93%A4%EA%B8%B0
- https://dkswnkk.tistory.com/691
- https://velog.io/@jynam821/%EC%99%95%EC%B4%88%EB%B3%B4%EB%8F%84-%EA%B0%80%EB%8A%A5%ED%95%9C-Spring-Boot-%EB%A9%80%ED%8B%B0-%EB%AA%A8%EB%93%88-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0
- https://blogingming.tistory.com/entry/%EC%95%84%EC%A3%BC-%EA%B0%84%EB%8B%A8%ED%95%9C-Spring-Boot-%EB%B0%B0%ED%8F%AC