* 모듈(Module) : 독립적으로 배포될 수 있는 코드의 단위
멀티 모듈(Multi-Module) : 코드 뭉치를 하나의 프로젝트 안에서 관리하는것
모듈별 책임을 분리하고 유지보수성과 확장성을 확보하기 위해 멀티모듈을 도입
멀티모듈의 설계 / 구조는 계층 기반으로 구성
하나의 프로젝트를 여러 개의 모듈로 나누어 관리
최상위 프로젝트(root)와 여러 개의 하위 모듈(module)로 구성
project-root/
├── module-api/
│ ├── controller/
│ ├── dto/
│ ├── resources/
│ └── build.gradle
├── module-service/
│ ├── service/
│ ├── utils/
│ └── build.gradle
├── module-domain/
│ ├── entity/
│ ├── repository/
│ └── build.gradle
├── module-core/
│ ├── conf/
│ ├── utils/
│ └── build.gradle
└── build.gradle (루트 설정)
project-root: 전체 프로젝트를 대표하는 루트 프로젝트로, 공통적인 빌드 설정을 관리
module-*: 각 모듈은 서로 다른 기능을 담당
module-api: 컨트롤러 및 외부와의 통신을 처리
module-service: 비즈니스 로직과 서비스 계층을 관리
module-domain: 데이터 모델 및 데이터 접근 계층을 관리
module-core: 공통 모듈로, 여러 모듈에서 재사용 가능한 유틸리티 및 설정 포함
멀티모듈의 주요 특징
1. 모듈화로 인해 코드 분리가 명확함
각 모듈은 특정한 책임만을 가지며 서로 독립적
결합도를 낮추고 응집도를 높이는 설계가 가능
2. 재사용성
공통적인 로직이나 유틸리티를 module-core 같은 공통 모듈에 작성하여, 다른 모듈에서 재사용 가능
3. 빌드 및 배포 효율성
변경 사항이 있는 모듈만 빌드하여 배포할 수 있어 빌드 시간을 단축
Gradle이나 Maven을 사용하면 하위 모듈의 의존성과 빌드 순서를 관리 가능
4. 팀 협업 효율성
각 팀이 서로 다른 모듈을 개발하도록 나누어 작업 가능
충돌을 최소화하고 생산성 증가
멀티모듈 프로젝트의 장점
유지보수성: 각 모듈이 독립적이므로 변경 사항의 영향 범위가 작음
확장성: 새로운 기능을 추가할 때, 기존 모듈에 영향을 주지 않고 새로운 모듈로 추가 가능
재사용성: 특정 모듈을 여러 프로젝트에서 재사용 가능
의존성 관리: 각 모듈이 개별적으로 의존성을 관리하므로 필요하지 않은 의존성을 배제할 수 있음
경험한 어려움 및 해결 방안
경험한 어려움 및 해결 방안
1: 의존성 관리의 어려움
module-service에서도 @Transactional을 사용하려면 spring-boot-starter-data-jpa가 필요
해결 : JPA 의존성을 추가
2. 멀티모듈 간 의존성 순환 문제
module-core는 최대한 독립적으로 설계하고 PoJo 기반 순수 자바 클래스로 구성
단방향 의존성을 유지하여 의존성 순환 방지
3. 멀티모듈에서 공통 설정 (Config 파일) 관리
공통 모듈의 역할을 명확하게 정리 → module-core가 비대해지지 않도록 주의
*. Config 위치
api 로 가는 경우
- WebMvcConfig: API 요청/응답 설정 (예: 메시지 컨버터, CORS 등)
- SwaggerConfig: Swagger 문서화 설정
- SecurityConfig: API 인증/인가 관련 설정 (Spring Security, OAuth)
- RestTemplateConfig: 외부 API 호출을 위한 RestTemplate 설정
core 로 가는 경우
- LoggingConfig: 로깅 설정
- GlobalExceptionHandler: 전역 예외 처리
- CommonConstants: 프로젝트 전반에서 사용하는 상수들
- EncryptionConfig: 암호화 관련 공통 설정
그 외
- feign : service 또는 (특정 API 모듈에서만 사용된다면) api
- Redis : 캐싱 또는 비즈니스 로직과 관련(service), 또는 core
- JPA Config (Audit 등) : domain
멀티 모듈 적용
1. 모듈단위로 잘게 쪼개서 사용하고 싶어서 사용 (재활용)
2. api / consumer(kafka) / batch > service > domain > common
- 엔트리포인트(=접근하는 컨트롤러) 부터 시작
- core(=common)에는 어떤 엔트리포인트에도 문제없는(=특정기술에 종속 X) 순수한 포조객체 , Utils 메소드
- domain에는 POJO(plain old Java Object), pojo + entity = jpa entity
- 항상 단방향 ex. service 모듈 에서 common implement
멀티 모듈 회고
1. Api 모듈
- api 모듈은 프로젝트의 엔트리 포인트
- 외부로부터의 요청을 처리하는 컨트롤러와 데이터 전달을 위한 객체인 DTO(Data Transfer Object) 포함
- 그 외 AOP, 공통 설정, 예외 처리 등을 포함
- 최상위 계층으로 외부와의 직접적인 인터페이스 역할을 하며, 모든 하위 모듈을 참조할 수 있는 구조로 설계
- API의 단순히 요청을 라우팅하고 데이터를 가공하는 역할에 집중해야 한다고 생각
- 그 외 추가적으로 배치, 컨슈머와 같은 다른 엔트리 포인트와도 구조적으로 통일성을 유지
2. Service
- 핵심 비즈니스 로직을 처리하고 데이터의 흐름을 제어하는 중간 계층
- Domain 모듈과 협력하여 데이터 조작 및 검증을 처리하며, API 모듈로부터 요청을 전달받아 로직을 수행
- 단방향 의존성을 유지하면서 Core 및 Domain 모듈만 참조
- VO(Value Object) 비즈니스 로직과 관련된 값 객체를 포함
3. Domain 모듈
- 프로젝트의 핵심 데이터를 정의하고, 데이터 접근 계층을 처리하는 중요한 역할
- POJO 기반의 엔티티와 JPA를 활용한 레포지토리 계층으로 구성
- 특정 비즈니스 로직이 없는 순수한 데이터 계층으로 유지
- module-core만 참조하도록 설계하여, 특정 비즈니스 로직이 없는 순수한 데이터 계층으로 유지
- 다른 모듈에서 도메인 객체를 재사용할 수 있도록 돕고, 데이터 계층과 비즈니스 로직 간의 결합도를 낮춤
- JPA 엔티티와 레포지토리를 포함하여 특정 기술 스택(JPA)에 종속적일 수 있음
4. Core 모듈
- 공통적으로 사용되는 유틸리티와 설정을 모아둔 가장 하위 계층
- 특정 기술 스택에 종속되지 않고,
배치 작업이나 다른 엔트리 포인트에서도 독립적으로 활용될 수 있도록 POJO 기반의 순수한 자바 클래스로 구성
- 모든 모듈에서 재사용 가능한 코드를 포함하며, JPA와 같은 기술 의존성을 철저히 배제
- 기술 변경이나 새로운 기능 추가 시에도 유연하게 대응할 수 있도록 설계
- ex. 공통 예외 처리나 유틸 메서드처럼 어디서나 필요한 기능
5. Config 위치
api 로 가는 경우
- WebMvcConfig: API 요청/응답 설정 (예: 메시지 컨버터, CORS 등)
- SwaggerConfig: Swagger 문서화 설정
- SecurityConfig: API 인증/인가 관련 설정 (Spring Security, OAuth)
- RestTemplateConfig: 외부 API 호출을 위한 RestTemplate 설정
core 로 가는 경우
- LoggingConfig: 로깅 설정
- GlobalExceptionHandler: 전역 예외 처리
- CommonConstants: 프로젝트 전반에서 사용하는 상수들
- EncryptionConfig: 암호화 관련 공통 설정
5. 그 외
feign : service 또는 (특정 API 모듈에서만 사용된다면) api
Redis : 캐싱 또는 비즈니스 로직과 관련(service), 또는 core
JPA Config (Audit 등) : domain
참고 :
https://www.youtube.com/watch?v=ipDzLJK-7Kc
https://www.youtube.com/watch?v=uvG-amw2u2s
https://www.youtube.com/watch?v=nH382BcycHc
https://techblog.woowahan.com/2637/
https://jojoldu.tistory.com/123
https://mangkyu.tistory.com/304
더보기
# 전체 빌드 (test 제외)
./gradlew build --stacktrace --info -x test
# 특정 모듈 빌드 # main 없는 경우 (common, domain, infra)
./gradlew :{project-name}-domain:build
# main 있는 경우 (api)
./gradlew :{project-name}-domain:bootJar
bootJar : dependecies와 클래스 파일을 모두 묶어서 빌드
jar : 클래스만 묶어서 빌드
'Spring' 카테고리의 다른 글
디버깅 모드 (0) | 2025.01.19 |
---|---|
FeignClient (1) | 2025.01.19 |
API(application programming interface), RestAPI (0) | 2023.05.22 |
웹 동작방식, HTTP, WAS, Web Server (0) | 2023.05.21 |
SOLID 원칙 (0) | 2023.04.07 |