msa 프로젝트 구성 중 각 시스템(서비스)에서 공통으로 필요로 하는 코드들이 많았다.
이 중복을 줄이기 위해서 멀티 모듈로 관리하는 방법이 있다는 걸 알게되었다.
결론적으로 내 프로젝트에는 멀티모듈 구조가 적합하지 않다고 판단해서 적용하지 않았지만, 멀티 모듈에 대해 알아본 것들을 정리했다!
🔍1. 멀티 모듈 (Multi-module)이란?
- 멀티 모듈은 하나의 큰 프로젝트 내에서 여러 개의 모듈을 정의하는 방식.
- 단일 애플리케이션에서 여러 모듈로 나누어 관리하는 방식
- MSA에서는 서비스 간의 의존성 관리나, 공통 라이브러리 등을 관리하기 위해 멀티 모듈을 사용할 수 있다.
- 예시: common-utils라는 모듈을 만들고, 여러 서비스가 이 모듈을 의존성으로 추가하여 공통 기능(로그 처리, 유효성 검사, 예외 처리 등)을 공유.
📌2. 멀티모듈 구조가 적합한 경우
- 모든 서비스가 동일한 기술 스택(예: Spring Boot + Gradle)을 사용하는 경우.
- 각 서비스가 동일한 코딩 스타일과 공통 라이브러리를 사용하는 경우.
- 개발자 간 협업이 원활하고, 서비스 간 높은 결합도가 있어야 하는 경우.
- 각 서비스가 동일한 배포 주기를 가질 수 있는 경우.
📌3. 멀티모듈 구조가 적합하지 않은 경우
- 서비스마다 기술 스택이 다양한 경우.
- 예: 주문 서비스(Java), 사용자 서비스(Python).
- 서비스마다 DB가 달라서 독립적으로 관리해야 하는 경우.
- 예: MySQL, PostgreSQL, MongoDB 등 다양한 DB를 사용하는 경우.
- 서비스별 개발팀이 다르거나, 각 팀의 작업 속도가 크게 다른 경우.
- 각 서비스가 독립적으로 배포 및 테스트가 가능한 구조를 원할 때.
📌4. 대안: 독립 서비스로 관리
멀티모듈 대신 각 서비스를 독립적으로 관리하면서도, 공통 코드를 공유하는 방식
- 공통 코드(예: DTO, 유틸리티 등)를 별도의 공통 라이브러리 프로젝트로 관리.
- => Git 서브모듈이나 별도의 공통 라이브러리 Git 저장소를 만들어 공유.
- 각 서비스는 완전히 독립적으로 개발 및 배포.
- 서비스별로 독립적인 빌드 및 파이프라인을 설정.
📌5. 예시 (이벤트 기반 통신)
이벤트 기반 통신에서 발행하는 쪽과 수신하는 쪽의 Event 객체를 동일하게 사용.
root-module/
├── order-service/
│ └── 발행자
├── product-service/
│ └── 수신자
├── common-events/
└── OrderEvent.java
✔️ 장점
- 코드 재사용성: 발행 및 수신 양쪽에서 동일한 객체를 사용하므로 코드 중복을 방지.
- 일관성 유지: 이벤트의 스키마(필드 구조)가 항상 동일하게 유지. 이벤트를 발행할 때와 수신할 때 필드가 다를 위험x.
- 의존성 관리 용이: 공통 모듈로 이벤트 클래스를 두면, 발행 서비스와 수신 서비스 모두 해당 모듈을 의존성으로 추가해 사용할 수 있다.
- 테스트 효율성 증가: 동일한 이벤트 객체를 사용하면, Mocking이나 Serialization 테스트 시 같은 클래스를 사용할 수 있어 효율적.
✔️ 고려할 점
- 서비스 간 강결합 가능성
- 공통 이벤트 객체를 사용하면 서비스 간 간접적인 의존성이 생김.
- 이를 완화하려면 공통 모듈의 변경을 신중히 하고, 이벤트 버전 관리(예: OrderEventV1, OrderEventV2)를 도입해야함.
- 모듈 간 독립성 손상 가능성
- 각 서비스가 독립적으로 배포되고 관리되어야 하는 경우, 공통 이벤트 클래스에 변경이 생기면 각 서비스의 독립 배포 주기를 방해할 수 있다.
- 메시지 호환성
- 발행자가 오래된 이벤트를 사용하고, 수신자가 새 이벤트를 수신할 경우 호환성 문제가 발생할 수 있다. JSON 직렬화 구조를 유연하게 처리하거나 필드 추가만 허용하는 방식으로 관리해야함.
- 직렬화 라이브러리
- 이벤트 객체를 직렬화/역직렬화하는 라이브러리(예: Jackson, Gson) -> 같은 직렬화 라이브러리를 사용하는 것을 권장.
📌6. 공통 모듈 설정 방법
common 모듈은 공통 코드를 포함하는 별도의 프로젝트로 만들고, 각 서비스가 이를 참조하도록 설정할 수 있다.
✅ 방법 1: JAR 파일로 사용
1️⃣common 모듈을 빌드하여 JAR 파일을 생성, 파일은 common/build/libs/에 생성된다.
cd common
./gradlew build
2️⃣각 서비스의 build.gradle에 common JAR 파일을 의존성으로 추가합니다.
dependencies {
implementation files('../common/build/libs/common-0.0.1-SNAPSHOT.jar')
}
✅ 방법 2: 로컬 프로젝트 참조
1️⃣각 서비스의 build.gradle에서 common 폴더를 직접 참조하도록 설정.
service-a/build.gradle
dependencies {
implementation project(':common')
}
2️⃣상위 settings.gradle에서 common 모듈을 포함시킨다.
workspace-folder/settings.gradle
include ':common', ':service-a', ':service-b', ':service-c'
'Backend > spring cloud (MSA)' 카테고리의 다른 글
| MSA 필수 개념 (0) | 2025.09.01 |
|---|---|
| OpenFeign: MSA 서비스 간 통신 (0) | 2025.04.10 |
| 데이터 통합 조회 방법 설계 (0) | 2025.04.06 |
| MSA 환경에서 인증/토큰 재요청 (0) | 2025.04.06 |
| 실시간 데이터 전송 (0) | 2025.02.23 |