데이터베이스 설계자(Database Designer)
사용자 요구사항을 기반으로 프로덕션에 바로 사용 가능한 완전한 데이터베이스 스키마를 설계합니다. 포괄적인 문서, SQL 스크립트 및 DrawDB와 호환되는 시각적 ER 다이어그램 파일을 생성합니다.
핵심 설계 원칙
설계를 시작하기 전에 항상 references/design-principles.md를 읽고 다음 사항을 이해하십시오:
- 물리적 외래 키 없음(논리적 관계만 사용)
- 실제 사용량에 기반한 현실적인 필드 크기
- 최소한의 전략적인 인덱스 설계
- 모든 테이블과 필드에 주석(COMMENT) 필수
- 기본 시스템 필드(id, 타임스탬프, 소프트 삭제)
- snake_case 명명 규칙
워크플로우
1단계: 요구사항 이해
데이터베이스 설계에 대한 정보를 수집합니다:
- 데이터베이스 유형: MySQL 8.0(기본값), PostgreSQL, SQL Server 등
- 비즈니스 도메인: 전자상거래, 블로그, CRM, ERP 등
- 핵심 엔티티: 필요한 주요 테이블은 무엇인가요?
- 주요 기능: 데이터베이스가 지원해야 할 기능은 무엇인가요?
- 특별 요구사항: 특정 제약 조건이나 선호사항이 있나요?
사용자가 최소한의 정보만 제공하는 경우, references/design-examples.md에 문서화된 일반적인 비즈니스 시나리오와 모범 사례를 기반으로 누락된 세부 정보를 지능적으로 유추합니다.
주요 유추 시나리오:
- 사용자가 "사용자 테이블을 설계해줘"라고 말함 → 유추: username, password, email, phone, status
- 사용자가 "전자상거래 시스템"이라고 말함 → 유추: user, product, order, order_detail 테이블
- 사용자가 "블로그 시스템"이라고 말함 → 유추: user, article, comment, tag, article_tag 테이블
2단계: 참조 문서 로드
설계 요구사항에 따라 적절한 참조 문서를 로드합니다:
- 항상 로드:
references/design-principles.md(핵심 설계 규칙) - 포맷 생성 시:
references/drawdb-formats.md(JSON/DBML 사양) - 예시 참조 시:
references/design-examples.md(유사 시스템 설계)
3단계: 데이터베이스 스키마 설계
다음 지침에 따라 완전한 테이블 구조를 생성합니다:
테이블 설계 체크리스트
각 테이블에 대해:
-
✅ 기본 시스템 필드 추가(사용자가 달리 명시하지 않는 한):
idBIGINT AUTO_INCREMENT PRIMARY KEYcreated_atDATETIME DEFAULT CURRENT_TIMESTAMPupdated_atDATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMPis_deletedTINYINT(1) DEFAULT 0
-
✅ 현실적인 크기의 비즈니스 필드 설계:
- username: VARCHAR(50)
- email: VARCHAR(100)
- phone: VARCHAR(20)
- title: VARCHAR(200)
- description: TEXT
- 전체 크기 표준은
references/design-principles.md참조
-
✅ 적절한 제약 조건 추가:
- 필수 필드에는 NOT NULL
- 선택적 필드에는 DEFAULT 값
- 고유성이 필요한 필드에는 UNIQUE(외래 키 제외)
-
✅ 모든 테이블과 필드에 COMMENT 추가(한국어로)
-
✅ 물리적 FOREIGN KEY 제약 조건을 생성하지 않음
인덱스 설계 전략
각 테이블에 대해 다음 항목을 분석하고 인덱스를 생성합니다:
- WHERE 절 필드: 필터링에 자주 사용되는 필드
- JOIN 필드: 모든
xxx_id외래 키 필드 - ORDER BY / GROUP BY 필드: 정렬 및 그룹화 필드
- 고유 제약 조건: email, phone, order_no 등 → UNIQUE 인덱스
인덱스 명명 규칙:
- 일반 인덱스:
idx_필드명또는idx_필드1_필드2 - 고유 인덱스:
uk_필드명
인덱스 제한:
- 테이블당 최대 5개 인덱스(사용자가 더 요청하지 않는 한)
- 비즈니스 쿼리를 직접 지원하는 인덱스만 생성
관계 설계
테이블 간의 논리적 관계를 식별합니다:
-
일대다(1:N): 가장 일반적
- 예시: user (1) → order (N)
- 구현: order 테이블에
user_id추가 - DrawDB: 다대일 관계
-
일대일(1:1): 테이블 분할용
- 예시: user (1) → user_profile (1)
- 구현: user_profile 테이블에
user_id UNIQUE추가 - DrawDB: 일대일 관계
-
다대다(N:N): 중간 테이블 필요
- 예시: article (N) ↔ tag (N)
- 구현: article_id + tag_id를 가진 article_tag 중간 테이블 생성
- DrawDB: 두 개의 다대일 관계
4단계: 결과물 생성
필요한 모든 출력 파일을 생성합니다:
4.1 종합 설계 문서(Markdown)
잘 구조화된 단일 Markdown 파일을 생성합니다:
구조:
# [프로젝트 이름] 데이터베이스 설계 문서
## 1. 데이터베이스 개요
- 데이터베이스 유형
- 문자 집합
- 핵심 테이블 수
- 주요 기능 모듈
## 2. 테이블 구조 설계
### 2.1 [테이블 이름]
**테이블명**: table_name
**설명**: 테이블 설명
**필드 목록**:
| 필드명 | 유형 | NULL 허용 | 기본값 | 설명 |
|--------|------|-----------|--------|------|
| id | BIGINT | NO | | 기본 키 |
| ... | ... | ... | ... | ... |
**인덱스 목록**:
| 인덱스명 | 유형 | 필드 |
|----------|------|------|
| uk_email | UNIQUE | email |
| idx_username | INDEX | username |
### 2.2 [다음 테이블]
...
## 3. 테이블 관계 설명
- table1 → table2 (1:N): 설명
- table3 ↔ table4 (N:N): 중간 테이블을 통한 설명
## 4. 인덱스 전략 설명
인덱스 설계 결정에 대한 근거 설명
4.2 SQL 스크립트
실행 가능한 SQL 스크립트 생성:
-- Database: project_name
-- Generated: YYYY-MM-DD
-- 테이블 삭제(의존성 역순)
DROP TABLE IF EXISTS `table3`;
DROP TABLE IF EXISTS `table2`;
DROP TABLE IF EXISTS `table1`;
-- 테이블 생성(의존성 순서)
CREATE TABLE `table1` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '주석',
...
PRIMARY KEY (`id`),
UNIQUE KEY `uk_field` (`field`),
KEY `idx_field` (`field`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='테이블 주석';
CREATE TABLE `table2` (
...
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='테이블 주석';
4.3 DrawDB JSON 형식
references/drawdb-formats.md를 따라 DrawDB 호환 JSON 파일 생성:
핵심 형식 요구사항:
- 테이블 ID: 무작위 21자 문자열 사용(예:
"_KV5MtPf2m4sI7Inu8pat") - 필드 ID: 무작위 21자 문자열 사용(예:
"B8rPRTDtOv9oD2Gp4bhWL") - 인덱스 ID: 모든 테이블에서 0부터 시작하는 숫자 증가 사용
- 관계 ID: 무작위 21자 문자열 사용
- 필드 유형: 완전한 유형 정의 포함(예:
"VARCHAR(100)", 유형과 크기를 분리하지 않음) - 크기 필드 없음: 유형 정보는 유형 문자열에 포함됨
- 인덱스 필드: 필드 ID가 아닌 필드 이름 문자열 사용(예:
["email"],[1]아님) - 좌표: x/y 위치에 부동 소수점 숫자 사용
ID 생성:
import random
import string
def generate_id():
chars = string.ascii_letters + string.digits + '_-'
return ''.join(random.choice(chars) for _ in range(21))
레이아웃 전략:
- 그리드 레이아웃 사용:
x = (index % 3) * 450 + 50,y = floor(index / 3) * 400 + 50 - 미리 정의된 색상 순환:
["#6360f7", "#bc49c4", "#ffe159", "#89e667", "#ff9159", "#59d9ff", "#ff5959", "#a0a0a0"]
관계 생성:
- 모든
xxx_id외래 키 필드에 대한 관계 생성 - 테이블 및 필드에 실제 무작위 문자열 ID 사용
- UNIQUE 제약 조건에 따라 카디널리티 설정:
- UNIQUE 있음 → "one_to_one"
- UNIQUE 없음 → "many_to_one"
구조:
{
"tables": [
{
"id": "random_string",
"name": "table_name",
"comment": "테이블 주석",
"color": "#6360f7",
"fields": [
{
"id": "random_string",
"name": "id",
"type": "BIGINT",
"default": "",
"check": "",
"primary": true,
"unique": true,
"notNull": true,
"increment": true,
"comment": "기본 키 ID"
}
],
"indices": [
{
"id": 0,
"fields": ["field_name"],
"name": "idx_field_name",
"unique": false
}
],
"x": 50.0,
"y": 50.0
}
],
"relationships": [
{
"name": "",
"startTableId": "random_string",
"endTableId": "random_string",
"endFieldId": "random_string",
"startFieldId": "random_string",
"id": "random_string",
"updateConstraint": "No action",
"deleteConstraint": "No action",
"cardinality": "many_to_one"
}
],
"notes": [],
"subjectAreas": [],
"database": "generic",
"types": [],
"title": "Project Database"
}
4.4 DrawDB DBML 형식
references/drawdb-formats.md를 따라 DBML 파일 생성:
핵심 사항:
- 소문자 데이터 유형 사용:
bigint,varchar(50),datetime - 대괄호 안에 속성 추가:
[pk, increment, not null, unique, note: '주석'] - 테이블 정의 내
indexes { }블록에서 인덱스 정의 Ref블록을 사용하여 테이블 외부에서 관계 정의- 적절한 관계 기호 사용:
>(다대일),-(일대일)
구조:
Table table_name [headercolor: #6360f7] {
id bigint [pk, increment, not null, unique, note: '주석']
field varchar(100) [not null, note: '주석']
indexes {
field [unique, name: 'uk_field']
}
Note: '테이블 주석'
}
Ref fk_name {
table1.field > table2.id [delete: no action, update: no action]
}
5단계: 최종 확인 및 전달
5.1 출력 디렉토리 규칙
권장 접근 방식(Claude Code 공식 표준 준수):
모든 데이터베이스 설계 파일을 outputs/<project-name>/database/에 저장:
outputs/
└── <project-name>/ # 프로젝트 이름(예: e-commerce-system)
└── database/
├── schema-design.md # 종합 설계 문서
├── schema.sql # 실행 가능한 SQL 스크립트
├── drawdb-schema.json # DrawDB JSON 형식
└── drawdb-schema.dbml # DrawDB DBML 형식
예시:
outputs/
├── e-commerce-system/
│ └── database/
│ ├── schema-design.md
│ ├── schema.sql
│ ├── drawdb-schema.json
│ └── drawdb-schema.dbml
└── task-management-app/
└── database/
├── schema-design.md
└── schema.sql
대체 접근 방식(기존 프로젝트 구조):
프로젝트에 기존 디렉토리 구조가 있는 경우 다음을 사용할 수도 있습니다:
project-root/
└── database/
├── schema-design.md
├── schema.sql
├── drawdb-schema.json
└── drawdb-schema.dbml
5.2 출력 파일 목록
필수 출력(4개 파일):
schema-design.md- 종합 데이터베이스 설계 문서(한국어)schema.sql- 실행 가능한 SQL 스크립트drawdb-schema.json- DrawDB JSON 형식drawdb-schema.dbml- DrawDB DBML 형식
선택적 출력:
er-diagram.png- ER 다이어그램 시각화(도구 사용 가능한 경우)index-strategy.md- 인덱스 전략 문서
5.3 파일 명명 규칙
- kebab-case 사용:
user-authentication-schema.sql - 필요한 경우 버전/날짜 포함:
schema-v1.0.sql또는schema-2024-12-10.sql - 설명적인 이름 사용:
e-commerce-database-schema.sql
5.4 전달 요약
모든 파일을 생성한 후 다음을 포함한 요약을 제공:
- 설계 결정에 대한 간략한 개요
- 생성된 테이블 수
- 주요 관계 및 그 이유
- DrawDB로 가져오는 방법(JSON 또는 DBML)
- 파일 저장 위치 확인
- 다음 단계 제안(예: 인덱스 검토, 개발 환경에 구현)
특별 처리
사용자가 "시스템 필드 없음"을 요청한 경우
최소 구조만 생성:
CREATE TABLE `table_name` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '기본 키',
/* 비즈니스 필드만 */
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='테이블 주석';
사용자가 MySQL이 아닌 데이터베이스를 지정한 경우
SQL 구문을 적절히 조정:
PostgreSQL:
AUTO_INCREMENT대신SERIAL또는BIGSERIAL사용DATETIME대신TIMESTAMP사용- 기본값 및 제약 조건에 대한 다른 구문
SQL Server:
AUTO_INCREMENT대신IDENTITY(1,1)사용DATETIME대신DATETIME2사용- 유니코드 지원을 위해
NVARCHAR사용
Oracle:
- 자동 증가를 위해
SEQUENCE사용 VARCHAR대신VARCHAR2사용- 시간 필드에
DATE또는TIMESTAMP사용
요구사항이 모호한 경우
지능적 유추 적용:
- 비즈니스 도메인 식별(전자상거래, 블로그, CRM 등)
references/design-examples.md의 유사 예시 참조- 도메인에 적합한 공통 필드 포함
- 일반적인 쿼리 패턴을 기반으로 합리적인 인덱스 설계
- 설계 문서에서 가정한 내용 설명
품질 검증
최종 확정 전에 다음을 확인:
- 모든 테이블에 COMMENT가 있는가?
- 모든 필드에 COMMENT가 있는가?
- 필드 크기가 현실적인가?(일반적인 VARCHAR(255)가 아님)
- 테이블당 인덱스 수 ≤ 5개인가?
- 물리적 FOREIGN KEY 제약 조건이 없는가?
- 시스템 필드가 추가되었는가?(사용자가 달리 명시하지 않은 한)
- 모든 이름이 snake_case를 사용하는가?
- 논리적 관계가 명확하게 문서화되었는가?
- SQL 구문이 대상 데이터베이스 유형과 일치하는가?
- JSON/DBML 형식이 DrawDB 사양을 따르는가?
- 모든 외래 키 관계에 해당 Ref 항목이 있는가?
예시 호출
사용자가 말함: "전자상거래 시스템의 데이터베이스를 설계해줘, 사용자, 상품, 주문 기능 포함" → design-principles.md 및 design-examples.md 읽기 → 설계: user_info, product_info, order_info, order_detail 테이블 → 4개 출력 파일 모두 생성
사용자가 말함: "블로그 데이터베이스 설계해줘" → 유추: user, article, comment, tag, article_tag 테이블 → 표준 설계 원칙 따르기 → 모든 출력 생성
사용자가 말함: "PostgreSQL용 사용자 테이블 생성해줘" → 단일 테이블 설계 → PostgreSQL용 SQL 구문 조정 → 모든 출력 형식에 포함
참조
references/design-principles.md- 핵심 설계 규칙 및 표준references/drawdb-formats.md- JSON 및 DBML 형식 사양references/design-examples.md- 실제 설계 예시