ddd-workshop/skills/aggregate-designer/SKILL.md
ddd-workshop 파이프라인의 5단계 (최종 산출물, 전술적 설계). 한 BC 내부의 Aggregate를 1개씩 설계한다. Design-Level Event Storming(이벤트·커맨드· 액터·정책·핫스팟)을 내부 도입부에서 상세화하고, 그 흐름을 근거로 Aggregate 구조(Root/Entity/VO), 불변식(Invariant), 정책(Policy 위치), 그리고 **Exposed Queries(읽기 경로)** 를 결정한다. UL은 BC Canvas의 per-BC UL을 이어받아 "용어 | Code Identifier | 의미" 이중 표기로 참조·확장. Exposed Queries는 screen-inventory의 Query 이름과 크로스체크. 산출물은 docs/shared/contexts/<bc>/<aggregate>.md 1개. BC 내 여러 Aggregate는 여러 번 호출. "aggregate 설계", "애그리거트", "invariant", "불변식", "domain policy", "event storming 상세", "exposed queries", "read path", "aggregate designer", "ddd-workshop 5단계" 같은 요청에 트리거한다.
npx skillsauth add dev-goraebap/skills aggregate-designerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
ddd-workshop 파이프라인의 최종 산출물. 한 BC에서 Aggregate 1개를 완성된 .md 파일로 설계한다.
이 스킬은 Design-Level Event Storming (상세한 이벤트·커맨드·정책·핫스팟)을 내부 단계로 수행한 뒤, 그 흐름에서 Aggregate 경계·불변식·정책·조회 경로를 끌어낸다.
v0.3 주요 변경:
docs/domains/... → docs/shared/contexts/<bc>/<aggregate>.md> **Status**: draft 만 사용)| 파일 | 용도 |
|---|---|
| references/template.md | Aggregate 문서 템플릿 (v0.3 형식) |
| references/example-order.md | 주문 Aggregate (B2C) |
| references/example-organization.md | 조직 Aggregate (사내) |
[Q 3/15 · 근거: ...]⚠️ 미정으로 산출물에 기록./ddd-workshop:aggregate-designercontext-designer 출력 직후 (또는 screen-inventory 직후).md 업데이트 → --update호출 단위: 한 세션에서 여러 Aggregate를 연속 진행한다. Step 10의 "다음 행동 메뉴"로 같은 세션에서 이어가기. 매번 재호출 강요 금지.
Bulk draft 모드 (옵션): Supporting/Generic BC에 한해, 사용자가 명시 요청하면 여러 Aggregate를 짧은 초안으로 연이어 생성. Core BC 금지. §10 참조.
docs/shared/context-map.md — 대상 BC 정보 + BC 간 관계docs/shared/contexts/<bc>/_canvas.md — 주 입력
docs/shared/contexts/<bc>/_screens.md — (있으면) Query 이름 매칭 대상docs/shared/requirements.md — 엣지 케이스·제약docs/shared/subdomain-map.md — Core/Supporting/Generic (상세도 결정)docs/shared/published-language.md — (있으면) cross-BC 공용 용어자동 점검:
_canvas.md 존재 확인. 없으면 "먼저 context-designer로 Canvas 생성" 안내._screens.md 있으면 Query 목록 보관 → Step 9 Exposed Queries와 대조.📋 Upstream 스캔
- 대상 BC: Leave Balance (Core)
- Canvas UL 로드: 10개 용어 (연차, 원장, 부여, 사용, ...)
- _screens.md 없음 — Exposed Queries는 Canvas의 Inbound Queries에서 시드
- Canvas Business Decisions 5개 → 불변식 후보 시드
- BC 내 예상 Aggregate 후보: AnnualLeaveBalance, LeaveLedgerEntry
- ⚠️ 퇴사 시 처리 방식 미정 (Canvas Open Questions)
| 구분 | 불변식 (Invariant) | 정책 (Policy) | |---|---|---| | 성격 | 항상 참 | 상황·시점에 따라 가변 | | 위치 | Aggregate 내부 | 외부 분리, 교체 가능 | | 변경 주기 | 도메인 본질 바뀔 때만 | 마케팅·운영이 자주 바꿈 | | 예시 | "잔액 ≥ 0", "주문 최소 1개 항목" | "VIP 10% 할인", "배송비 계산" |
판정 질문:
애매하면 Policy로 (올리기 쉽고 내리기 어렵다).
| 위치 | 언제 | |---|---| | Specification | 조건 판별 재사용·조합·부정 | | Strategy (Policy 객체) | 교체 가능한 의사결정 규칙 | | Domain Service | 여러 엔티티 얽혀 단일 Aggregate에 애매 | | Event Handler | 이벤트에 반응하는 비동기 정책 |
Repository.findX().toDTO() 로 Aggregate를 재조립해 조회용으로 쓰기. → Aggregate가 비대해지고 트랜잭션 경계 혼란.[Q 1/15]
이번 회차에 설계할 Aggregate를 정합니다.
BC `Leave Balance`의 Aggregate 후보 (Canvas UL 기반):
1) AnnualLeaveBalance (잔고 권위, Root) — 권장
2) LeaveLedgerEntry (원장 엔트리, append-only)
3) 기타 (자유 입력)
4) 모름
DDD 권장: Core Aggregate Root부터 (권장: 1)
대상 Aggregate와 관련된 이벤트를 과거형 시간 순 나열.
[시스템] →(자동 부여)→ [연차_적립됨]
[결재자] →(승인)→ (Leave Request)→ [연차_차감요청됨]→ [연차_차감됨]
[관리자] →(조정)→ [연차_조정됨]
[연차_차감됨] ─정책: 만료 경계 체크─→ (만료예정분_소멸시키기)
[사원_퇴사됨] ─정책: 진행 중 정산─→ (미사용분_정산하기)
(consume) → [차감됨] or [잔고부족으로_거부됨]
⚠️ 만료 경계에서 취소된 신청의 복원 처리
[Flow: 연차 생애]
...
1) 그대로 OK
2) 누락 이벤트 추가
3) 잘못 그려진 부분 수정
4) 핫스팟 해소부터 (권장 — 불변식/정책 판정에 영향)
책임지는 것 + 책임지지 않는 것 둘 다.
각 규칙을 판정 질문으로 검증:
[Q · 규칙: "잔고 = 원장 누적 합계"]
판정 질문:
- 이 규칙이 바뀌면 도메인 정의가 바뀌는가? ✅
- 마케팅·운영이 바꿀 수 있는가? ❌
- 테스트에서 가짜 대체 원하는가? ❌
→ Invariant. 동의? (1) 동의 2) 실은 Policy 3) 모름
[Q · AccrualPolicy]
제안 위치: Strategy (근기법 공식 구현체 + 사내특례 구현체 교체 가능)
이유: 법 개정 시 구현체 교체로 대응
교체 시나리오: 2026년 근기법 개정 발효 시
동의? (1) 동의 (2) Specification (3) Domain Service (4) Event Handler (5) 불변식
다른 Aggregate·BC·외부 시스템 참조 방식 명시. context-map과 일치 검증.
발행 이벤트 + 구독 이벤트.
이 Aggregate가 외부에 제공하는 읽기 계약 나열.
[Q · Exposed Queries]
Canvas의 Inbound Queries + screen-inventory 매칭:
| Query | 반환 | 원천 | 주의 |
|---|---|---|---|
| getBalance(employeeId) | {remaining, expiring} | Query Service | Aggregate 재조립 금지 |
| getLedger(employeeId, range) | LedgerEntry[] | 원장 테이블 직독 | append-only 보장 |
screen-inventory (_screens.md) 매칭 결과:
✅ listMyLeaveHistory — 없음 (이 BC에선 getLedger로 커버)
⚠️ getBalanceForecast — Canvas에 없음, 추가할지?
1) 이대로 OK
2) Query 추가
3) Query 매개변수 조정
4) screen-inventory 업데이트 필요 (별도 `screen-inventory` 재호출)
원천(Source) 옵션:
미확정 설계 이슈. 비어 있으면 "없음".
파일 저장 후 숫자 메뉴로 묻는다. 재호출 강요 금지.
✅ AnnualLeaveBalance Aggregate 설계 완료
docs/shared/contexts/leave-balance/annual-leave-balance.md
다음으로 무엇을 하시겠어요?
1) 같은 BC(Leave Balance)의 다른 Aggregate 연속 진행 (LeaveLedgerEntry)
2) 다른 BC로 이동 (context-map 기준으로 제안)
3) 여기서 종료
4) 방금 만든 문서 수정·보강 (--update)
5) Bulk draft 모드 (Supporting/Generic 한정)
기본 경로: docs/shared/contexts/<bc-slug>/<aggregate-slug>.md
YAML frontmatter 없음. 필요한 경우 본문 최상단에 뱃지 1줄:
> **Status**: draft | active | deprecated
본문 구조는 references/template.md 를 참조. 주요 섹션:
# <RootName> + > **Status**: active 뱃지## Role — 책임지는 것 / 책임지지 않는 것## Ubiquitous Language (이 Aggregate 범위) — 이중 표기 테이블## Event Storming (Design-Level) — 플로우 + 해소/미해소 핫스팟## Structure — Root / Entity / VO / 외부 참조## Invariants — 항상 참인 규칙만## Policies — 위치 + 이유 + 교체 시나리오## External Dependencies — 관계 + 참조 방식## Domain Events (발행) / (구독)## Exposed Queries — 읽기 계약 + Read-side 규약 + screen-inventory 매칭## Open Questions채워진 예시: references/example-order.md, references/example-organization.md.
--update)_canvas.md 변경 시 경계 영향 큼.1) 새 Invariant 추가
2) Policy 추가·위치 변경
3) 이벤트 스토밍 갱신
4) Exposed Queries 수정 (screen-inventory 동기화)
5) Open Questions 해소
6) 외부 의존 변경
□ Step 0 upstream 스캔 완료
□ Canvas 존재 확인됨 (없으면 context-designer 먼저)
□ Generic BC면 실행 만류 확인함
□ 이벤트 스토밍에 비정상 경로(실패/취소/타임아웃) 포함
□ 핫스팟 최소 1개 기록 (없으면 "없음" 명시)
□ Role에 "책임 + 책임 아님" 둘 다 서술
□ Root 1개 확정
□ 외부 참조가 ID만 (context-map과 일치)
□ Invariant 최소 2개 + 각각 판정 질문 통과
□ Policy 최소 1개 + 위치 제안 + 교체 시나리오
□ Domain Events 발행·구독 둘 다 나열
□ Exposed Queries 섹션 존재 (없으면 "없음" 명시)
□ Exposed Queries에 "Aggregate 재조립 금지" 규약 언급
□ screen-inventory 있으면 Query 이름 매칭 기록
□ UL 이중 표기 (용어 / Code / 의미)
□ 산출물 경로: docs/shared/contexts/<bc>/<aggregate>.md
□ YAML frontmatter 없음 (status 뱃지만 허용)
□ Open Questions 섹션 존재
| BC 분류 | 상세도 | |---|---| | Core | 최대 — Invariant/Policy 엄격 분리, 이벤트 스토밍 철저, Exposed Queries 명시. Bulk draft 금지. | | Supporting | 표준 — CRUD 중심, Policy 분리 최소화. Bulk draft 허용. | | Generic | 실행 만류 — 외부 솔루션 인터페이스만 정의 권장. |
사용자가 명시 요청했을 때만. Core BC 금지.
⚠️ Bulk draft 모드입니다.
- Invariant vs Policy 구분 정확도 낮음
- Exposed Queries는 screen-inventory 없이 Canvas만 참조
- 생성 문서는 모두 `Status: draft`
- Core BC 사용 불가
대상 BC: Organization (Supporting)
후보 Aggregate: Employee, Department, Position, Title
진행? (1) 진행 (2) 순차 모드로
⚠️ 사용자 확정 필요⚠️ 검토 필요> **Status**: draft 뱃지.Status: active로 저장 (반드시 draft).docs/domains/ 에 저장 (반드시 docs/shared/contexts/).testing
도메인 일반 패턴을 강의 모드로 가르치는 인지과학 기반 학습 스킬. AI가 가상 도메인 전문가(선생님) 역할을 하고 사용자가 학생으로 낯선 도메인을 차근차근 배운다. 메뉴로 시작해서 페이즈를 골라 잠수 → 능동 회상 Q&A → 자기 설명(Feynman) 순서로 진행. Dunlosky 메타분석 기반 인지과학 8원칙(Cognitive Load, Practice Testing, 정교화 질문, Self-Explanation, Schema 연결, Dual Coding, Desirable Difficulty, 분산 학습)을 본문에 명시 적용. 도메인의 법령·산업 표준·인증을 학습 본문에 정식 통합 (출처 인용이 아니라 학습 대상). AI가 판단해 보편적이고 자료 풍부한 도메인은 자료 요청 없이 진행, 좁고 깊은 도메인일 때만 사용자에게 자료 있는지 묻기. 산출물은 학습 노트 스타일 (진도 체크박스 + 페이즈별 일관 구조 + 출처 링크). 페르소나 강요 없이 보편 액터 표현("사원 A", "관리자 A"). bigpicture의 이전 단계로 작동하거나 단독 사용 가능. Triggers — "도메인 학습", "낯선 도메인 가르쳐줘", "이 산업 어떻게 굴러가요", "선생님 모드", "1:1 강의", "도메인 입문", "도메인 일반 패턴", "HR 플랫폼이 뭔지", "이커머스 흐름", "domain classroom", "/domain-classroom".
development
빅픽처 이벤트스토밍의 1:1 분석 도구. 학습 단계(domain-classroom)에서 머리에 박힌 도메인 일반 패턴을 클라이언트 시스템에 매핑해 빅픽처 산출물(시간순 도메인 이벤트·페이즈·액터·외부시스템·핫스팟·피벗)을 누적한다. domain-classroom의 학습 노트(docs/learning-notes/{도메인}- classroom.md)와 클라이언트 자료(RFP·요구사항정의서·기존 시스템 스키마)를 입력으로 받아 페이즈 단위로 진행. 페르소나·서사 없는 분석 톤. 도메인 이벤트 판별 4기준(도메인 전문가 관심·비즈니스 상태 변화·법적 의미·다른 흐름 트리거)을 명시 적용해 UI/Telemetry 이벤트 혼입 방지. 이벤트는 한국어 자연어 + Code Identifier 이중 표기. 핫스팟에 ID·답할 위치·확신도 태그 부여. 산출물은 docs/eventstorming.md 단일 파일로 시작, 후속 단계 스킬(process-modeling·software-design)이 추가될 때 폴더로 자연 분기. Initial/Update/Cycle 모드 지원 — 코드 작성 후에도 다시 사이클 가능. Triggers — "빅픽처", "빅픽처 만들어줘", "이벤트스토밍", "도메인 이벤트 정리", "Big Picture EventStorming", "페이즈 매핑", "도메인 산출물 정리", "/bigpicture".
data-ai
빅픽처 이벤트스토밍의 1:1 학습 친화 변형. 그룹 워크샵에서 도메인 전문가가 던지는 이벤트를 받아 적는 대신, AI가 가상 도메인 전문가 역할을 하고 사용자가 학습자로 1:1 인터뷰하며 빅픽처를 누적한다. 산출물(시간순 도메인 이벤트·액터· 외부시스템·핫스팟·피벗)은 빅픽처 이벤트스토밍과 거의 동일하지만, 한 보드에 한 번에 펼치는 방식이 아니라 **한 액터·한 챕터씩 시간순 서사로 누적**한다. 각 장면마다 "왜 이게 필요한가?" 설명을 곁들여 학습자가 따라올 수 있게 한다. RFP·요구사항정의서·기존 도메인 자료를 입력으로 받거나, 자료가 없으면 AI 사전 리서치(보편 사례·법령·산업 표준)로 보충해 진행. 페르소나 시점의 챕터 단위 (5~7개 장면) + 확신도 태그 [확실/일반론/추측]로 검증 지점 명시 + 사용자 인터랙션 + 액터 전환으로 빅픽처를 점진적으로 채운다. 산출물 저장은 옵셔널 — 이해 자체가 목적이다. Triggers — "낯선 도메인 이해", "도메인 차근차근 알려줘", "1:1 빅픽처", "솔로 이벤트스토밍", "RFP 분석", "비즈니스 흐름 이해", "액터 시나리오", "신규 프로젝트 도메인 파악", "빅픽처 스토리타임", "bigpicture storytime", "/bigpicture-storytime".
databases
PostgreSQL DB에 직접 접근하는 스킬. DB 조회, 테이블 구조 확인, 데이터 검증이 필요할 때 사용한다. Node.js 스크립트로 직접 연결하며 접속 정보는 환경변수 또는 credentials 파일에서 읽는다. "postgres 조회", "DB 확인", "테이블 구조", "pg-query", "쿼리 실행", "데이터 검증", "PostgreSQL 접속" 같은 요청에 트리거한다.