본문 바로가기
개발 이야기/Springboot

Multi-module에서 Domain 분리하기

by 농개 2024. 2. 21.
반응형

Springboot로 API 서버 애플리케이션 등을 개발할 때 Multi-module을 채택 할 수 있습니다.

(요즘 핫하다고는 못하겠네요. 주목 받은지 꽤 시간이 흐른듯합니다 ㅎㅎ)

 

아래와 같은 Multi-module로 된 프로젝트가 있습니다.

Front APIBackoffice API를 개발하다보면

같은 도메인(예: DB Entity 및 Repository)을 사용할 때가 생길 수 있습니다.

중복코드가 많아 질 수 있는 상황입니다.

 

아래와 같이 Domain 모듈로 분리해주면 좀 더 세련된 코딩을 할 수 있을 것 같습니다.

 

이번 포스팅에서는 Multi-module에서 Domain(DB 의존성) 모듈을 분리하여 세팅할 때 필요한 작업을 정리해봅니다.

 

1. 프로젝트 구조

Project의 각 Module 구조는 아래와 같습니다.

├── backoffice-api
├── front-api
├── core
├── domain
├── gradle.properties
├── gradlew
├── build.gradle.kts
└── settings.gradle.kts

 

build.gradle.kts는 아래와 같습니다.

rootProject.name = "my-project"
include("backoffice-api")
include("front-api")
include("core")
include("domain")

 

 

2. Domain 모듈 작성

아래와 같이 domain 내에 build.gradle.kts를 작성합니다.

plugins {
    id("java")
}

group = "me.basket"
version = "0.0.1-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    api("org.springframework.boot:spring-boot-starter-data-jpa")
    api("mysql:mysql-connector-java:8.0.33")
}
// (중략...)
  • domain 모듈에서 jpa 의존성 추가시 implementation이 아닌 api로 해줘야함.
  • 만약 implementation으로 하게 되면, backoffice-api 모듈에서 jpa의 API(관련 annotaion 등)을 참조하지 못하게 됨.
<implementation과 api 의 차이점>

Gradle에서 implementationapi 구성은 종속성을 선언하는 데 사용되지만, 다른 범위를 갖습니다
implementation으로 선언된 종속성은 선언된 모듈에서만 보이며 하위 모듈로 전이되지 않습니다.
내부 구현 세부 정보에 사용되며 해당 모듈의 소비자에 노출되지 않습니다.
api로 선언된 종속성은 선언된 모듈과 해당 모듈에 의존하는 모듈 모두에서 볼 수 있습니다.
모듈의 공개 API의 일부이며 해당 모듈의 소비자에 노출됩니다.

 

Domain 모듈의 구조는 아래와 같이 구성했습니다.

└── me
    └── basket
        └── example
            ├── base
            │   ├── BaseEntity.kt
            └── domain
                ├── enums
                │   └── MemberCategory.kt
                ├── entity
                │   ├── MemberEntity.kt
                └── repository
                    ├── MemberRepository.kt

 

3. Api 모듈 작성

아래와 같이 backoffice-api 또는 front-api 의 build.gradle.kts를 작성해줍니다.

plugins {
    id("java")
}

group = "me.basket"
version = "0.0.1-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    implementation(project(":core"))
    implementation(project(":domain"))
    
    /* Springboot */
    implementation("org.springframework.boot:spring-boot-starter-web:3.1.4")
    implementation("org.springframework.boot:spring-boot-starter-actuator:3.1.4")
    
    // (...중략)
}
  • domain 모듈 의존성 추가에 implementation을 사용해줌.

 

4. Application Class 수정

위와 같이 domain을 모듈로 다른 패키지로 분리하게 되면

아래와 같은 작업을 해줘야합니다.

@SpringBootApplication
@EnableJpaRepositories(basePackages = ["me.basket.example.domain"])
@EntityScan(basePackages = ["me.basket.example.domain"])
class BackofficeApiApplication

fun main(args: Array<String>) {
    runApplication<BackofficeApiApplication>(*args)
}
  • 다른 패키지(domain 모듈 내)에 위치해 있는 @Entity, @Repository 등을 스캔이 필요.
  • 이를 위해서는 @EnableJpaRepository, @EntityScan을 통해 수동으로 패키지를 지정해줘야함.

 

위와 같이 간단하게 Domain을 모듈로 분리하고

의존성 관리를 좀 더 세련되게 할 수 있겠습니다.

 

반응형