Search
Duplicate
📒

[Spring MSA] xx. 멀티모듈 아키텍쳐

상태
미진행
수업
Spring MSA
주제
Clean Architecture
4 more properties
참고

멀티 모듈 프로젝트를 만드는 이유

NOTE
모듈은 패키지의 한 단계 위의 집합이며 자바에서는 독립적으로 배포될 수 있는 코드의 단위이다!
MSA 서비스를 개발하다보면 각 서버에서 동작할 프로젝트가 필요하게되고 이를 하나의 단일 프로젝트로 개발하게 되면 다음과 같은 문제가 생긴다.
공통적으로 처리해야하는 코드의 처리
각 프로젝트의 공통되는 코드들은 각 프로젝트에 복붙해서 사용할 수 밖에 없다
한 파일의 코드가 수정된다면 다른 프로젝트의 코드도 수정해야 한다.
접근성 문제
프로젝트 수에 따라 IDE를 실행시켜야한다.
멀티 모듈로 개발하면 위에서 발생하는 문제들을 해결해줄 수 있다!
코드 재사용성
공통 기능을 하나의 모듈에 구축하고, 여러 모듈에서 활용한다.
기능 분리
모듈별로 기능을 분리해서 직관적인 프로젝트 관리가 가능하다.
빌드 유연성
루트 프로젝트에서 전체를 빌드할 수도 있고, 개별 모듈 별로 빌드할 수도 있다.
의존성 분리
전체 프로젝트에 의존성을 추가할 필요 없이, 개별 모듈에 필요한 의존성을 지정할 수 있다.

멀티 모듈 프로젝트 구성 1

NOTE
다음의 구성으로 멀티 모듈을 작성한다.
rootProject.name = "ordering-project" include( "order-service:order-application", "order-service:order-container", "order-service:order-dataaccess", "order-service:order-domain:order-application-service", "order-service:order-domain:order-domain-core", "order-service:order-messaging", )
Kotlin
복사
서브모듈을 등록시킨다. (settings.gradle.kts)
모듈 패키지
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile // 플러그인 선언 // Kotlin, Spring 관련 플러그인과, Springboot, 의존성 관련 플러그인 plugins { kotlin("jvm") version "1.9.20" kotlin("plugin.spring") version "1.9.20" apply false id("org.springframework.boot") version "3.2.0" apply false id("io.spring.dependency-management") version "1.1.4" apply false } // 자바 버전 설정 java { sourceCompatibility = JavaVersion.VERSION_17 } // 모든 프로젝트(루트 - 서브 모듈)에 공통적으로 적용 // 루트 프로젝트 포함 allprojects{ // 프로젝트 그룹 & 버전 설정 group = "com.example" version = "0.0.1-SNAPSHOT" // Maven 중앙 저장소 사용 repositories { mavenCentral() } } // 서브 프로젝트에만 적용될 설정 // root 프로젝트에 영향이 가지 않음 subprojects{ // 서브 프로젝트에 Kotlin 및 Spring Boot 관련 플러그인 적용 // 프로젝트의 빌드에 사용된다. (위에서 사용한 플러그인을 적용시킨것) apply(plugin = "org.jetbrains.kotlin.jvm") apply(plugin = "org.jetbrains.kotlin.plugin.spring") apply(plugin = "org.springframework.boot") apply(plugin = "io.spring.dependency-management") // bootJar 태스크 비활성화, jar 태스크 활성화 // 기본적으로 Spring Boot는 bootJar를 사용하지만, 일반 Jar 파일을 생성하려면 이렇게 설정 // 일반적인 서브모듈은 스프링이 없는 일반 빌드 Jar을 사용하도록 한다. tasks.getByName("bootJar"){ enabled = false } tasks.getByName("jar"){ enabled = true } // 공통 의존성 // 컴파일, 테스트 등에서 사용하는 외부 라이브러리나 모듈을 의미한다. dependencies { //implementation("org.springframework.boot:spring-boot-starter-web") implementation("com.fasterxml.jackson.module:jackson-module-kotlin") implementation("org.jetbrains.kotlin:kotlin-reflect") testImplementation("org.springframework.boot:spring-boot-starter-test") } // Kotlin 컴파일 옵션 tasks.withType<KotlinCompile> { kotlinOptions { freeCompilerArgs += "-Xjsr305=strict" jvmTarget = "17" } } // 테스트 태스크 섲렁 tasks.withType<Test> { useJUnitPlatform() } }
Kotlin
복사
rootmodule
allproject, subproject, project(모듈 이름)으로 원하는 범위만큼의 모듈에 원하는 설정을 할 수 있다.
// bootJar 태스크 활성화, jar 태스크 비활성화 // 이 설정은 서브 모듈에서 Spring Boot 실행 가능 Jar를 생성할 때 필요 tasks.getByName("bootJar"){ enabled = true } tasks.getByName("jar"){ enabled = false } // order-application-service 모듈의존 dependencies { implementation("org.springframework.boot:spring-boot-starter-web") implementation(":order-service:order-domain:order-application-service") }
Kotlin
복사
submodule (order-application)
여기서 bootJar의 경우 실행가능한 jar을 만들어야 하기 때문에, main()이 필요하다. 때문에 main()이 없는 경우는 flase로 설정해줘야 한다.

멀티 모듈 프로젝트의 구성 2

NOTE
다른 사람이 모듈을 설계한 이미지
api (프로젝트 루트)
api-core (api 공통)
공통 유틸을 비롯한 프로젝트 공통 기능 모듈
api-domain (api 데이터)
Service, Repositroy, Entity 등 데이터 모듈
api-web
컨트롤러를 비롯한 통신 모듈
dependencies { testImplementation("org.springframework.boot:spring-boot-starter-test") } tasks.bootJar { enabled = false } tasks.jar { enabled = true }
Kotlin
복사
:api-core
dependencies { testImplementation("org.springframework.boot:spring-boot-starter-test") } tasks.bootJar { enabled = false } tasks.jar { enabled = true }
Kotlin
복사
:api-domain
dependencies { api("io.springfox:springfox-boot-starter:3.0.0") implementation(project(":api-core")) implementation(project(":api-domain")) implementation("org.springframework.boot:spring-boot-starter-web") implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") testImplementation("org.springframework.boot:spring-boot-starter-test") }
Kotlin
복사
:api-web
api
해당 모듈을 의존하는 다른 모듈에도 노출된다.
implementation
현재 내 모듈내에서만 사용한다. (다른 모듈이 접근하지 못한다)

멀티 모듈 프로젝트의 구성 3

NOTE
@SpringBootApplication( scanBasePackages = {패키지 이름 작성}) public class ApiApplication { public static void main(String[] args) { SpringApplication.run(ApiApplication.class, args); } }
Kotlin
복사
별도의 설정을 하지 않는다면 Spring은 다른 모듈에 있는 클래스들을 Bean으로 등록하지 않는다.
위와 같이 scanBasePackage에 패키지 이름을 입력해야 정상적으로 Bean으로 등록된다!