개요
소프트웨어 개발에서 가장 중요한 것은 유지보수성과 확장성이 중요합니다. 잘못된 설계는 시간이 지날수록 코드의 복잡도를 증가시키고, 개발 속도를 저하 시킵니다. 이를 해결하기 위해 등장한 설계 패턴이 클린 아키텍처 (Clean Architecture) 와 헥사곤 아키텍처(Hexagonal Architecture)입니다.
또한, 도메인 주도 설계(Domain Driven Design)도 비즈니스 로직을 보호하는 핵심적인 접근 방식입니다. 이번 포스팅에서는 클린 아키텍처와 헥사곤 아키텍처의 개념을 살펴보고 이것이 어떻게 DDD에 연결되는지 자세히 분석해 보겠습니다.
클린 아키텍처란?
클린 아키텍처는 로버트 C.마틴 (Uncle Bob) 이 제안한 소프트웨어 설계 개념입니다. 이 아키텍처는 유지보수성과 확장성을 높이기 위해 여러 계층으로 나누고, 비즈니스 로직을 보호하는 방식을 취합니다. 이 개념은 애플리케이션이 시간이 지나도 쉽게 변경 가능하도록 설계하는 것을 목표로 하는 아키텍처입니다. 클린 아키텍처의 핵심은 의존성 방향입니다. 의존성은 안쪽(도메인)에서 바깥쪽(프레임워크)로만 향하도록 설계 해야 합니다. 데이터베이스, UI, 프레임워크 등은 도메인 내부에 직접적인 영향을 미쳐서는 안된다는 의미입니다.
클린 아키텍처의 핵심구조
- Entities(엔터티) -> 가장 핵심인 비즈니스 규칙
- Use Cases (유스케이스) -> 도메인 규칙을 활용하여 실제 동작을 수행
- Interface Adapters(인터페이스 어뎁터) -> UI, DB, API 등과 연결)
- Frameworks & Drivers(프레임워크와 드라이버) -> 가장 바깥쪽, 기술적 세부사항이 위치
여기서 핵심개념은 도메인 계층이 외부 요소에 의존하지 않아야한다.
의존성은 안쪽(도메인)에서 바깥쪽(프레임워크)으로만 향한다.
UI, DB, API와 같은 기술적인 부분은 쉽게 교체할 수 있도록 설계한다.
즉, 비즈니스 로직을 가장 중요한 핵심으로 유지하고 나머지는 플러그인처럼 교체 가능 하게 만드는 것입니다.
헥사곤 아키텍처란?
헥사곤 아키텍처는 Port & Adapters 패턴을 사용합니다. 헥사곤 아키텍처도 같은 비즈니스 로직 보호 철학을 따르지만 구조가 다르게 표현됩니다.
헥사곤 아키텍처의 핵심구조
- Business Logic 비즈니스 로직 -> 핵심적인 도메인 코드
- Input Port 입력포트 -> 애플리케이션에 들어오는 요청을 처리하는 인터페이스
- Output Port 출력포트 -> 데이터베이스, 메시지큐 같은 외부 시스템을 연결하는 인터페이스
- Driving Adapter 주요 어댑터 -> API, UI., 콘솔, 테스트 스크립트 같은 사용자 입력
- Driven Adapter 보조 어댑터 -> DB, 메시지큐, HTTP 등 외부 시스템과의 연결
여기서 핵심 개념은 비즈니스 로직은 포트(Port)를 통해 외부와 통신합니다. 어댑터를 사용하여 입력(Driving Adapter)과 출력을(Driven Adapter) 분리합니다. 이렇게 설계함으로써 외부 시스템이 변경되어도 비즈니스 로직에는 영향을 미치지 않습니다.
헥사곤 아키텍처는 클린 아키텍처처럼 '비즈니스 로직'을 보호하는 목표는 같지만, 이를 '포트와 어댑터'라는 개념을 사용해서 목표를 달성하는 점에서 다릅니다. 쉽게 말하면
- 클린 아키텍처는 "비즈니스 로직을 보호하는 아키텍처 철학"
- 헥사곤 아키텍처는 "비즈니스 로직을 보호하는 구체적인 패턴"
이라고 설명할 수 있습니다.
클린 아키텍처와 헥사곤 아키텍처의 장단점
클린 아키텍처와 헥사곤 아키텍처의 개념을 들어보면 좋은 점만 있을 것 같지만 항상 소프트웨어 개발 방법론에는 단점이 있습니다. 가장 큰 단점 중 하나가 모든 레이어가 독립적이어야 하므로 코드 작성량이 많아지고 복잡도가 증가합니다.
단점
코드량 증가
각 계층이 독립적이므로 인터페이스, 어뎁터, DTO 등 추가적인 코드가 많아집니다. 예를들어서 단순히 데이터베이스에서 데이터를 가져와 UI에 그려주기만 하면 되는데 여러 계층을 거쳐야 하니까 CRUD 코드도 복잡해질 수 있습니다.
초반 설계와 학습 비용이 큼
이 아키텍처는 왜 이렇게 써야할까? 라는 의문을 가질 수 있습니다. 의존성 역전의 법칙 Solid 원칙 등 개념적으로 난이도가 높아서 개발자들이 익숙해지는데 시간이 걸립니다.
작은 프로젝트에서는 과도한 설계
스타트업이 MVP 모델을 만든다고 했을 때 이러한 복잡한 구조가 불필요할 수 있습니다. 단순 CRUD 서비스라면 이렇게까지 레이어를 나눌 필요가 없습니다.
이 단점들을 상쇄하는 장점
도메인 로직 보호 로 장기적인 유지보수 비용 절감
비즈니스 로직이 외부 요소에 의존하지 않기 때문에 UI,DB 프레임워크 변경이 있어도 비즈니스 로직은 그대로 유지할 수 있습니다. 예를들어 MySQL을 사용하다가 MongoDB로 변경할 때 일반적인 아키텍처라면 비즈니스 로직도 수정해야 하지만, 클린 아키텍처에서는 DB 어뎁터만 바꾸면 됩니다. 또는 UI프레임워크(React -> Vue)로 바꾼다거나 API형태(GraphQL <-> Rest API) 변경 시에도 인터페이스 어댑터만 수정하면 됩니다.
결과적으로 유지보수와 확정성이 좋습니다.
테스트 용이성
비즈니스 로직이 완전히 독립적이므로 데이터베이스나 API 없이도 테스트가 가능합니다.
예를들어서 단순한 CRUD 서비스라면 보통 DB가 필요하지만, 클린 아키텍처에서는 Mock(가짜 객체), In-Memory DB를 활용하여 독립적인 테스트가 가능합니다. 입력포트와 출력포트가 분리되어 있어 각 레이어별로 단위 테스트하기가 쉽습니다.
기술스택 교체가 쉬움
도메인 로직이 외부기술(DB, UI, API)에 의존하지 않으므로 특정 기술 스택이 변경되더라도 비즈니스 로직은 그대로 유지할 수 있습니다. 음.. 예를 들어서 AWS RDS(MySQL)에서 Firebase Firestore로 DB를 변경한다고 할 때 비즈니스 로직은 그대로 유지할 수 있고 어댑터만 수정하면 됩니다.
팀 협업 효율 증가
MSA 서비스에 적합한 아키텍처라서 각각의 서비스를 분리된 형태로 개발한다면 서비스별로 프론트앤드 개발자는 UI 어댑터에 집중하고, , 백엔드 개발자는 Use Case에 집중하고, DBA는 스키마 설계와 레포지토리 어댑터를 담당하여 병렬적으로 개발해 개발속도를 빠르게 만들고 유지보수를 용이하게 만들 수 있습니다.
신규 기능 추가 용이
새로운 기능을 추가할 때 기존 코드에 영향을 주지 않고 확장이 가능합니다. 예를들어서 기존 REST API를 사용하다가 GraphQL을 추가하고 싶다면 기존 Use Case와 Entity는 그대로 두고 새로운 GraphQL 어댑터만 만들면 됩니다. 이메일로 알람을 보내다가 슬랙으로 변경하고 싶으면 비즈니스 로직을 건들이지 않고 새로운 "알림 어댑터"만 만들면 됩니다.
DDD와 클린 아키텍처는 같은 철학을 공유한다.
클린 아키텍처와 DDD는 공통된 철학이 있습니다.
- 비즈니스 로직(도메인 로직)이 가장 중요하다.
- 비즈니스 로직을 보호하기 위해 외부요소(DB, UI, 프레임워크)와 분리해야 한다.
- 의존성은 바깥(외부 시스템)에서 안쪽(도메인)으로만 향해야 한다.
- 비즈니스 로직은 UI, DB, API 같은 기술적인 요소에 의존하면 안된다.
공통점은 UI, DB가 바뀌어도 핵심 비즈니스 로직은 변하면 안된다는 것입니다.
클린 아키텍처와 DDD의 차이
클린 아키텍처에서의 비즈니스 로직
- Entities (엔터티) → 시스템의 가장 핵심적인 "비즈니스 규칙" 이 위치
- Use Cases(유스케이스) -> "엔터티를 활용하여 특정 도메인 동작을 수행"
- 외부요소(DB, UI, API)는 Interface Adapters, Frameworks & Drivers 계층에 위치 -> 비즈니스 로직을 "독립적"으로 유지할 수 있도록 분리함.
DDD(Domain-Driven Dessign)에서 비즈니스 로직
- 도메인 모델 -> 핵심적인 비즈니스 규칙이 구현됨.
- 도메인 서비스 -> 여러 엔티티를 조합하여 특정 비즈니스 로직 수행
- 애플리케이션 서비스 -> 유스케이스를 담당
- 어그리게이트 루트(Aggregate Root) -> 여러 개의 도메인 객체를 하나의 단위로 묶어서 관리하는 것
결론은 Clean Architecture의 "Entities"와 DDD의 "Domain Model"은 같은 개념 둘 다 핵심적인 비즈니스 로직을 담당하고, 외부 기술(UI, DB, API)에 의존하지 않다는 공통적인 철학을 갖습니다.
결론
클린 아키텍처와 헥사곤 아키텍처는 단기적으로 불편하지만, 장기적으로는 유지보수 비용을 절감할 수 있는 대규모 엔터프라이즈급 애플리케이션에 적합한 아키텍처 구조입니다. 특히 MSA 아키텍처와 궁합이 잘 맞아서 공부해두면 유용합니다. 더불어 DDD 설계 개념도 클린 아키텍처의 철학과 겹치는 부분이 많아서 MSA를 공부한다면 해당 아키텍처는 꼭 알아두시는 것을 추천합니다.