architecture-dddlisted
Install: claude install-skill changja88/dddjango
# 도메인 주도 설계 (DDD)
## 언제 쓰나
<!-- graph-owned: 이 절의 정본은 ontology 그래프다 — 수정은 rules 정본에서, 이 본문 직접 수정 금지 -->
도메인 언어(유비쿼터스 언어), 비즈니스 정책·상태 전이, 애그리거트 경계, 바운디드 컨텍스트 경계, 도메인 이벤트 채택 여부가 불명확할 때 로드한다. 경계:
- Django ORM·서비스 레이어·outbox 구현 → `implementation-django`
- outbox 전달 보장·트랜잭션 격리·Risky Write 설계 → `architecture-db`
- REST API 계약·엔드포인트 설계 → `architecture-api`
## 핵심 운영 원칙
<!-- graph-owned: 이 절의 정본은 ontology 그래프다 — 수정은 rules 정본에서, 이 본문 직접 수정 금지 -->
- 전략 설계가 전술 패턴보다 먼저다: 핵심 도메인 식별 → 바운디드 컨텍스트 설계 → 컨텍스트 맵 → 전술 패턴 적용. 전략 없이 전술 패턴만 적용하면 "잘못된 경계에서 좋은 코드를 작성하는 결과"가 된다 (§1.2, §2)
- 유비쿼터스 언어는 바운디드 컨텍스트 내에서만 유효하다 — 동일 개념도 컨텍스트가 다르면 다른 언어를 쓴다 (§2.3)
- 애그리거트는 Vernon의 4가지 규칙을 따른다: 진짜 불변식만 경계 안에서 보호, 최소 크기 설계, 타 애그리거트는 ID로만 참조(영속성/ORM 포함 — BC 경계 ORM FK 금지, 같은 BC 내 FK는 허용), 경계 밖 일관성은 결과적 일관성으로 달성 (§3.3)
- 엔티티는 애그리거트의 일부로만 사용하고, 독립적으로 생성·접근하지 않는다 (§3.2, §8)
- 도메인 서비스는 여러 애그리거트에 걸친 무상태 도메인 로직에 사용하고, 애그리거트는 도메인 서비스를 직접 알지 않는다 (§3.5)
- 응용 서비스는 흐름 제어와 트랜잭션 관리만 담당하고, 비즈니스 로직을 두지 않는다 (§3.6)
- 도메인 이벤트는 애그리거트가 수집하고, UoW 커밋 직전(동일 트랜잭션 내 부수 효과) 또는 직후(외부 통합)에 디스패치 타이밍을 명시한다. 타이밍이 불명확하면 이벤트 유실이나 트랜잭션 불일치가 발생한다 (§3.7)
- 발행 이벤트 봉투의 discriminator(`event_type` 류)는 1종째부터 domain_layer `StrEnum`으로 선언하고(birth-enum) append-only로 유지한다 — 버전 태그(`payload_schema_version`)는 리터럴 동결, 소비 BC는 발행 enum을 import하지 않는다 (§3.7)
- 아키텍처는 4계층+DIP를 기본으로 한다: 도메인이 인프라를 직접 알지 않도록 도메인 영역에 인터페이스를 두고 인프라에서 구현한다 (§5.1, §5.2)
- 구현 패턴(Data Mapper, Repository+UoW, Event Sourcing, Saga, CQRS)은 명확한 필요가 확인된 시점에 선택하고, 패턴 선택 절차를 통해 Risky Write 라우팅을 포함해