모놀리틱 아키텍처
- 단일 모듈 멀티 프로젝트
멀티 모듈 구조란
- 프로젝트를 논리적인 단위로 분리하여 각 모듈이 독립적으로 기능하는 구조
장점
- 각 모듈이 독립적으로 기능함으로써, 전체 시스템의 안정성과 확장성을 보장함 → 복잡성을 관리하고 생산성이 향상됨
- 코드의 재사용성을 높이고, 팀 간의 협업을 강화함 → 모듈화를 통해 공통 기능을 분리하고, 각 팀이 독립적으로 모듈을 개발할 수 있기 때문
- 각 모듈이 독립적인 빌드와 배포 주기를 가질 수 있음 → 독립적인 개발 환경을 구성할 수 있기 때문
단, 멀티 모듈 구조의 적용은 프로젝트의 초기 설계 단계에서부터 고려되어야 함 → 모듈간의 의존성과 인터페이스를 명확하게 정의하는 것이 중요하기 때문 (잘 못 정의 하면 스파게티 코드가 됨)
멀티 모듈 구조의 적용 방법
- 프로젝트를 분리할 기준을 정의해야 함 → 이 기준에 따라 모듈을 분리하고, 각 모듈의 역할을 정의하기 때문
- 각 모듈의 의존성을 관리하는 방법을 결정해야 함 → 의존성 관리는 프로젝트의 안정성과 확장성에 직접적인 영향을 미치기 때문
- 모듈별로 독립적인 빌드와 배포 환경을 구성해야함 → 각 모듈의 개발과 배포를 효율적으로 관리할 수 있기 때문(이건 서비스 마다 모듈을 분리할 때 해당되지 않을까…? 주문, 배달 이런식으로.. )
- 모듈 간의 인터페이스를 명확하게 정의하고, 공통 기능은 별도의 모듈로 분리해야 함
- 멀티 모듈 구조의 적용은지속적인 리팩토링과 개선 과정을 통해 이루어짐
좀 더 찾아보니 멀티 모듈 구조 적용 방법 중 도메인 관점과 백엔드 개발 관점으로 나뉜다.
도메인 관점 모듈화
- 도메인 관점에서는 모듈을 유저, 책, 주문 등과 같이 비즈니스 도메인 단위로 나눔 장점
-
팀 단위 작업 분리 : 도메인 단위로 팀을 나누어 병렬 작업이 가능해짐
-
유지보수 용이성 : 특정 도메인의 변경이 다른 도메인에 영향을 미치지 않으므로, 수정과 확장이 용이함
-
비즈니스 로직 집중 : 각 도메인이 독립적으로 관리되기 때문에 비즈니스 로직을 명확하게 분리하고 집중할 수 있음
-
확장성 : 새로운 도메인을 추가할 때 기존 도메인에 영향을 미치지 않고 쉽게 추가 가능
단점
-
중복 코드 : 도메인 간에 중복 코드가 발생함
-
의존성 관리 복잡성
-
초기 설계 복잡성
→ 도메인 관점 모듈화를 보니, 각각 도메인이 명확하게 나뉘어져 있는 대기업의 경우 적합할 것 같다는 생각이 든다. EX) 배달의 민족 - 주문, 결제, 배달 등 또한 MSA로 변경이 더 쉽지 않을까 예상한다.
백엔드 개발 관점
- 아키텍처를 기준으로 분리하는 것이다. (이 관점은 팀바팀, 사바사로 조금씩 차이가 있는 것 같다.)
- 계층형 아키텍처 : 컨트롤러, 서비스 , 레포지토리(도메인) 등을 각각 다른 모듈로 분리함
- 관련된 서버를 기준으로 분리함 (컨트롤러 + 서비스 , 레포지토리 + 엔티티, 외부 API, 배치 서버 등)
보통 사이드 프로젝트에서 많이 사용하는 구성은 관련된 서버를 기준으로 분리하는 것이다.
레이어 구상 공부
내부 모듈
- 시스템과는 연관이 있는 모듈
- 애플리케이션, 도메인의 비즈니스를 모른다.
역할 예시
- 외부 API 요청 응답 (Restemplate, WepClient)
- Web Filter를 이용한 보안
- 로깅
- 메시지 큐
규칙
- 예외가 모듈 밖으로 절대 빠져나가지 안에서 처리하도록 구성한다.
- 외부에서 이 모듈을 사용할 때는 예외를 핸들링하지 않고 성공/실패 여부만 판단해서 비즈니스를 수행하도록 한다.
도메인 모듈
- 도메인을 알고 있다.
- 애플리케이션 비즈니스를 모른다.
- 하나의 모듈은 최대 하나의 인프라스트럭처에 대한 책임만 갖는다.
- 도메인 모듈을 조합한 더 큰 단위인 도메인 모듈이 있을 수 있다.
- 도메인 모듈을 구성할 때는 객체지향 설계를 전제로 하고 있다.
역할 예시
- 도메인(엔티티)
- 도메인이 가져야할 서비스 (트랜잭션 단위)
규칙
- 하나의 모듈은 최대 하나의 인프라스트처만 책임지도록 모듈을 작성하는 것이 좋음
- 다양한 인프라스트럭처를 사용하게 될 때 점점 지옥이 열리기 때문!
- 그러나 두 인프라스트럭처 사이의 관계가 생길 때는 두 모듈을 품는 모듈을 작성하거나 두 인프라스트럭처 모듈을 품는 어플리케이션에서 처리가 좋음
독립 모듈
- 시스템과 관련 없이 자체로서 독립적인 역할을 갖는다.
- 인프라스트럭쳐 연동 사용성 제공
- Object Mapping 기능 제공
역할 예시
규칙
- 똑 떼어내서 오픈소스화 해도 괜찮은 정도의 모듈로 한정짓는다.
- 즉 자체적으로 독립적인 역할을 갖는다.
공통 모듈
- Type, Util 등을 정의한다.
- 가능하면 사용하지 않는다.
역할 예시
규칙
- 가능하다면 이 모듈을 사용하지 않는다.
- 의존성을 절대 가져가지 않는다.
- 자바를 순수하게 사용할 수 있는 것 외에는 불가능하다.
공통 모듈이 두꺼워지면 스파게티 코드가 된다…
애플리케이션 모듈
- 독립적으로 실행 가능한 어플리케이션 모듈
- 하위 설계했던 모듈들을 조립하여 서비스 비지니스를 완성시키는 모듈
역할 예시
- Controller
- API 문서화 (Swagger)
규칙
- 각 모듈들을 필요에 맞게 의존하면서 비즈니스 로직을 수행한다.
나의 생각
- 공부를 해보니 기존의 레이어 아키텍쳐 (Controller - Service - Repository)대로 분리를 한다. 다만 공통 모듈은 최대한 지양하는 조건이었다. 또한 예상한대로 외부 요청 로직은 하나의 모듈로 분리를 한다. 그러나 멀티 모듈을 지나치게 세분화한다면 모듈 구조를 처음 접하거나 익숙하지 않는다면 뇌에 과부하가 발생할 수 있을 것 같다. 따라서 모듈의 구조를 최대한 단순하고 직관적으로 분리하는 것이 좋을 것 같다. (클린하게 분리하려고 무자비로 모듈을 늘리는 것이 안 좋다는 의미..)
참고
멀티 모듈 구조의 이해와 적용 방법
멀티모듈 설계 이야기 with Spring, Gradle | 우아한형제들 기술블로그
우아한 멀티 모듈 세미나 정리
스프링 부트 단일 모듈 코드에 멀티 모듈을 적용하여 프로젝트 구조 개선하기