티스토리 뷰

멀티모듈이란

한 프로젝트 안에 여러 개의 모듈이 존재하는 것을 말합니다.

모듈은 작은 프로젝트라고 생각하면 될 것 같습니다.

 

멀티모듈 장점

  1. 모듈마다 필요한 의존성을 설정할 수 있어서 응집도 높은 코드 작성 가능
  2. 루트 프로젝트에서 전체 모듈의 의존성 관리 가능
  3. 중복되는 코드를 모듈로 분리하여 코드 중복을 줄임
  4. 독립적으로 배포 가능

 

멀티모듈 사용이유

토이 프로젝트에서 배치를 사용하게 되었습니다.

배치 서버는 실시간으로 처리하기 어려운 대용량 데이터를 다룰 때 사용합니다.

 

API 요청과 배치 작업이 서로에게 영향을 주어 서버에 부하가 집중되는 것을 방지하기 위해 분리했습니다.

 

멀티모듈 생성

루트 프로젝트 우클릭 후 Module... 을 클릭합니다.

 

 

모듈 이름과 필요한 의존성을 추가합니다. (프로젝트를 생성하는 것과 동일)

그리고 생성된 모듈 안에 build.gradle 제외 다른 파일들은 지웁니다.

 

 

모듈을 생성한 다음 루트 프로젝트의 settings.gradle 파일에 모듈의 이름을 추가합니다.

 

 

멀티모듈 의존성 관리

루트 프로젝트의 build.gradle에서 플러그인과 의존성을 전체 모듈에 적용할 수 있습니다.

각 모듈의 필요한 의존성만 build.gradle에 남기 때문에 가독성과 응집도를 높일 수 있습니다.

 

plugins {
    id 'java'
    id 'java-library' // 밑에 나올 api 키워드를 사용하기 위해 추가
    // 루트 프로젝트에 적용하지 않고 하위 모듈에서만 사용
    id 'org.springframework.boot' version '3.3.1' apply false 
    id 'io.spring.dependency-management' version '1.1.5' apply false
}

subprojects {
    apply plugin: 'java'
    apply plugin: 'java-library'
    apply plugin: 'org.springframework.boot'
    apply plugin: 'io.spring.dependency-management'

    group = 'io.address'
    version = '0.0.1-SNAPSHOT'

    java {
        toolchain {
            languageVersion = JavaLanguageVersion.of(17)
        }
    }

    repositories {
        mavenCentral()
    }

    configurations {
        compileOnly {
            extendsFrom annotationProcessor
        }
    }

    dependencies {
    	// Lombok, 테스트와 같이 프로젝트 전체에서 사용되는 의존성은 루트 프로젝트에서 관리
        implementation 'org.springframework.boot:spring-boot-starter-web'

        compileOnly 'org.projectlombok:lombok'
        annotationProcessor 'org.projectlombok:lombok'

        testImplementation 'org.springframework.boot:spring-boot-starter-test'
        testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
    }
    
    tasks.named('test') {
        useJUnitPlatform()
    }
}

 

allprojects subprojects
루트 프로젝트를 포함해 하위 프로젝트 전체에 영향을 주는 설정 하위 프로젝트 전체에 영향을 주는 설정

 

그리고 각 모듈의 build.gradle에는 필요한 의존성만 추가해 주었습니다.

 

// 배치 모듈 build.gralde
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-batch'
    implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
    testImplementation 'org.springframework.batch:spring-batch-test'
}

ext {
    set('springCloudVersion', "2023.0.2")
}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}

 

 

중복 클래스 domain 모듈로 분리

개발을 하면서 모듈마다 엔티티 클래스가 중복되었습니다.

중복 클래스가 계속해서 증가하게 되면 프로젝트를 관리하기 힘들 것 같아서 공통 엔티티 클래스를 묶는 domain 모듈을 만들었습니다.

 

dependencies {
    api 'org.springframework.boot:spring-boot-starter-data-jpa'
    runtimeOnly 'com.mysql:mysql-connector-j'
}

// domain 모듈은 독립적으로 실행되지 않음
bootJar {
    enabled = false
}

 

domain 모듈은 독립적으로 실행되지 않기 때문에 Main 클래스도 필요하지 않습니다.

 

api vs implementation

batch -> domain -> JPA (의존 방향)

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

 

domain 모듈이 JPA를 implementation 키워드를 사용해 의존하면

batch 모듈은 domain 모듈의 클래스는 사용할 수 있지만, JPA 관련 클래스는 사용할 수 없습니다.

 

api 'org.springframework.boot:spring-boot-starter-data-jpa'

 

domain 모듈이 JPA를 api 키워드를 사용해 의존하면

batch 모듈은 domain 모듈의 클래스와 JPA 관련 클래스를 사용할 수 있습니다.

api를 사용하면 참조할 수 있는 범위를 넓힐 수 있어 개발하기 편합니다.

 

하지만 JPA를 다른 데이터 접근 기술로 변경하게 된다면, 배치 모듈까지 영향을 받아 코드를 수정하는 범위가 커져 관리하기 힘들게 됩니다.

따라서 api 키워드를 최대한 멀리하고, 개발하는 게 좋을 것 같습니다.

 

 

domain 모듈 db.yml 

domain 모듈 reources 패키지에 db.yml 파일을 만들고, db 관련 설정을 해주었습니다.

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://${DB_URL}:${DB_PORT:3306}/${DB_NAME}?useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Seoul&allowPublicKeyRetrieval=true
    username: ${DB_USERNAME:root}
    password: ${DB_PASSWORD}

  jpa:
    database-platform: org.hibernate.dialect.MySQL8Dialect
    hibernate:
      ddl-auto: none
    open-in-view: false
    properties:
      hibernate:
        format_sql: true
        show_sql: true

 

 

그리고 db 설정을 다른 모듈에서 사용할 수 있도록 spring.config.import 프로퍼티를 사용했습니다.

spring.config.import 프로퍼티를 사용하면 중복 코드 없이 쉽게 설정 파일을 적용할 수 있습니다.

# batch 모듈의 yml 파일
server:
  port: 8081

spring:
  config:
    import:
      - db.yml

  batch:
    job:
      enabled: false

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/03   »
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
글 보관함