# Design Md

> 프로젝트 루트에 DESIGN.md — AI 코딩 에이전트가 UI를 일관되게 만들도록 브랜드의 시각 언어 (컬러·타이포·스페이싱·컴포넌트)를 실행 가능한 결정값으로 박은 "디자인 시스템 SSOT" — 를 생성하는 스킬. 기존 코드베이스를 스캔해 실제 값을 추출(현실 기술)하고, 스캔으로 못 채운 부분만 대화로 보완한다(하이브리드). 코드가 없으면 대화 중심으로 폴백한다. 산출 끝에는 프로젝트 지침 파일에 "UI 생성 전 DESIGN.md 읽기" 참조 줄 추가를 반드시 안내한다(DESIGN.md는 자동 로드되지 않기 때문). 그린필드거나 사용자가 육안검증·공유를 원하면 자기완결 preview.html(스와치·타입스케일·컴포넌트 갤러리, 라이트/다크 토글)을 조건부로 함께 생성한다. "미리보기도 만들어줘", "preview.html", "디자인 시스템 미리보기 페이지" 같은 표현에도 반응한다. 다음 표현이 나오면 반드시 이 스킬을 사용한다: "DESIGN.md 만들어줘", "design.md 생성", "디자인 시스템 문서 만들어줘", "디자인 가이드 문서 만들어줘", "디자인 토큰 문서화", "AI가 UI 일관되게 따를 문서 만들어줘", "브랜드 스타일 가이드 마크다운", "UI 컨벤션 문서", "우리 앱 디자인 규칙 문서로 박아줘". 사용자가 "AI/에이전트가 우리 앱 스타일을 일관되게 따르게 하고 싶다"거나, 프로젝트의 색·폰트·간격·컴포넌트를 문서로 고정해 매 UI 생성이 흔들리지 않게 하려 할 때는, 명시적으로 "DESIGN.md"라고 부르지 않아도 이 스킬을 쓴다.

- Skill: `gagip/design-md` (Agent Skill, multi-file: 6 files)
- Install (CLI): `npx skillmds@latest add gagip/design-md`
- Raw SKILL.md: https://api.skillmd.com/api/skills/gagip/design-md/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: gagip (https://skillmd.com/u/gagip)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/gagip/design-md

---


# design-md 스킬

프로젝트 루트에 **`DESIGN.md`** 한 파일을 생성한다. 이 파일은 브랜드의 시각 언어를 AI 코딩 에이전트가
**참조 가능한 결정값**으로 기술한 디자인 시스템의 단일 진실 원천(SSOT)이다.

> **왜 DESIGN.md가 필요한가** — LLM은 세션마다 콜드 스타트라 브랜드 제약을 기억하지 못한다. "기존 스타일에 맞춰줘"는
> 매번 문맥에 우연히 들어온 예시에서 규칙을 *추론*할 뿐이라 UI 생성마다 색·간격·컴포넌트가 흔들린다. 규칙을 파일에 박아
> UI 생성 전에 읽히면, 출력 기준선이 "못 쓸 결과물"에서 "약간 손보면 쓸 결과물"로 올라간다. 이 포맷은 Google Labs의
> `design.md` 스펙이 형식 표준을 정의하고, VoltAgent·oh-my-design 같은 커뮤니티 라이브러리가 실제 예시를 배포하며 사실상
> 표준이 됐다.

> **프로젝트 지침과의 역할 분리** — `AGENTS.md`·`CLAUDE.md` 같은 프로젝트 지침 파일은 "프로젝트를 **어떻게 빌드**하나"(코딩 대상),
> DESIGN.md는 "**어떻게 보이고 느껴져야** 하나"(디자인 대상)를 담당한다. 둘은 겹치지 않는다.

## 이 스킬의 정체성 — "현실 기술" (열망 금지)

대부분의 DESIGN.md 도구는 대화로 취향을 물어 *열망적* 디자인 시스템을 만든다. **이 스킬은 반대로, 기존 코드에서 실제로
쓰이는 값을 먼저 추출한다.** DESIGN.md의 최대 실패 모드가 "문서↔코드 드리프트"(문서엔 있는데 코드엔 없는 값을 에이전트가
믿고 엉뚱한 UI를 생성)이기 때문이다. 고치고 싶은 리디자인이 아니라 **레포의 실제 상태**를 기술한다 — 그래야 에이전트가
문서를 믿고 만든 UI가 기존 코드와 어긋나지 않는다.

## 작성 원칙 (사람용 디자인 문서와 다른 점)

사람용 문서는 근거·감성을 길게 서술해도 되지만, AI용은 **결정론적으로 참조 가능**해야 한다. 다섯 원칙:

1. **선택지가 아니라 결정 + 사용 조건을 준다.** 옵션을 주면 생성마다 다르게 쓴다. 값 하나를 박고 "언제 쓰고, 언제 절대
   안 쓰는지"까지 규정한다. 예: `primary-900 — 화면 최고 강조 액션에만, 한 뷰에 2개 금지`.
2. **값 + 의도를 함께.** hex만도, 원칙만도 실패한다. `#5A67D8`를 던지지 말고 `#5A67D8 — Primary CTA, active links`처럼
   값에 역할을 붙인다.
3. **용도별로 명명한다.** `font-size: 3rem` 나열이 아니라 `Hero h1 = 64px`. 에이전트는 이름→용도 매핑으로 어디에 쓸지
   결정한다.
4. **Don'ts를 반드시, 구체적으로.** 여러 실험에서 don'ts가 do's보다 정확도를 더 크게 올렸다. "cool gray 금지",
   "serif display에 bold 금지"처럼 **구체적 행동 금지**로 쓴다. "깔끔하게" 같은 일반 긍정문은 실패한다.
5. **현실을 쓴다.** 위 "현실 기술" 원칙. 스캔으로 실제 값을 뽑고, 못 채운 것만 대화로 보완한다.

---

## 실행 절차

### Step 1: 대상 파악 + 모드 판별 (하이브리드)

먼저 대상 프로젝트 루트를 정한다(인자가 있으면 그 경로, 없으면 현재 작업 디렉터리 — `git rev-parse --show-toplevel` 폴백 `pwd`).

그다음 **스타일 소스가 있는지** 훑어 브라운필드(코드 있음)/그린필드(코드 없음)를 판별한다:

```bash
# 스타일 소스 존재 여부 스캔 (있으면 브라운필드 = 스캔 우선)
ls tailwind.config.* 2>/dev/null
find . -path ./node_modules -prune -o \( -name '*.css' -o -name '*.scss' -o -name 'theme.*' -o -name 'tokens.*' \) -print 2>/dev/null | head
grep -rEl ':root|--[a-z].*:|font-family|styled|createTheme|StyleSheet.create' src app 2>/dev/null | head
```

- **하나라도 잡히면 브라운필드** → Step 2의 스캔을 돌려 실제 값을 추출하고, 빈 축만 대화로 보완한다.
- **아무것도 없으면 그린필드** → Step 2 스캔을 건너뛰고 곧바로 대화 중심(Step 2의 "대화 보완")으로 디자인 시스템을 정의한다.

기존에 `DESIGN.md`가 이미 있으면 Read로 읽어 **덮어쓸지/보강할지**를 사용자에게 확인한다 — 기존 결정을 임의로 지우지 않는다.

### Step 2: 값 추출 (스캔 우선, 부족분만 대화)

목표는 필수 6축(브랜드 톤·컬러·타이포·스페이싱/레이아웃·컴포넌트·Do/Don't)을 채우는 것이다.
**축별 구체 grep 패턴과 무엇을 뽑을지는 `references/section-spec.md`를 읽어 따른다.** 요지만 옮기면:

- **컬러**: `:root` 커스텀 프로퍼티, `tailwind.config` `theme.colors`, hex/rgb/hsl 리터럴을 grep해 **실제 쓰이는 색**과
  빈도를 뽑는다. 값만이 아니라 **역할**(어디에 쓰이나)을 코드 맥락에서 읽는다.
- **타이포**: `font-family`, `@font-face`, `next/font`, `fontFamily`, 반복되는 `font-size`/`fontSize` 스케일을 뽑아
  **용도별**로 정리한다.
- **스페이싱/레이아웃**: 베이스 단위(4/8px), 반복 padding/margin 값, `max-width`, 그리드/컨테이너를 뽑는다.
- **컴포넌트**: 버튼·인풋·카드·모달의 실제 스타일(radius·padding·height·shadow)을 **절대값**으로 뽑는다.

> **스캔의 핵심은 "빈도와 역할"이다.** 코드에 색이 40개 있어도 전부 토큰이 아니다. 자주·의미 있게 쓰인 값을 골라
> 시맨틱 토큰(primary/surface/ink…)으로 승격하고, 일회성 값은 버린다. 판단이 서지 않으면 사용자에게 묻는다.

**대화 보완**: 스캔으로 못 채운 축(예: 브랜드 톤·personality, Don'ts, 접근성 의도)은
구조화 질문 도구가 있으면 그 도구로 좁힌다. 없으면 추천안을 첫 번째에 둔 번호 목록으로 대화에서 묻는다.
한 번에 다 펼치지 말고 빈 축을 하나씩 물어 확정한다. 그린필드면 이 대화가 주 입력이 된다.

### Step 3: DESIGN.md 작성

`templates/DESIGN.template.md`를 뼈대로 쓴다. 이 파일은 **2부 구성**이다:

1. **YAML frontmatter** — 기계가 파싱할 토큰(colors/typography/spacing/rounded/components). Google `design.md` 스펙 형식.
2. **Markdown body** — 사람이 읽을 근거 + 사용 규칙. VoltAgent 9섹션 헤더를 따른다.

**필수 6섹션은 반드시 채운다** (하나라도 비면 저장하지 않는다):

| 섹션 | 무엇을 |
|---|---|
| **Overview / Visual Theme** | 브랜드 personality·타깃·톤 3~5문장 (모호 케이스의 판단 기준) |
| **Colors** | 토큰마다 `값 + 역할 + "언제 쓰고 언제 금지"` (표) |
| **Typography** | 서체·스케일·weight를 **용도별**(display/body/label/caption)로 |
| **Spacing & Layout** | 베이스 단위 + 스케일(xs~xl), 그리드·max-width |
| **Components** | 버튼·인풋·카드를 radius·padding·height·shadow **절대값**으로 |
| **Do's & Don'ts** | 구체적 행동 규칙. **정확도 최대 레버 — 절대 생략 금지** |

권장 섹션(값이 있으면 추가): Depth & Elevation · Responsive Behavior · Accessibility. 선택: Motion · Known Gaps.

**값 granularity와 섹션별 상세 형식·예시는 `references/section-spec.md`, Don'ts 예문은 `references/dos-and-donts-bank.md`를 참고한다.**

> **인라인 토큰만, 거대 JSON 통째 금지.** DESIGN.md에는 **압축된 시맨틱 토큰 표**(이름+값+역할)만 인라인한다. 원시 토큰
> 덤프를 통째로 붙이지 않는다 — DESIGN.md는 매 요청마다 전량 로드되므로, 부풀면 토큰을 크게 낭비한다(성숙 프로덕션에서
> 특히 비싸다). 값+규칙의 압축 구조가 이 파일의 가치다.

### Step 4: 자체 점검 게이트 (저장 직전)

저장 전 아래를 확인한다. 하나라도 실패하면 고친 뒤 저장한다:

- 필수 6섹션이 모두 채워졌는가 (특히 **Do's & Don'ts**가 비어 있지 않은가)
- 각 토큰에 **값 + 역할/사용조건**이 붙었는가 (값만 나열된 칸이 없는가)
- 값이 **구체적**인가 (hex·px·절대값 — "부드러운 회색" 같은 추상 표현이 아님)
- **현실을 기술했는가** — 스캔으로 뽑은 값이면 실제 코드와 일치하는가, 대화로 정한 값이면 열망이 아니라 합의된 값인가
- YAML frontmatter의 토큰과 body의 표가 **서로 어긋나지 않는가**

### Step 5: 저장 + 참조 줄 안내 (⚠️ 반드시)

DESIGN.md를 **프로젝트 루트**에 `Write`한다 (`<root>/DESIGN.md`). 코드 옆에 둬야 SSOT가 레포 밖으로 새지 않는다.

그다음 **가장 중요한 마무리** — DESIGN.md는 **자동으로 읽히지 않는다.** 프로젝트 지침 파일에 참조 줄을 걸어야 실제로
참조된다. 이걸 빠뜨리면 파일이 있어도 에이전트가 무시한다. 아래 줄 추가를 **제안하고, 사용자가 동의하면 반영**한다:

```markdown
## 디자인
UI를 생성·수정하기 전 항상 프로젝트 루트의 `DESIGN.md`를 읽고 그 토큰·규칙을 따른다.
```

대상은 상황별로 갈린다:
- 현재 하네스가 읽는 프로젝트 지침 파일(`AGENTS.md`, `CLAUDE.md` 등)이 있으면, 현재 경로에
  가장 가까운 적용 범위의 파일에 `Edit`로 추가한다.
- 둘 이상이 별도 파일로 공존해 정본이 불명확하면 어느 파일을 바꿀지 사용자에게 확인한다.
- **프로젝트 지침 파일이 없으면**(그린필드에서 흔하다) → 두 하네스가 함께 읽을 수 있는 **`AGENTS.md`를
  새로 만들어 이 줄을 넣자고 제안**하고, 동의 시 `Write`로 생성한다.
  DESIGN.md만 있고 앵커가 없으면 자동 로드가 안 돼 무용지물이므로, "안내만" 하고 끝내지 않는다 — 그린필드에서 preview는
  적극 만들면서 참조 앵커를 안 거는 비대칭을 피한다.

동의가 없으면 이 줄을 그대로 보여주며 "직접 넣어달라"고 안내한다. 저장한 DESIGN.md 경로와 이 참조 줄 처리 결과를 함께
보고한다.

### Step 6: preview.html 조건부 생성 (시각 레퍼런스)

DESIGN.md는 텍스트라 사람이 "이게 온-브랜드인가"를 눈으로 보기 어렵다. **`preview.html`은 그 값을 한 화면에 렌더한
시각 레퍼런스 보드**다(스와치·타입스케일·스페이싱 바·컴포넌트 갤러리 + 라이트/다크 토글). **항상 만들지는 않는다** —
이미 렌더되는 실앱이 있으면 대체로 중복이기 때문이다. 아래 트리거로 판단한다:

- **그린필드**(Step 1에서 볼 실앱이 없다고 판별) → preview가 유일한 시각화다. **생성을 권장**한다.
- **브라운필드**(실앱 있음) → 기본은 생성하지 않고, **공유·육안검증용으로 만들지 옵션으로 제안**한다.
- 사용자가 "미리보기/preview 만들어줘"라고 명시하면 모드와 무관하게 만든다.

참조-줄과 같은 **제안 → 동의 시 생성** 패턴이다. 동의하면 `templates/preview.template.html`을 뼈대로,
**방금 저장한 DESIGN.md의 값**을 채워 `<root>/preview.html`로 `Write`한다. **채우는 방법·섹션별 규칙·자기완결
제약·다크 토글 처리는 `references/preview-spec.md`를 읽어 따른다.** 핵심만 옮기면:

- **자기완결** — 외부 폰트·CSS·JS·CDN을 절대 참조하지 않는다(모두 인라인). 오프라인에서 그대로 열려야 한다.
- **값 100% 일치** — preview는 DESIGN.md의 시각화일 뿐이다. hex·px·서체를 임의로 바꾸지 않는다.
- **다크 토글, 열망 금지** — DESIGN.md에 다크 팔레트가 **있으면** 그 값으로 스왑, **없으면** 토글이 페이지 배경(크롬)만
  전환해 같은 브랜드 색을 밝은/어두운 주변에서 대조하게 한다. **없는 다크 색을 지어내지 않는다.**

저장 후 "브라우저로 `preview.html`을 열어 확인하라"고 안내한다. 커밋·push는 하지 않는다.

### Step 7: 확장 안내 (토큰 파일 — 아직 생성하지 않음)

이 스킬은 **DESIGN.md + (조건부) preview.html**까지 생성한다. **토큰 파일**은 아직 만들지 않고, 필요 조건이 보이면
사용자에게 옵션으로만 안내한다 (템플릿에도 주석 슬롯으로 표시돼 있다):

- **토큰 파일** — 빌드 파이프라인(Tailwind/Style Dictionary 등)이 감지되면 **DTCG JSON 정본**($value/$type)을 보편
  코어로 두고, 감지된 주력 스택용 소비판(웹=`--ds-*` CSS·Tailwind, 네이티브=Kotlin/Swift 등)을 붙여 emit하는 게 유용하다.
  DTCG JSON은 플랫폼 중립이라 iOS↔Android처럼 CSS를 공유 못 하는 네이티브에서 특히 값이 크다.

> 토큰 파일을 아직 자동 생성하지 않는 이유: 성숙 프로덕션에서 DESIGN.md에 원시 토큰을 통째로 인라인하면 매 요청마다
> 토큰을 크게 과소비하고, 에이전트가 기존 컴포넌트를 재사용하지 않고 재생성하는 기술부채가 생긴다는 실측 보고가 있다.
> 그래서 코어(DESIGN.md)는 가볍게 두고, 소비판 토큰 파일은 빌드 파이프라인이 실제로 감지될 때만 별도 emit하는 게 맞다.

---

## 주의사항

- **DESIGN.md + (조건부) preview.html까지 생성한다. 토큰 파일은 아직 만들지 않는다**(조건 보이면 안내만). 코드
  (컴포넌트 등)를 수정하지 않는다 — `Write`는 DESIGN.md·preview.html에, `Edit`는 프로젝트 지침의 참조 줄 추가에만 쓴다.
- **preview.html은 조건부·동의 후.** 항상 만들지 않는다 — 그린필드면 권장, 브라운필드면 옵션 제안. 자기완결(외부 참조 0)이며
  값은 DESIGN.md와 일치해야 하고, 없는 다크 팔레트를 지어내지 않는다.
- **필수 6섹션 강제.** 특히 Do's & Don'ts가 없으면 저장하지 않는다 — 이게 AI 정확도의 최대 레버다.
- **현실 기술, 열망 금지.** 브라운필드면 스캔 값이 실제 코드와 일치해야 한다. 못 채운 축만 대화로 보완한다.
- **참조 줄 안내를 빠뜨리지 않는다.** DESIGN.md는 자동 로드되지 않으므로, 프로젝트 지침의 참조가 없으면 무용지물이다.
- **기존 DESIGN.md를 임의로 덮어쓰지 않는다.** 있으면 보강/덮어쓰기를 사용자에게 확인한다.
- **커밋·push는 하지 않는다.** 저장까지만 하고, 커밋 여부는 사용자가 프로젝트 규약대로 판단한다.

