모듈, 레이어, 아키텍처는 서로 다른 결정이다
모듈 경계와 코드 레벨의 레이어, 아키텍처를 구분하고 구현에 더 강한 제약이 필요할 때만 모듈을 추출하는 기준을 다룬다.
출처 및 AI 안내: 이 글은 제미니의 개발실무 유튜브를 기반으로 작성되었습니다.
gpt-5.6-sol모델을 사용해 생성·편집했습니다.
도메인 코드를 별도 모듈로 분리해도 레이어드 아키텍처를 쓸 수 있다. 모든 코드를 싱글 모듈에 두고 레이어드나 헥사고날 아키텍처를 구현할 수도 있다. DB 모듈을 나누더라도 코드 안의 책임을 레이어로 구분하는 방식은 그대로 유지할 수 있다.
이 구조들은 서로 연관 지을 수 있지만 같은 결정은 아니다. 하나로 묶어 생각하면 특정 아키텍처에 어떤 모듈 구조가 필요하냐는 잘못된 질문으로 이어진다. 먼저 물어야 할 것은 코드에 어떤 역할이 필요하고, 어느 의존성을 허용하며, 그 규칙을 강제하기 위해 이제 모듈 경계까지 필요한가이다.
코드 레이어가 곧 아키텍처 레이어는 아니다
구현을 설명하며 말하는 레이어는 이름 붙은 레이어드 아키텍처보다 코드 레벨의 역할을 뜻할 때가 많다. 헥사고날 아키텍처를 선택해도 프레젠테이션, 비즈니스 행위, 구현 세부사항에는 이해할 수 있는 자리가 필요하다. 포트와 어댑터가 생긴다고 코드 내부의 구분이 사라지는 것은 아니다.
이 차이는 중요하다. ‘레이어’라는 한 단어 때문에 별개의 논의가 같아 보일 수 있기 때문이다. 하나는 아키텍처 전체의 흐름에 관한 논의다. 다른 하나는 개발자가 변경할 위치를 찾을 수 있도록 구현 안의 책임을 배치하는 문제다. 싱글 모듈에서도 둘을 모두 표현할 수 있다. 반대로 멀티 모듈이라고 둘 중 어느 하나가 저절로 보장되지는 않는다.
따라서 먼저 코드 레벨 구분의 품질을 살펴야 한다. 구현의 책임이 불분명한 상태에서 그 이름을 그대로 모듈 경계로 옮기면 불확실한 구조를 바꾸기만 더 어려워진다.
아키텍처가 모듈 배치를 정해 주지는 않는다
레이어드 구조와 헥사고날 구조는 모두 싱글 모듈 안에 둘 수 있다. 헥사고날이라면 그 안에서 포트와 어댑터를 구성하면 된다. 반대로 멀티 모듈 프로젝트도 일반적인 레이어드 흐름을 따를 수 있다. 도메인이나 DB 모듈을 추출했다는 것은 의존성 경계에 관한 선택이지, 그 자체로 아키텍처 스타일을 결정했다는 뜻은 아니다.
모듈 구조로 아키텍처를 뒷받침할 수는 있다. 별도 모듈을 이용해 원하지 않는 의존성을 막고 선택한 경계를 더 엄격하게 관리하는 방식이다. 이는 충분히 타당하지만 판단의 순서가 중요하다. 먼저 지켜야 할 경계를 정하고, 더 강한 제약이 유용할 때 모듈을 사용한다. 어떤 아키텍처를 택했다고 해서 미리 정해진 하나의 모듈 트리가 자동으로 따라오지는 않는다.
그래서 여러 배치가 모두 가능하다. 도메인을 좁은 의존성과 함께 격리할 수 있다. 더 빠른 작업을 위해 일부 의존성을 허용하고 프레젠테이션, 비즈니스, 구현 역할을 한데 모을 수도 있다. 비즈니스와 구현 역할을 한 번 더 엄격하게 분리하는 구조도 가능하다. 이 배치들에서도 같은 아키텍처 아이디어를 유지할 수 있다. 차이는 아키텍처의 유무보다 제약의 강도와 작업 방식에서 생긴다.
필요가 보인 뒤 모듈을 추출한다
구현이 진화해 응집과 경계가 드러날 때까지는 패키지만으로도 충분할 수 있다. 패키지 구조가 중요한 규칙을 더 이상 충분히 표현하거나 보호하지 못할 때 모듈이 쓸모를 갖는다.
그 필요는 구체적인 문제로 나타난다.
- 새로 합류한 사람이 코드를 잘못된 위치에 두기 쉽다.
- 팀이 허용하는 의존 방향을 명확하게 표현하고 싶다.
- 경계를 더 분명히 하면 올바른 작업 위치를 찾기 쉬워진다.
- 도메인이나 비즈니스 코드를 주변 구현 세부사항에서 더 강하게 보호해야 한다.
- 외부로 향하는 프레젠테이션 코드를 핵심과 섞이지 않게 분명히 격리하고 싶다.
이런 조건은 경계가 해결할 문제를 설명하므로 모듈을 도입할 이유가 된다. 프로젝트에 여러 모듈을 사용한다고 말할 수 있다는 사실 자체는 이유가 아니다. 모듈을 하나 더 만드는 일은 기법이지 구현이 잘 설계됐다는 증거가 아니다.
작업에 맞는 제약을 선택한다
나도 속도가 중요할 때는 이미 익숙한 구현 방식에 맞춘 간결한 멀티 모듈 패턴을 쓰기도 한다. 이것은 나에게 효율적인 기본값이지 모든 프로젝트가 지켜야 할 최소선이 아니다. 싱글 모듈을 자주 선택하지는 않지만, 사용한다고 해서 문제가 된다고 생각하지도 않는다. 멀티 모듈이 아니라는 이유만으로 프로젝트에 결함이 있다고 보는 것 역시 이상하다.
구현에서 시작하자. 책임과 코드 레벨의 레이어를 응집력 있게 만든 뒤, 패키지만으로 그 결정을 충분히 전달할 수 있는지 묻는다. 실수, 의존성의 이탈, 뒤섞인 책임 때문에 더 강한 격리가 정말 필요해졌다면 이미 설명할 수 있는 경계를 따라 모듈을 추출하면 된다.
모듈, 레이어, 아키텍처는 서로를 강화할 수 있다. 그래도 각각은 별도의 조절 장치다. 이 차이를 분명히 해야 각 장치가 자신에게 맞는 문제를 풀 수 있다.