[단편] 멀티모듈 설계 고민 이야기

황제연·2025년 3월 4일
post-thumbnail

서론

2024 한국관광데이터 공모전에서 진행했던 Photoravel 프로젝트를 대상으로 정리한 글입니다.
초기 설계 과정에서 멀티모듈화를 고려했으나, 프로젝트의 규모와 복잡성을 감안했을 때
적절하지 않다고 판단하여 단일 모듈 구조로 개발했습니다.

당시에는 멀티모듈화를 반대하는 입장이었지만,
프로젝트가 완료된 이후 과연 그 선택이 옳았는지 다시 검토하고자 이 글을 작성했습니다.

멀티모듈이란 무엇인가?

먼저, 모듈이란 독립적으로 개발 및 배포할 수 있는 패키지들의 묶음을 의미합니다.
하나의 모듈로 구성된 프로젝트를 단일 모듈 프로젝트라 하며,
여러 개의 모듈로 구성된 프로젝트를 멀티모듈 프로젝트라고 합니다

단일 모듈의 한계

과거에는 대부분의 프로젝트가 단일 모듈로 구성되었습니다.
당시에는 프로젝트의 규모가 작았기 때문입니다.

하지만 현대의 프로젝트는 점점 규모가 커지고 있으며, 새로운 기능과 서비스가 추가되면서 공통된 코드가 많아지고 있습니다.
이에 따라 동일한 코드를 여러 번 복사하여 사용하는 비효율적인 작업이 증가하고,
프로젝트가 커질수록 코드 관리가 어려워지는 문제가 발생합니다.
또한, 여러 프로젝트에서 동일한 코드를 사용하기 위해 IDE나 인스턴스를 여러 개 실행해야 하고,
패키지 간 의존성이 강해져 하나의 변경이 여러 곳에서 오류를 발생시킬 수 있습니다

멀티모듈의 등장

이러한 문제를 해결하기 위해 등장한 것이 멀티모듈입니다.
멀티모듈을 적용하면 중복 코드가 줄어들고, 여러 프로젝트를 하나의 IDE나 인스턴스에서 실행할 수 있습니다.
또한, 각각의 모듈이 독립적인 역할을 담당하기 때문에 패키지 간 의존성이 낮아집니다.

이를 통해 특정 기능을 수정할 때 전체 프로젝트를 빌드할 필요 없이 해당 모듈만 리빌드하면 되고,
버그가 발생해도 해당 모듈만 검토하면 되므로 유지보수가 용이해집니다.

프로젝트의 구조 파악

멀티모듈 적용 여부를 검토하기 전에, 먼저 Photoravel 프로젝트의 구조를 정리했습니다.

도메인과 공통 기능

현재 Photoravel 프로젝트는 6개의 주요 도메인과 4개의 공통 기능을 포함하고 있습니다.

도메인 간 의존성

대부분의 도메인은 서로 독립적이지만 Member 도메인에 대한 의존성은 높았습니다.


특히, Member와 Photographer 도메인은 Matching 기능과도 연결되어 있어 상호 의존성이 강한 구조를 보였습니다.

멀티 모듈이 좋은 선택일까?

현재 프로젝트에서 모듈화할 수 있는 대상은 도메인 영역과 공통 기능입니다.
하지만 프로젝트의 규모를 고려했을 때 모듈을 나누기에는 크기가 작으며,
도메인 간 의존성이 강하기 때문에 도메인 단위로 나누는 것도 적절하지 않습니다.

또한, 프로젝트는 확장성을 고려하지 않은 상태이며 현재 추가 개발 계획이 없으므로 기능 확장 가능성도 크지 않습니다.
만약 멀티모듈로 변경한다면, 배포가 복잡해지고 설정이 늘어나면서 관리해야 할 요소도 증가하게 됩니다.

특히, Member 모듈을 분리할 경우 거의 모든 기능이 Member 모듈을 필요로 하기 때문에 항상 함께 배포해야 합니다.
이로 인해 배포 단위가 커지고, 멀티모듈의 장점인 독립 배포의 이점이 사라집니다.

또한, 단일 모듈에서는 Gradle 빌드 설정을 한 곳에서 관리하면 되지만,
멀티모듈로 변경하면 각 모듈마다 별도의 Gradle 설정 파일을 작성해야 합니다.
이는 관리 포인트를 증가시키는 요소입니다

따라서 현재 프로젝트는 멀티모듈의 장점보다 단점이 더 크다고 판단되었기 때문에,
단일 모듈 구조를 유지하기로 결정했습니다.

패키지 정리

└─trendravel
    └─photoravel_be
        ├─common
        │  ├─authentication
        │  │  ├─controller
        │  │  ├─dto
        │  │  ├─oauth2
        │  │  │  ├─service
        │  │  │  └─social
        │  │  ├─security
        │  │  │  ├─accessHandler
        │  │  │  ├─entryPoint
        │  │  │  └─filter
        │  │  ├─service
        │  │  ├─session
        │  │  └─token
        │  │      ├─helper
        │  │      ├─model
        │  │      └─service
        │  ├─exception
        │  │  ├─error
        │  │  └─exceptionhandler
        │  ├─image
        │  │  ├─event
        │  │  │  └─eventHandler
        │  │  ├─service
        │  │  ├─util
        │  │  └─valid
        │  └─matching
        │      ├─controller
        │      ├─dto
        │      │  ├─request
        │      │  └─response
        │      └─service
        ├─config
        ├─db
        │  ├─enums
        │  ├─guidebook
        │  ├─inmemorydb
        │  │  ├─entity
        │  │  └─repository
        │  ├─location
        │  ├─match
        │  │  └─enums
        │  ├─member
        │  ├─photographer
        │  ├─respository
        │  │  ├─guidebook
        │  │  ├─location
        │  │  ├─matching
        │  │  ├─member
        │  │  ├─photographer
        │  │  ├─review
        │  │  └─spot
        │  ├─review
        │  │  └─enums
        │  └─spot
        ├─domain
        │  ├─guidebook
        │  │  ├─controller
        │  │  ├─dto
        │  │  │  ├─request
        │  │  │  └─response
        │  │  └─service
        │  ├─location
        │  │  ├─controller
        │  │  ├─dto
        │  │  │  ├─request
        │  │  │  └─response
        │  │  └─service
        │  ├─member
        │  │  ├─controller
        │  │  ├─convertor
        │  │  ├─dto
        │  │  └─service
        │  ├─photographer
        │  │  ├─controller
        │  │  ├─dto
        │  │  │  ├─request
        │  │  │  └─response
        │  │  └─service
        │  ├─review
        │  │  ├─controller
        │  │  ├─dto
        │  │  │  ├─request
        │  │  │  └─response
        │  │  └─service
        │  └─spot
        │      ├─controller
        │      ├─dto
        │      │  ├─request
        │      │  └─response
        │      └─service
        └─util
            └─response

멀티모듈을 적용하지 않는 대신,
패키지 구조를 정리하여 개발 편의성을 높였습니다.

마무리

초기 설계 시, 멀티모듈을 반대한 이유는 복잡성과 유지보수의 어려움 때문이었습니다.
하지만 당시에는 이를 구체적으로 설명할 수 있을 만큼 깊이 이해하지 못했습니다.

이번 정리를 통해서 멀티모듈의 단점을 보다 명확하게 인식할 수 있었으며, 추가적인 문제점도 발견했습니다
결국, 현재 프로젝트의 특성과 요구 사항을 고려할 때 단일 모듈 구조를 유지한 것이 옳은 선택이었다는 생각이 듭니다.

이 경험을 바탕으로 앞으로도 상황에 맞는 최적의 구조를 선택하며, 개발 과정에 잘 녹여나갈 수 있기를 기대합니다.

참고

profile
Software Developer

0개의 댓글