Page History
...
이벤트 소싱(Event Sourcing): 모든 상태 변화를 이벤트로 저장하여, 시스템의 상태를 이벤트의 집합으로 유지하는 방식입니다. 이를 통해 모든 변경 내역을 추적할 수 있으며, 과거 상태로의 복원이 용이합니다.
CQRS(Command Query Responsibility Segregation): 명령(Command)와 조회(Query)를 분리하여, 쓰기 모델과 읽기 모델을 독립적으로 최적화할 수 있도록 하는 아키텍처입니다. 이를 통해 복잡한 비즈니스 로직의 단순화와 확장성을 높일 수 있습니다.
액터 모델(Actor Model): 액터라는 독립적인 객체들이 메시지를 통해 상호작용하면서 상태를 관리하는 아키텍처입니다. 비동기적이며 높은 확장성과 내결함성을 제공하여 분산 시스템 구현에 적합합니다.
리액티브 시스템(Reactive Systems): 높은 응답성, 탄력성, 확장성을 갖춘 시스템을 의미하며, 비동기 메시지 전달을 통해 확장성과 유연성을 극대화합니다. 이벤트 소싱 및 CQRS와 조합하여 유용하게 사용됩니다.
마이크로서비스 아키텍처(Microservices Architecture): 도메인별로 독립된 서비스로 나누어 설계하는 방식으로, 각 서비스가 개별적으로 배포 및 확장될 수 있습니다. DDD와 결합하여 각 바운디드 컨텍스트를 별도의 마이크로서비스로 구현함으로써 시스템의 유지보수성과 확장성을 높입니다.
헥사고널 아키텍처(Hexagonal Architecture): 포트와 어댑터 아키텍처라고도 불리는 이 방식은 애플리케이션의 핵심 도메인 로직을 외부의 인프라스트럭처로부터 분리하여, 유연성과 테스트 용이성을 높입니다. 도메인 로직을 중심에 두고, 외부 의존성을 포트와 어댑터 형태로 연결함으로써 시스템이 변화에 덜 민감해지고 쉽게 확장할 수 있도록 합니다.
반버논의 "도메인 주도 설계(DDD)" 4장 아키텍처 편에서는 도메인 모델을 중심으로 한 소프트웨어 아키텍처 설계를 설명합니다. 주요 내용을 요약하면 다음과 같습니다:
계층화된 아키텍처:
- 시스템은 일반적으로 여러 계층으로 나뉘며, 도메인 로직과 비즈니스 규칙은 가장 중요한 계층입니다.
- 계층화된 아키텍처는 주로 사용자 인터페이스(UI), 애플리케이션, 도메인, 인프라스트럭처 계층으로 구성됩니다. 도메인 계층은 비즈니스 규칙을 캡슐화하고 애플리케이션 계층은 도메인 로직을 활용해 작업 흐름을 제어합니다.
도메인 계층의 중요성:
- 도메인 계층이 소프트웨어의 중심에 있어야 하며, 그 주위에 다른 기술 계층들이 도메인 논리를 지원하는 방식으로 구조화해야 합니다.
- 이렇게 하면 도메인 모델이 변화하거나 확장될 때 애플리케이션 계층이나 인프라 계층에 미치는 영향을 줄일 수 있습니다.
의존성 역전 원칙:
- 아키텍처의 핵심은 의존성 역전 원칙을 따르는 것입니다. 이는 인프라스트럭처 계층이 도메인 계층에 의존하도록 설계해, 도메인 모델을 독립적으로 유지할 수 있도록 합니다.
- 이를 통해 도메인 모델은 다른 기술적 세부 사항이나 프레임워크의 변화에 덜 영향을 받게 됩니다.
Bounded Context(경계 컨텍스트):
- 도메인 주도 설계에서는 전체 도메인을 여러 개의 작은 경계 컨텍스트로 나누어 관리합니다.
- 경계 컨텍스트는 도메인 모델을 한정된 범위 내에서 명확히 정의하고, 모델의 일관성을 유지하며, 각 컨텍스트 간 통합을 명확히 합니다.
애그리게이트와 리포지토리:
- 도메인 모델에서 중요한 요소는 **애그리게이트(Aggregate)**로, 도메인 객체 간의 일관성을 유지하는 단위입니다.
- 애그리게이트는 그 상태를 직접 관리하며, **리포지토리(Repository)**는 애그리게이트를 저장하고 검색하는 인터페이스 역할을 합니다.
서비스와 이벤트:
- 비즈니스 로직을 캡슐화하기 위해 서비스를 사용할 수 있으며, 도메인 모델과의 결합을 최소화하여 유연성을 확보합니다.
- 이벤트는 시스템 내에서 중요한 상태 변경을 나타내고, 다른 시스템이나 컴포넌트가 이를 감지하고 반응하도록 돕습니다.
이 장에서는 소프트웨어가 복잡한 도메인 요구사항을 충족시키면서도 유연성과 확장성을 갖추기 위해 도메인 모델을 중심으로 구조화해야 한다는 점을 강조합니다.
액터 모델(Actor Model)은 DDD(Domain-Driven Design)의 일부 요소를 구현하고 아키텍처적으로 보완하는 데 유용하게 활용될 수 있습니다. 특히 분산 시스템 및 병행성을 효과적으로 처리해야 하는 상황에서, 액터 모델과 DDD를 결합하는 방식은 유의미한 이점을 제공합니다. 아래는 DDD 요소 중에서 액터 모델을 활용할 수 있는 부분에 대한 설명입니다:
경계 컨텍스트(Bounded Context)와 액터:
- DDD의 경계 컨텍스트는 도메인의 특정 부분을 명확하게 정의하고 해당 범위 내에서 일관성을 유지하는 것이 핵심입니다. 각 경계 컨텍스트를 액터로 모델링할 수 있습니다.
- 각 액터는 독립적으로 상태와 비즈니스 로직을 갖고 있으며, 다른 액터와 메시지 기반으로 통신하기 때문에 경계 컨텍스트 간의 명확한 경계를 설정하고 이를 통해 상호작용할 수 있는 강력한 도구가 됩니다.
애그리게이트(Aggregate)와 액터:
- DDD에서 애그리게이트는 트랜잭션 경계를 나타내며, 상태의 일관성을 보장하는 단위입니다. 이러한 애그리게이트를 액터로 표현하면, 각 애그리게이트의 일관성을 유지하는 동시에 독립적으로 상태를 관리할 수 있습니다.
- 애그리게이트를 액터로 구현하면 동시성 문제를 자연스럽게 해결할 수 있으며, 애그리게이트 간의 변경사항도 메시지를 통해 비동기적으로 전달할 수 있습니다. 이로 인해 데이터 충돌을 줄이고 시스템의 확장성을 높일 수 있습니다.
도메인 이벤트(Domain Event)와 액터 간 메시징:
- DDD의 도메인 이벤트는 상태 변화나 중요한 비즈니스 이벤트를 시스템 내 다른 부분에 알리는 역할을 합니다. 액터 모델의 특성상 액터 간에는 메시지 기반 통신이 이루어지므로, 도메인 이벤트를 메시지로 사용해 액터들 간의 통신을 자연스럽게 연결할 수 있습니다.
- 도메인 이벤트를 비동기 메시지로 발행하고 구독하는 방식은 액터 모델에서 기본적인 통신 패턴으로, 이를 통해 시스템의 반응성을 높이고 이벤트 주도 아키텍처를 효과적으로 구현할 수 있습니다.
유비쿼터스 언어(Ubiquitous Language)와 액터의 역할:
- 유비쿼터스 언어를 유지하면서 비즈니스 개념을 명확하게 모델링하는 것은 DDD의 중요한 원칙입니다. 액터 모델에서는 비즈니스 개념을 액터로 표현하여 유비쿼터스 언어를 유지하면서도 도메인 모델을 직접 반영할 수 있습니다.
- 각 액터가 특정 비즈니스 개념이나 역할을 맡도록 설계함으로써 도메인 지식을 코드에 자연스럽게 반영할 수 있으며, 비즈니스 전문가와 개발자 간의 커뮤니케이션이 수월해집니다.
CQRS와 액터 모델의 결합:
- DDD에서 명령-질의 책임 분리(CQRS, Command Query Responsibility Segregation) 패턴을 사용할 때, 액터 모델을 활용하여 명령과 이벤트 처리를 각각 독립적으로 처리할 수 있습니다.
- 명령(Command)을 처리하는 액터와 이벤트(Event)를 다루는 액터를 분리함으로써 시스템을 더 효율적으로 확장 가능하게 설계할 수 있으며, 각 액터의 책임이 명확해집니다.
복잡한 비동기 워크플로우:
- DDD에서 비즈니스 로직이 복잡한 워크플로우를 포함할 때, 액터 모델은 이를 비동기로 처리하기에 적합합니다. 워크플로우의 각 단계를 액터로 나누고, 메시지를 통해 각 단계를 진행함으로써 복잡한 비동기 흐름을 단순화하고 관리 가능하게 만듭니다.
결론적으로, 액터 모델은 DDD의 경계 컨텍스트, 애그리게이트, 도메인 이벤트 및 CQRS 등의 요소를 강화하고 비동기적이고 병행적인 처리를 용이하게 하는 데 적합합니다. 액터 모델의 비동기 메시지 기반 특성은 DDD의 복잡한 도메인 로직을 분산 시스템에서 안정적으로 운영할 수 있게 해주는 훌륭한 도구가 될 수 있습니다.
Akka 프레임워크는 액터 모델 외에도 분산 시스템, 비동기 메시징, 이벤트 기반 아키텍처를 쉽게 구현할 수 있는 여러 툴과 라이브러리를 제공합니다. 이들 중 DDD(Domain-Driven Design)와 연관하여 유용하게 사용할 수 있는 도구들을 아래에 소개합니다:
1. Akka Persistence
- 상태 저장 및 복구: Akka Persistence는 액터의 상태를 영속화하고 복구할 수 있게 하여, 시스템이 중단되거나 장애가 발생한 이후에도 애그리게이트의 상태를 유지할 수 있습니다. 이는 DDD에서 애그리게이트를 영속적으로 관리하는 데 유용합니다.
- Event Sourcing: Akka Persistence는 이벤트 소싱(Event Sourcing) 패턴을 지원합니다. 애그리게이트의 상태 변화를 이벤트로 저장함으로써, 도메인의 모든 상태 변화를 추적하고 복원할 수 있습니다. DDD와 연계하면 도메인 이벤트를 영속적으로 관리하고, 데이터 일관성을 보장할 수 있는 강력한 메커니즘이 됩니다.
2. Akka Cluster
- 분산 시스템 구성: Akka Cluster는 여러 노드를 하나의 시스템처럼 사용할 수 있게 하여 분산 시스템을 쉽게 구성할 수 있는 기능을 제공합니다. 이는 DDD에서 여러 경계 컨텍스트(Bounded Context) 간에 분산 환경에서 협업하거나 데이터를 공유할 때 유용합니다.
- 고가용성: Akka Cluster는 각 노드 간 상태 정보를 공유하고, 장애 발생 시 다른 노드가 자동으로 작업을 대체하여 시스템의 고가용성을 유지합니다. 분산된 애그리게이트를 관리하고 경계 컨텍스트 간의 데이터를 안전하게 유지하기 위한 아키텍처적 기반을 제공합니다.
3. Akka Sharding
- 애그리게이트 분산 관리: Akka Sharding은 시스템에서 수많은 액터를 논리적으로 그룹화하여 다양한 노드에 분산시킬 수 있는 기능을 제공합니다. DDD에서 애그리게이트의 수가 매우 많거나 경계 컨텍스트가 크다면, 각 애그리게이트를 여러 노드에 분산시켜 부하를 균등하게 나누고, 병목 현상을 줄일 수 있습니다.
- 수평적 확장성: 애그리게이트 액터를 샤딩하여 각 액터를 클러스터 내 다양한 노드에 분산시킬 수 있기 때문에, 대규모 시스템에서도 일관성과 확장성을 유지하면서 효율적으로 운영할 수 있습니다.
4. Akka Streams
- 데이터 스트림 처리: Akka Streams는 대용량 데이터 스트림을 비동기로 처리할 수 있는 도구를 제공합니다. 이를 통해 DDD에서 도메인 이벤트나 애플리케이션 간 데이터 흐름을 관리할 수 있습니다.
- Reactive Streams: Akka Streams는 리액티브 스트림(Reactive Streams) 표준을 준수하므로, 경계 컨텍스트 간 비동기 데이터 흐름을 설계할 때 반응형 패러다임을 따르며 시스템의 반응성을 유지할 수 있습니다. 이로써 이벤트 기반 아키텍처에서 발생하는 데이터의 흐름을 손쉽게 처리할 수 있습니다.
5. Akka HTTP
- 경계 컨텍스트 간 통신: DDD에서 각 경계 컨텍스트는 독립적으로 운영되며, 서로 필요한 데이터를 교환하기 위해서는 안정적인 API 통신이 필요합니다. Akka HTTP는 HTTP 기반의 비동기 RESTful API를 쉽게 구성할 수 있는 도구를 제공합니다.
- 비동기 API 호출: 액터 기반 아키텍처에서 경계 컨텍스트 간 통신을 비동기적으로 처리하여 시스템의 성능과 반응성을 높일 수 있습니다. 이를 통해 도메인 서비스들이 독립성을 유지하면서도 상호작용할 수 있게 됩니다.
6. Akka Typed (Typed Actors)
- 타입 안전성: Akka Typed는 액터의 메시지 유형을 명시적으로 정의함으로써 타입 안전성을 높이는 방식으로, DDD에서 각 액터(애그리게이트나 도메인 객체)가 정확한 도메인 의미를 가진 메시지를 주고받도록 보장할 수 있습니다.
- 명확한 도메인 모델링: DDD의 유비쿼터스 언어를 유지하면서 각 액터의 역할과 메시지 타입을 명확히 정의하여 도메인 로직의 오류를 줄일 수 있습니다.
7. Akka Projections
- CQRS 구현: Akka Projections는 CQRS (Command Query Responsibility Segregation) 패턴을 쉽게 구현할 수 있는 기능을 제공합니다. 이벤트 소싱을 통해 생성된 이벤트 스트림을 읽고, 이를 별도의 읽기 모델로 변환하는 기능을 제공합니다.
- 도메인 이벤트와 조회 모델 관리: 이벤트 소싱을 통해 생성된 도메인 이벤트를 기반으로 읽기 모델을 구축하고 업데이트함으로써 조회 성능을 높이고 데이터 일관성을 보장할 수 있습니다. 이는 도메인 이벤트와 쿼리 모델을 분리하고 비동기적으로 관리할 수 있는 강력한 도구입니다.
Akka의 DDD와의 연계 활용 요약
- Akka Persistence와 Akka Projections를 통해 애그리게이트와 이벤트 소싱을 쉽게 구현하고 관리할 수 있습니다.
- Akka Cluster와 Akka Sharding을 이용해 경계 컨텍스트 및 애그리게이트의 확장성과 고가용성을 보장할 수 있습니다.
- Akka Streams와 Akka HTTP를 사용해 비동기 데이터 흐름과 경계 컨텍스트 간 통신을 효율적으로 관리할 수 있습니다.
- Akka Typed는 도메인 로직의 타입 안전성을 보장하고, DDD의 유비쿼터스 언어와 도메인 개념을 명확하게 반영하는 데 도움을 줍니다.
이러한 Akka의 기능들은 DDD의 도메인 모델을 중심으로 하는 복잡한 분산 시스템을 더 효율적이고 확장 가능하게 설계하고 운영하는 데 매우 유용합니다.