서비스를 개발하다 보면 DDD, 클린 아키텍처, 헥사고날 아키텍처 같은 아키텍처 패턴을 학습하고 적용하려고 시도하게 됩니다.
저도 마찬가지로 처음에는 DDD + Bounded Context + Service Layer 구조를 중심으로 구조를 나누고 역할을 구분하려고 했습니다.
그런데 시간이 지나고, 복잡도가 조금씩 늘어나면서 다음과 같은 고민들이 생겼습니다.
1. DDD + 헥사고날 + 클린 아키텍처 적용의 현실적인 비용
이론적으로는 Domain, Application, Infra 계층을 명확히 나누고, Port & Adapter 패턴을 통해 완전한 계층 분리를 한다면 이상적으로 유연하고 확장성이 높은 구조가 만들어질 것입니다.
하지만 대규모 서비스가 아닌 경우, 이런 구조적 분리는 오히려 코드량이 증가하고, 생산성이 떨어지는 상황을 경험했습니다.
- 과도한 계층 분리로 불필요한 코드와 클래스가 증가
- 개발자가 코드를 따라가는데 오히려 시간이 소요
- 실질적인 비즈니스 가치에 비해 오버 엔지니어링된 느낌
결국 아키텍처도 비용-효과 관점에서 적절한 Trade-Off가 필요하다는 것을 직접 느꼈습니다.
2. DDD + 클린 아키텍처에서의 실질적인 타협
그래서 저는 기존의 DDD + 클린 아키텍처를 실제 프로젝트 상황에 맞게 '타협'하여 적용해보기로 했습니다.
특히 기존에 Bounded Context 안의 Service Layer에서 다른 도메인의 Repository나 Service를 직접 참조하는 것이 자연스럽지 않다는 점이 가장 크게 다가왔습니다.
이는 서비스들이 서로 암묵적으로 엮이면서 의존성이 복잡해지고, 도메인 경계가 흐려지는 문제를 야기했기 때문입니다.
그래서 저는 다음과 같은 방식으로 구조를 리팩토링하고 있습니다:
- Application Layer를 명확히 둔다.
- Application Service가 여러 Domain Service, Repository, Client를 orchestration (조합)
- Domain Service는 오직 비즈니스 로직만 담당 (Repository나 Client 호출 금지)
- Infra나 Client는 Application Layer를 통해 호출
- Domain Layer는 최대한 깨끗하게 유지하고, Application Layer에서 외부와의 연결, 흐름을 담당하게 구성
이렇게 하면 기존의 바운디드 컨텍스트 구조보다 Application Layer에서 도메인 로직이 더 명확하게 표현되고, 가독성도 개선되는 효과를 느끼고 있습니다.
동시에 필요 이상으로 계층을 쪼개지 않고, 현실적인 타협선에서 관리 가능한 구조를 지향하고 있습니다.
정리
- 아키텍처는 정답이 아니라 Trade-Off
- 비즈니스 가치, 팀 역량, 서비스 규모에 맞는 현실적인 Best-Practice를 찾는 과정이 중요
- DDD + 클린 아키텍처를 정석적으로 '완벽히' 도입하려 하기보다,
프로젝트 상황에 맞게 적당히 타협하고 실질적인 가독성과 관리 효율성을 높이는 방향으로 접근하는 것이 더 가치 있음