• Feed
  • Explore
  • Ranking
/
/
    아키텍처

    멀티모듈 도입기

    멀티모듈 도입기
    아키텍처
    테
    테리
    2025.03.24
    ·
    6 min read

    항해99에서 1주차 미션을 수행하는데, 프로젝트를 멀티 모듈로 구성하라는 조건이 있었다. 계층적으로 패키지를 구성하는 것에 비해, 계층적으로 멀티모듈을 나누는 것이 어떤 이점이 있는지를 멘토님께 여쭈어 보았고, 그에 대한 답변은 다음과 같았다.

    계층을 패키지로 나누는 것과 멀티모듈로 나누는 것에는 기능적으로 큰 차이는 없습니다. 하지만 멀티모듈을 사용하면 계층 간 명확한 경계를 설정하고, 의존성을 강제할 수 있는 장점이 있습니다. 아래에 3가지 정도 예를 들어보면

    1. 의존성 제약

    A 모듈이 “도메인 계층”이고, B 모듈이 “서비스 계층”이라고 가정해 보겠습니다.

    • 만약 A 모듈이 B 모듈을 의존하지 않아야 한다면, 멀티모듈로 분리하여 B 모듈이 A 모듈을 참조하는 구조로 강제할 수 있습니다.

    • 반면, 패키지 구조에서는 접근제어자로 관리하는것이 제한적이고 어렵습니다.

    1. 라이브러리 종속성 관리

    각 모듈이 필요한 라이브러리만 포함할 수 있도록 강제할 수 있습니다.

    • 예를 들어 A 모듈은 JPA만 필요하고, B 모듈은 Redis를 필요로 한다면, A 모듈에서 Redis 관련 라이브러리를 실수로 가져다 쓰는 일을 방지할 수 있습니다.

    3. 코드 변경의 독립성

    • 특정 계층(A 모듈)이 상대적으로 변경이 적고 안정적인 모듈이라면, 이 모듈을 다른 모듈과 독립적으로 유지함으로써 불필요한 변경 전파를 방지할 수 있습니다.

    • 예를 들어, B 모듈(서비스 계층)에서 변경이 발생해도 A 모듈(도메인 계층)이 영향을 받지 않도록 보장할 수 있습니다.

    하지만, 실무에서는 강한 의존성 제약이 초기 개발 생산성을 낮출 수 있는 트레이드오프가 있습니다.

    • 초기에는 모듈 간의 분리와 의존성을 맞추는 데 시간이 더 걸릴 수 있고,

    • 작은 프로젝트에서는 오히려 불필요한 복잡성을 초래할 수도 있습니다.

    결론적으로, 멀티모듈을 계층적으로 나누는 것은 “강한 설계 원칙을 유지할 수 있는 수단”이지만, 프로젝트의 규모와 복잡도를 고려하여 적절하게 선택하는 것이 중요하다고 생각합니다.


    4267

    cinema-app-api

    dependencies {
        implementation project(":cinema-core")
        runtimeOnly project(":cinema-domain-rds")
    
        implementation 'org.springframework.boot:spring-boot-starter-web'
    }
    
    bootJar{
        enabled = true
    }
    
    jar{
        enabled = false
    }
    • 외부와 통신을 담당하는 모듈

    • cinema-core 모듈을 의존한다.

    • cinema-core로 부터 객체를 받아서, Response DTO로 반환한다.

    cinema-core

    dependencies {
        implementation 'org.springframework:spring-context'
    }
    • 핵심 비즈니스 로직 구현

    • 다른 모듈을 의존하지 않는다.

    cinema-domain-rds

    4268
    dependencies {
        compileOnly project(":cinema-core")
    
        // jpa
        implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    
        // mysql
        runtimeOnly 'com.mysql:mysql-connector-j'
    
        // querydsl
        implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
        annotationProcessor 'com.querydsl:querydsl-apt:5.0.0:jakarta'
        annotationProcessor "jakarta.annotation:jakarta.annotation-api"
        annotationProcessor "jakarta.persistence:jakarta.persistence-api"
    }
    • MySQL, JPA 의존

    • 단순 CRUD 연산

    • 저장소 특화 기능을 제공한다.

    • 데이터 조회 후, cinema-core에 있는 도메인 객체로 변환해서 전달한다.

    참고

    지속 성장 가능한 소프트웨어를 만들어가는 방법
    스프링은 국내에서 정말 많이 쓰이고 있습니다, 개인적으로 많은 회사를 다녀보며 주니어/시니어를 막론하고 많은 분들이 스프링에 함몰되어 개발을 하고 있다는 느낌을 받을 때가 많았고 이 점이 항상 아쉬웠습니다.
    https://geminikims.medium.com/%EC%A7%80%EC%86%8D-%EC%84%B1%EC%9E%A5-%EA%B0%80%EB%8A%A5%ED%95%9C-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4%EB%A5%BC-%EB%A7%8C%EB%93%A4%EC%96%B4%EA%B0%80%EB%8A%94-%EB%B0%A9%EB%B2%95-97844c5dab63
    지속 성장 가능한 소프트웨어를 만들어가는 방법

    https://techblog.woowahan.com/2637







    - 컬렉션 아티클