기존의 진행했던 프로젝트는 소규모의 프로젝트였고 개발의 완성이 목표였던 프로젝트였기 때문에 하나의 모듈에 모든 로직이 통으로 들어있는 구조로 개발을 하였다.
이를 모놀리틱 아키텍처라고 한다. 모놀리틱 아키텍처는 소프트웨어를 하나의 독립적인 단위로 개발하고 운영하는 방식이다. 이는 개발, 테스트, 배포가 간단하고 모든 컴포넌트가 동일한 도메인을 공유함으로 호환성 문제가 적다. 또한 여러 서비스 간의 네트워크 호출이 없어 성능이 비교적 뛰어날 가능성이 높다.
그러나 이 아키텍처는 서비스의 규모가 커지면 유지보수가 어렵고, 버그 발생시 서비스 전체가 문제가 생길 수 있다. 확장성 또한 제한적일 수 있어 대규모 프로젝트에는 적합하지 않다.
그래서 MSA(Micro Service Architecture)가 등장한 것인데 상황과 환경에 맞는 아키텍처를 설계하는 것이 중요하다.
기존의 프로젝틀를 진행할 때는 모놀리틱 아키텍처로 하나의 모듈에 모든 코드가 있다보니 아무리 패키지로 관심사를 분리해도 프로젝트의 크기가 커지면서 코드의 복잡성이 높아졌다. 그래서 이번에는 각각의 모듈에 관심사를 분리하여 프로젝트의 크기가 커지더라도 분리된 모듈을 통해 복잡성을 관리할 수 있을 것 같아 멀티 모듈을 선택하였다.
또한 유지보수성 측면에서 멀티 모듈을 선택하였는데, 전에는 코드를 변경하면 그에 대응하는 사이드 이펙트가 전체 코드에서 발생하였다. 그러나 멀티 모듈을 사용함으로써 각각의 모듈의 의존성이 비교적 독립적이기 때문에 사이드 이펙트로부터 좀 더 관리하기에 편했다.
추가적으로, MSA 환경에 멀티 모듈 프로젝트를 배포해보진 않았지만, 기존에 프로젝트를 진행할 때는 한 모듈에 모든 코드가 다 존재하여 각각의 의존성에 대해 고려하지 않았지만 멀티 모듈 프로젝트를 진행하면서 이 코드가 가져올 사이드 이펙트나 의존성 문제에 대해 고민하면서 코드를 짜다보니 코드를 작성할 때의 시각이 좀더 넓어진 것 같다.
보통 스프링 프로젝트를 생성하게 된다면 다음과 같이 모놀리틱 프로젝트로 생성이 된다. 
멀티 모듈 아키텍처는 말 그대로 여러개의 아키텍처를 사용하는 것이기 때문에 이 프로젝트에 각각의 역할에 맞는 모듈을 생성해주면 된다. 나는 gradle을 사용했기 때문에 gradle 모듈을 추가해주었다.

API 모듈은 클라이언트의 요청을 받아들이고, 요청에 따른 처리 후 응답을 반환하는 역할을 한다. 대부분의 컨트롤러와 서비스 클래스들이 이 모듈에 위치한다. API 모듈은 대부분의 모듈에 의존하게 된다.
Domain 모듈은 애플리케이션의 핵심 부분을 맡는다. 엔티티와 레포지토리 인터페이스 등이 위친한다. 이 모듈은 변경에 굉장히 취약하기 때문에 최대한 의존성이 없어야 하는 모듈이다.
Common 모듈은 프로젝트 전반에서 공통으로 사용되는 코드를 포함한다. 유틸리티 클래스, 상수 클래스, 예외 처리 등의 공통으로 사용되는 코드들이 속한다. 이 모듈은 모든 모듈에서 의존성을 가질 가능성이 높다.
Infra 모듈은 말 그대로 인프라에 관련된 코드들이 위치한다. 외부 서비스, 파일 시스템 등의 연동을 위해 필요한 코드가 위치한다.
Batch 모듈은 주기적으로 실행되는 배치 작업을 처리한다. 주직적인 업데이트, 특정 시간에 실행되어야 하는 작업 등을 이 모듈에서 관리한다.
각각의 모듈이 완전하게 독립적이지는 않지만 각각 필요한 모듈에만 의존하고 있기 때문에 모놀리식 아키텍처 보다는 유지보수하기가 쉽고 관리하기가 쉽다.
찾아보니 모놀리틱 아키텍처가 MSA로 확장이 불가능한 것은 아니다. 그러나 모놀리틱 아키텍처는 코드의 복잡성이 높고 비대할 가능성이 높기 때문에 MSA 전환시 시간과 리소스가 멀티 모듈에 비해 많이 들것이다.
그렇다고 멀티 모듈 아키텍처라고 모놀리틱 아키텍처가 불가능한 것은 아니다. 멀티 모듈은 모놀리틱 아키텍처에서도 사용할 수 있고, MSA 아키텍처에서 사용될 수 있다.
모듈을 나눌 때의 기준을 도메인으로 할지 계층별로 할지 고민을 많이 했다. 그러면서 여러 글과 깃 레포를 참조해봤는데 많은 분들이 기능 + 공통 모듈로 모듈을 나눈것을 볼 수 있었다.
도메인 주도 개발(DDD)에 대해서는 자세히는 모르지만 DDD에서 사용하는 개념인 바운디드 컨텍스트(Bounded Context)를 기준으로 모듈을 분리하는 경우도 있고, 기능을 기준으로 예를 들어 상품 주문, 상품 거래, 상품 배송, 등 이렇게 분리할 수도 있을 것이다.
모듈을 분리하는 것은 개발자의 마음이지만, 내 생각에는 기능 별로 분리하는 것이 좋다고 생각한다. 왜냐하면 도메인 별로 모듈을 분리하게 된다면 여러 도메인을 사용할 경우에는 복잡성이 올라가서 의존성이 올라간다고 생각이 되었다. 각 환경과 리소스에 따라 다르겠지만 역시나 적절하게 판단하고 사용하면 될 것 같다.
참고: https://mangkyu.tistory.com/304, https://techblog.woowahan.com/2637/, https://hudi.blog/why-use-multi-module/