영상요약및 번역본

🎭 배우들이 DDD 세계를 지배할 수 있습니다

Hannes Lowette – NDC Porto 2022 발표 요약

1. 발표 개요 및 문제 정의

  • 발표자는 벨기에 출신의 Hannes로, DDD(Domain-Driven Design)와 CQRS(Command Query Responsibility Segregation) 기반 시스템을 Akka.NET으로 구현하는 방법을 소개함.

  • BeerSender.NET이라는 맥주 배송 및 추적 시스템을 예시로 사용함.

    • 벨기에의 다양한 맥주를 친구들에게 보내려다, 국제 배송 및 통관 문제로 여러 번 반송, 추가 비용, 복잡한 추적 과정을 겪음.

    • 이 경험을 바탕으로 "맥주 추적 시스템"의 필요성을 느끼고, 이를 .NET 프레임워크로 개발하기로 함.

2. DDD와 CQRS, Event Sourcing 개념 정리

  • DDD

    • 비즈니스와 개발팀이 **동일한 언어(유비쿼터스 언어)**를 사용하여 소프트웨어를 설계함.

    • 시스템 내에서 의미가 달라지는 **경계(바운디드 컨텍스트)**를 구분하여, 각 컨텍스트마다 명확한 책임과 언어를 정의함.

    • **Aggregate(집합체)**는 비즈니스 로직의 단위이자 이벤트가 발생하는 중심.

  • CQRS

    • **명령(Command)**과 **조회(Query)**를 분리하여 각각 독립적으로 확장 및 최적화할 수 있게 함.

    • 명령은 시스템의 상태를 변경하고, 조회는 상태를 읽기만 함.

    • 이벤트는 명령 실행 후 발생하며, 읽기 저장소를 최신 상태로 유지하는 데 사용됨.

  • Event Sourcing

    • 상태 변화의 모든 이벤트를 저장하고, 이를 재생하여 현재 상태를 복원함.

    • 예: 쇼핑카트에서 상품을 추가/삭제한 모든 과정을 이벤트로 저장하여, 추천 엔진 등에서 활용 가능함.

3. Akka.NET과 Actor 모델의 특징

  • Akka.NET은 Scala 기반 Akka의 .NET 포트로, 메시지 기반의 Actor 모델을 구현함.

  • 소프트웨어를 현실 세계처럼 객체(Actor) 간 메시지 교환으로 모델링함.

  • 특징:

    • 비동기 메시지 기반

    • 멀티코어 및 클러스터 활용 가능

    • 높은 확장성과 복원력

  • Actor는 자신의 상태와 행동을 가지며, 오직 메시지로만 상호작용함.

  • 메시지는 순차적으로 처리되어, 동시성 문제를 피할 수 있음.

4. Actor 시스템 구조 및 메시지 처리

  • Actor는 특정 클래스를 상속받아 구현함.

  • 메시지는 POCO(Plain Old CLR Object)로 자유롭게 정의 가능.

  • 메시지를 처리하면서 메시지 객체를 변경해서는 안 됨.

  • 클러스터 환경에서는 메시지가 직렬화/역직렬화됨.

  • 성능: 단일 서버에서 초당 수백만~수천만 메시지 처리 가능.

  • Actor System은 Actor 생성/관리/메시지 분배/이벤트 버스 관리 등을 담당함.

  • Actor는 트리 구조로 구성되며, 부모-자식 관계가 중요함.

5. Actor의 감독 전략 (Supervision)

  • ReceiveActor: 타입별 메시지 핸들러 등록 가능

  • 자식 Actor는 context.actorOf로 생성하며, 이름은 고유해야 함.

  • 감독 전략:

    • 부모 Actor는 자식 Actor의 예외 상황을 처리함

    • Resume(계속), Stop(중지), Restart(재시작), Escalate(상위로 전달)

  • 예: 자식 Actor 중 하나라도 실패하면 전체 작업을 중단하는 전략 등 적용 가능.

  • Erlang 사례: 2백만 라인의 텔레콤 시스템에서 연간 31ms 다운타임 기록

6. Akka Persistence와 Event Sourcing

  • Akka Persistence는 Actor의 상태를 이벤트 소싱 방식으로 영속화할 수 있는 라이브러리.

  • Actor 재생성 시, 스냅샷과 이벤트를 순서대로 재생하여 상태 복원.

  • 모든 Actor에 적용하면 성능 저하 우려 → 필요한 경우에만 사용 권장

  • 상태는 별도의 State 객체로 관리

  • 메시지 처리 방식:

    • Command: 명령 처리 시 persist 호출

    • Recover: 복구 시 apply만 수행

  • 스냅샷 저장은 비동기로 처리되며, SnapshotOffer 메시지로 상태 객체 복원 가능

7. Akka.NET과 DDD의 궁합

  • DDD의 현실 세계 모델링과 Actor의 메시지 기반 모델이 자연스럽게 어울림

  • Akka.NET은 메시지 기반 처리, 이벤트 소싱, 이벤트 버스 등 CQRS 시스템 구축에 적합

  • 클러스터링을 통해 선형 확장 가능

8. Aggregate 구현 및 테스트 전략

  • Aggregate는 외부 의존성 없이 구현, 저장소 정보도 모름

  • 명령을 전달하면 이벤트 목록을 반환함 (상태를 직접 변경하지 않음)

  • apply를 통해 상태를 변경

  • 테스트:

    • Given (이전 이벤트)

    • When (명령)

    • Then (예상 이벤트)

    • C#의 record 타입을 활용한 깊은 비교 및 가독성 확보

    • 제품 담당자도 이해할 수 있는 테스트 시나리오 작성

9. CQRS 아키텍처 내 Aggregate Actor

  • Aggregate를 Actor로 감싸서 명령을 처리하고 이벤트를 저장/적용함

  • Persistence ID는 Aggregate 타입 + ID 조합으로 생성

  • 이벤트 발생 시 내부 이벤트 스트림에도 publish하여 읽기 모델에 반영

  • Actor 계층:

    • Aggregate Manager → Aggregate Actor 생성 및 참조 관리

    • Command Router → 명령을 Aggregate Manager로 전달

    • Projector → 이벤트를 읽기 저장소(DB 등)에 반영

  • 확장 전략:

    • 라우팅: 라운드로빈, 최소 인박스, Consistent Hashing

    • 클러스터 환경에서는 샤딩(Sharding) 사용 가능

10. 실전 운영 팁

  • UI와 이벤트 스트림을 연동 → 실시간 UI 구현 가능

  • HOCON 설정 → 설정 정보를 외부 파일로 관리

  • 클러스터링 학습 필요

  • 로깅 시스템과 연동 가능

  • 모니터링:

    • Petabridge Phobos (유료)

    • OpenTelemetry 연동

11. 학습 자료 및 결론

  • Petabridge 부트캠프 (무료)

  • Petabridge 블로그 (심층 설명)

  • 유료 강의 (원격, 클러스터링, 디자인 패턴 등)

🔑 결론

DDD와 Actor 모델은 매우 잘 어울린다.
비즈니스와 개발 모두가 이해 가능한 표현력 높은 시스템을 만들 수 있다.


링크 : https://lilys.ai/digest/4965701/4291743?s=1&noteVersionId=569965





  • No labels