
클린 아키텍처
- 헥사고날 아키텍처와 마찬가지로 핵심은
비즈니스 로직(도메인 모델)을 인프라(외부 세계)에서 분리한다 는 것이다.
- 도메인 모델은 가장 중심에 있고, 도메인에 접근하기 위해서는 밖의 레이어들을 거쳐 들어올 수 밖에 없다.
의존성은 반드시 밖에서 안으로만 존재하며, 안쪽에 있는 레이어는 밖의 레이어에 대해 알면 안된다. (=참조하면, =의존하면 안된다)
분리한다 의 의미는 안쪽 레이어가 바깥쪽 레이어를 모르게 한다 는 뜻!
- 클린 아키텍처와 헥사고날 아키텍처는 분리하는 방식이 다를 뿐, 동작하는 코드는 비슷한 형태로 흐른다.
- 개인적으로 클린 아키텍처보단 헥사고날 아키텍처가 더 좋은 것 같다. 포트와 어댑터라는 이름과 동작이 더 직관적이고 단순한 형태여서?
클린 아키텍처와 헥사고날 아키텍처의 차이점은?
1. 구조적 차이
헥사고날 아키텍처
- 헥사고날 아키텍처는 외부와의 상호작용을
포트와 어댑터로 구분한다.
- 포트는 인터페이스로 핵심 비즈니스 로직과 외부 시스템을 분리하는 역할을 하며,
어댑터는 구현체로 외부 시스템과 통신한다.
클린 아키텍처
- 헥사고날 아키텍처보다는 계층적 구조이다.
- 핵심 비즈니스 로직(Use Case, Entities)를 중심으로, 바깥 계층이 안쪽 계층에 의존하도록 설계된다.
- 외부 의존성 (DB, 프레임워크)은 가장 바깥쪽에 위치하며, 내부로는 영향을 미치지 않는다.
2. 의존성의 방향
헥사고날 아키텍처
- 포트와 어댑터를 통한 명확한 의존성 역전
- 핵심 로직은 포트 인터페이스에만 의존하고, 어댑터가 구체적인 외부 구현을 처리한다.
클린 아키텍처
- 의존성 규칙을 따르며, 의존성은 항상 바깥쪽에서 안쪽으로만 흐르게 설계된다.
- 비즈니스 로직은 외부 시스템에 의존하지 않고, 외부 시스템이 내부 유스케이스와 엔티티에 의존하는 구조다.
3. 추상화의 구체성
헥사고날 아키텍처
- 입력/출력 포트와 같은 추상화 인터페이스를 명확히 정의한다.
- 포트를 통해 모든 외부와의 상호작용을 처리한다.
- MSA와 잘 어울리며, 다양한 외부 시스템과의 통합에 강하다.
클린 아키텍처
- 계층적인 구분에 조금 더 초점을 맞춘다.
- 계층간 의존성을 줄이는 데 중점을 둔다.
- 유스케이스 중심의 설계에 더 중점을 둔다. (헥사고날 아키텍처 보다는)
예시
헥사고날 아키텍처에서의 상품 주문 처리
com.example.order
│
├── domain
│ ├── Order.java
│ ├── OrderItem.java
│ └── OrderService.java
│
├── ports
│ ├── input
│ │ └── CreateOrderPort.java
│ ├── output
│ │ └── OrderRepositoryPort.java
│
├── adapters
│ ├── web
│ │ └── OrderController.java
│ ├── persistence
│ │ └── JpaOrderRepository.java
│ └── external
│ └── ExternalPaymentAdapter.java
클린 아키텍처에서의 상품 주문 처리
com.example.order
│
├── domain
│ ├── Order.java
│ ├── OrderItem.java
│ └── Product.java
│
├── application
│ └── service
│ ├── CreateOrderUseCase.java
│ └── GetOrderDetailsUseCase.java
│
├── adapters
│ ├── controllers
│ │ └── OrderController.java
│ ├── persistence
│ │ └── JpaOrderRepository.java
│ └── dto
│ └── OrderRequest.java
│
└── infrastructure
└── config
└── WebConfig.java
결론
- 헥사고날 아키텍처는 포트와 어댑터를 명확히 분리하고, 비즈니스 로직과 외부 시스템 간의 상호작용을 철저히 분리한다. 외부 시스템의 변경이 잦고 다양한 통신이 필요한 경우에 적합하다.
- 클린 아키텍처는 계층 간 의존성을 내부로만 흐르게 설계하여, 각 계층이 독립적으로 동작할 수 있게 하는 데 중점을 둔다. 유스케이스 중심으로 시스템을 구조화하며, 유지보수성과 확장성이 뛰어난 설계를 목표로 한다.