Skill: Model Domain
목적
도메인의 유비쿼터스 언어를 정의하고 서술형 명세로 작성
철학: "ERD 그리기 말고, 말로 설명하기"
입력
- 도메인 이름 (예: "users")
- Phase 2 결과 (SESSION.md의 완전한 도메인 정의)
출력
ai-context/domain-books/{domain}/domain-model.md- 용어 정의 + 관계 규칙 + 제약 조건 + 생명주기
유비쿼터스 언어란?
해당 도메인 전용이면서 개발자가 쉽게 이해할 수 있는 전용 언어
❌ 잘못된 접근 (ERD)
┌─────────┐ ┌──────────────┐
│ User │───1:N──│ Translation │
└─────────┘ └──────────────┘
✅ 올바른 접근 (유비쿼터스 언어)
"사용자는 여러 개의 번역 기록을 가질 수 있다."
"번역 기록은 반드시 한 명의 사용자에게 속한다."
작동 방식
1. 용어 추출
SESSION.md에서 해당 도메인의 엔티티와 속성을 읽고, 각 개념을 한글 용어로 정의한다:
SESSION.md → users 도메인:
속성: ID, Email, DisplayName, ProfileImage, PreferredLanguage, CreatedAt
용어 정의:
사용자 (User) — 앱을 사용하는 개인
식별자 (ID) — 사용자를 고유하게 구분하는 값
이메일 (Email) — 로그인 및 연락용 이메일 주소
표시 이름 (DisplayName) — 다른 사용자에게 보이는 이름
프로필 사진 (ProfileImage) — 사용자의 프로필 이미지 경로
선호 언어 (PreferredLanguage) — 사용자가 선호하는 언어 설정
가입 시각 (CreatedAt) — 사용자가 가입한 날짜와 시간
2. 관계 규칙 생성
SESSION.md의 관계 정의를 서술형 문장으로 변환한다:
1:N 관계 (User → Translation):
"사용자는 여러 개의 번역 기록을 가질 수 있다."
"번역 기록은 반드시 한 명의 사용자에게 속한다."
"사용자가 삭제되면 모든 번역 기록도 함께 삭제된다."
3. 제약 조건 추출
SESSION.md의 제약 정의를 자연어로 변환한다:
Email Unique → "이메일 (Email)은 중복될 수 없다."
ID 자동생성 → "식별자 (ID)는 시스템이 자동으로 생성한다."
4. 생명주기 정의
생성·수정·삭제 각 단계를 단계별 흐름도로 작성한다.
domain-model.md 구조
# {domain} 도메인 모델
> 생성일: {오늘 날짜}
> Phase: 3 (Domain Modeler)
> 상태: ✅ 완료
---
## 📖 유비쿼터스 언어 (용어 정의)
> 이 도메인에서 사용하는 전용 용어들
### 핵심 용어
| 용어 | 정의 | 예시 |
|------|------|------|
| 사용자 (User) | 앱을 사용하는 개인 | "홍길동", "john@example.com" |
| 식별자 (ID) | 사용자를 고유하게 구분하는 값 | "u_123abc" |
| ... | ... | ... |
---
## 📐 관계 규칙
> 이 도메인의 엔티티들이 어떻게 연결되는지 서술형으로 정의
### 사용자와 번역 기록
**규칙 1**: 사용자는 여러 개의 번역 기록을 가질 수 있다.
- 한 사용자가 0개 이상의 번역을 요청할 수 있음
- 예: "홍길동 사용자는 10개의 번역 기록을 가지고 있다"
**규칙 2**: 번역 기록은 반드시 한 명의 사용자에게 속한다.
- 모든 번역은 누가 요청했는지 기록됨
- 예: "이 번역 기록은 john@example.com 사용자의 것이다"
---
## ✅ 제약 조건
> 엔티티가 지켜야 하는 규칙
### 필수 규칙
1. **식별자 (ID)**는 시스템이 자동으로 생성한다.
- 사용자가 직접 설정할 수 없음
2. **이메일 (Email)**은 중복될 수 없다.
- 이미 존재하는 이메일로는 가입 불가
- 예: "user@example.com"으로 이미 가입되어 있으면 다시 가입 불가
---
## 🔄 생명주기
> 엔티티가 어떻게 생성, 수정, 삭제되는지
### 생성 (가입)
\`\`\`
사용자가 가입을 요청한다
↓
이메일이 중복되지 않는지 확인한다
↓
모든 필수 정보가 제공되었는지 확인한다
↓
사용자 엔티티를 생성한다
↓
식별자(ID)와 가입 시각(CreatedAt)을 자동으로 설정한다
\`\`\`
**규칙**: 가입 시 선호 언어가 제공되지 않으면 기본값은 '영어'로 설정된다.
### 수정 (프로필 편집)
...
### 삭제 (탈퇴)
...
작성 원칙
✅ 좋은 명세 (서술형)
- "사용자는 여러 개의 번역 기록을 가질 수 있다."
- "번역 기록은 반드시 한 명의 사용자에게 속한다."
- "이메일은 중복될 수 없다."
❌ 나쁜 명세 (기술적)
- "User 테이블의 id 컬럼은 UUID 타입"
- "Translation.user_id는 User.id를 참조하는 Foreign Key"
- "email 컬럼에 UNIQUE 제약"
→ 말로 설명하기! 테이블/컬럼 언급 금지.
관계 표현 패턴
1:N 관계
"A는 여러 개의 B를 가질 수 있다."
"B는 반드시 하나의 A에 속한다."
예시:
- "사용자는 여러 개의 번역 기록을 가질 수 있다."
- "번역 기록은 반드시 한 명의 사용자에게 속한다."
1:1 관계
"A는 하나의 B를 가진다."
"B는 반드시 하나의 A에 속한다."
예시:
- "사용자는 하나의 프로필을 가진다."
- "프로필은 반드시 한 명의 사용자에게 속한다."
N:M 관계
"A는 여러 개의 B와 연결될 수 있다."
"B는 여러 개의 A와 연결될 수 있다."
예시:
- "사용자는 여러 개의 관심 태그를 가질 수 있다."
- "태그는 여러 명의 사용자와 연결될 수 있다."
Cascade 관계
"A가 삭제되면 모든 B도 함께 삭제된다."
예시:
- "사용자가 삭제되면 모든 번역 기록도 함께 삭제된다."
제약 조건 패턴
필수/선택
"X는 반드시 제공되어야 한다."
"Y는 선택 사항이다."
유일성
"X는 중복될 수 없다."
형식 검증
"X는 반드시 Y 형식이어야 한다."
예시:
- "이메일은 반드시 유효한 형식이어야 한다. (@ 기호 포함)"
값 범위
"X는 A, B, C 중 하나여야 한다."
"Y는 최소 N 이상이어야 한다."
예시:
- "선호 언어는 '한국어' 또는 '영어'만 가능하다."
- "표시 이름은 최소 1자 이상이어야 한다."
자동 생성
"X는 시스템이 자동으로 생성한다."
생명주기 작성 가이드
생성 (Create)
요청자가 생성을 요청한다
↓
[검증 단계 1]
↓
[검증 단계 2]
↓
엔티티를 생성한다
↓
[자동 설정 단계]
수정 (Update)
요청자가 수정을 요청한다
↓
권한을 확인한다
↓
[검증 단계]
↓
변경 가능한 필드만 수정한다
수정 가능/불가능 필드 명시 필수
삭제 (Delete)
요청자가 삭제를 요청한다
↓
권한을 확인한다
↓
연결된 데이터를 확인한다
↓
[Cascade 처리]
↓
엔티티를 삭제한다
기술 용어 금지 목록
작성 후 아래 키워드가 없는지 확인한다:
| 금지 영역 | 키워드 |
|---|---|
| 데이터베이스 | 테이블, 컬럼, Foreign Key, Primary Key, Index, UUID, VARCHAR, INT, TIMESTAMP |
| 프레임워크 | FastAPI, SQLAlchemy, Alembic, Pydantic |
| 프로토콜 | HTTP, REST, GraphQL, WebSocket |
| 클라우드 | PostgreSQL, MySQL, Redis, S3 |
검증 체크리스트
domain-model.md 작성 완료 후:
- 용어 테이블에 모든 핵심 용어 포함
- 각 용어에 정의와 예시 있음
- 관계 규칙이 서술형으로 작성됨
- 모든 관계에 예시 포함
- 제약 조건에 이유 설명
- 생명주기 3단계 (생성/수정/삭제) 모두 포함
- 기술 용어 (테이블, 컬럼, FK, UUID 등) 0개
- 한글 용어 사용 (영어 병기는 괄호 안에)