본문으로 건너뛰기

전자상거래 DDD 레이어드 아키텍처

전자상거래 도메인: 5개 Aggregate (Customer, Product, Order, Inventory, Tag) + Domain Service + Application Layer CQRS.

public class Order
{
public string CustomerId { get; set; }
public string Status { get; set; }
public decimal TotalAmount { get; set; }
public List<OrderLineDto> Lines { get; set; }
}
public class OrderLineDto
{
public string ProductId { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
}

이 구현은 컴파일되고 실행됩니다. 하지만 다음과 같은 잘못된 상태를 허용합니다:

  • 아무 문자열이나 Status에 대입 — 유효하지 않은 주문 상태가 가능합니다
  • 음수 금액, 0 이하 수량 — 값 범위 검증이 없습니다
  • 빈 주문 라인 — 주문 항목 없는 주문이 생성됩니다
  • 수동 합계 계산 — TotalAmount와 라인 합계가 불일치할 수 있습니다
  • 신용 한도 미검증 — 고객 신용을 초과하는 주문이 확정됩니다

4가지 보장:

  1. 타입 안전성 — 값 객체가 생성 시점에 검증 완료
  2. 불변식 보장 — 상태 머신, 구조적 제약이 잘못된 상태를 원천 차단
  3. CQRS 분리 — Command/Query 독립 최적화
  4. 파이프라인 자동화 — Apply 패턴 + FinT 모나드로 검증/에러 처리 자동화

DDD 전술적 패턴이 규칙 경계를 정의하고, Functorium의 함수형 타입이 이를 컴파일러 수준에서 강제합니다.

이 예제는 Domain 레이어와 Application 레이어를 두 트랙으로 나누어, naive한 코드에서 완성된 DDD 모델까지 각 4단계를 거칩니다.

단계Domain 레이어Application 레이어
0. 요구사항도메인 비즈니스 요구사항애플리케이션 비즈니스 요구사항
1. 설계도메인 타입 설계 의사결정애플리케이션 타입 설계 의사결정
2. 코드도메인 코드 설계애플리케이션 코드 설계
3. 결과도메인 구현 결과애플리케이션 구현 결과
DDD 개념Functorium 타입적용
Value ObjectSimpleValueObject<T>, ComparableSimpleValueObject<T>CustomerName, Email, Money, Quantity, ProductName 등
Smart EnumSimpleValueObject<string> + HashMapOrderStatus (5 states, transition rules)
EntityEntity<TId>OrderLine (child entity)
Aggregate RootAggregateRoot<TId>Customer, Product, Order, Inventory, Tag
Domain EventDomainEvent19종 (Created, Updated, Confirmed 등)
Domain ErrorDomainErrorType.CustomEmptyOrderLines, InvalidOrderStatusTransition 등
SpecificationExpressionSpecification<T>ProductNameSpec, CustomerEmailSpec 등 6종
Domain ServiceIDomainServiceOrderCreditCheckService
RepositoryIRepository<T, TId>5개 Repository 인터페이스
패턴구현적용
CQRSICommandUsecase / IQueryUsecase10 Commands, 9 Queries
Apply Patterntuple.Apply()VO 병렬 검증 합성
FinT LINQfrom...in 체이닝비동기 에러 전파
Port/AdapterIQueryPort, IRepository읽기/쓰기 분리
FluentValidationMustSatisfyValidation구문 + 의미 이중 검증
Nested ClassRequest, Response, Validator, UsecaseUse Case 캡슐화
samples/ecommerce-ddd/
├── Directory.Build.props
├── Directory.Build.targets
├── ecommerce-ddd.slnx
├── domain/ # 도메인 레이어 문서
│ ├── 00-business-requirements.md
│ ├── 01-type-design-decisions.md
│ ├── 02-code-design.md
│ └── 03-implementation-results.md
├── application/ # 애플리케이션 레이어 문서
│ ├── 00-business-requirements.md
│ ├── 01-type-design-decisions.md
│ ├── 02-code-design.md
│ └── 03-implementation-results.md
├── Src/
│ ├── ECommerce.Domain/
│ │ ├── SharedModels/
│ │ │ ├── ValueObjects/ (Money, Quantity)
│ │ │ └── Services/ (OrderCreditCheckService)
│ │ └── AggregateRoots/
│ │ ├── Customers/ (Customer, VOs, Specs)
│ │ ├── Products/ (Product, VOs, Specs)
│ │ ├── Orders/ (Order, OrderLine, VOs)
│ │ ├── Inventories/ (Inventory, Specs)
│ │ └── Tags/ (Tag, VOs)
│ └── ECommerce.Application/
│ ├── Ports/ (IExternalPricingService)
│ └── Usecases/
│ ├── Products/ (Commands, Queries, Ports)
│ ├── Customers/ (Commands, Queries, Ports)
│ ├── Orders/ (Commands, Queries, Ports)
│ └── Inventories/ (Queries, Ports)
└── Tests/
└── ECommerce.Tests.Unit/ (301개 테스트)
├── Architecture/ # 아키텍처 규칙 검증 (26개 테스트)
├── Domain/
└── Application/
Terminal window
# 빌드
dotnet build Docs.Site/src/content/docs/samples/ecommerce-ddd/ecommerce-ddd.slnx
# 테스트
dotnet test --solution Docs.Site/src/content/docs/samples/ecommerce-ddd/ecommerce-ddd.slnx