Claude Code가 일관된 UI를 생성하도록 design-rules.md를 만든 과정
"예쁘게 만들어줘"의 함정
AI 코딩 도구에게 "버튼 예쁘게 만들어줘"라고 말하면 어떤 일이 벌어질까?
훈련 데이터에서 "예쁜 버튼"으로 학습된 패턴을 그대로 뱉어낸다. border-radius: 12px, box-shadow: 0 4px 6px rgba(0,0,0,0.1), 왼쪽에 border가 있는 blockquote. GitHub에서 봤던, Medium에서 봤던 그 흔한 스타일들.
문제는 그게 우리 디자인 시스템의 토큰이 아니라는 것이다.
디자인 시스템을 운영하면서 이런 일이 반복됐다:
1. Claude Code에게 "카드 컴포넌트 만들어줘"
2. border-radius: 8px, padding: 20px 같은 하드코딩 값이 나옴
3. 수동으로 var(--radius-lg), var(--spacing-5)로 수정
4. 다음 컴포넌트에서 또 같은 일 반복
매번 "토큰 써"라고 말해도 LLM은 다음 요청에서 또 잊어버린다. 컨텍스트 윈도우 밖으로 밀려나기 때문이다.
시도 1: CLAUDE.md에 규칙 적기
처음엔 단순하게 접근했다. CLAUDE.md에 "토큰 써라"고 적었다.
```markdown
## 디자인 시스템 규칙
- 하드코딩 색상 금지, var(--color-*) 사용
- 하드코딩 간격 금지, var(--spacing-*) 사용효과가 있긴 했다. 하지만 문제가 있었다:
1. 규칙이 길어지면 무시된다 - CLAUDE.md가 길어질수록 뒷부분 규칙은 적용 안 됨
2. 맥락 의존적이다 - "UI 만들어줘" 요청이 아닌 경우에도 항상 로드됨
3. 업데이트가 안 된다 - 규칙을 바꿔도 이미 설정된 프로젝트들은 그대로
근본적인 해결책이 필요했다.
시도 2: UserPromptSubmit Hook으로 규칙 주입
Claude Code에는 Hook 시스템이 있다. 사용자가 프롬프트를 제출할 때마다 특정 명령을 실행할 수 있다.
아이디어는 간단했다:
- "버튼", "카드", "UI" 같은 키워드가 프롬프트에 있으면
- design-rules.md 파일을 컨텍스트에 주입
핵심은 node_modules에서 직접 읽는다는 것이다. 파일을 프로젝트에 복사하지 않고 패키지에서 바로 참조한다. npm 업데이트하면 규칙도 자동으로 최신 버전이 된다.
design-rules.md: 무엇을 담았나
단순히 "토큰 써라"가 아니라, LLM의 행동 패턴 자체를 제약하는 규칙을 설계했다.
1. 훈련 데이터 패턴 금지 (섹션 0)
이 섹션이 가장 중요하다. LLM에게 "네가 많이 본 패턴을 그대로 쓰지 마"라고 명시한다.
## 0. 훈련 데이터 패턴 사용 금지 (Anti-Pattern)
> ⚠️ 이 섹션은 모든 규칙보다 우선한다.
금지되는 행동:
- "GitHub에서 이렇게 하니까..." → ❌
- "대부분의 웹사이트가 이렇게 하니까..." → ❌
- "흔히 보는 형태"를 그대로 만드는 것 → ❌구체적인 안티패턴 목록도 포함했다:
컴포넌트
금지 패턴
이유
Blockquote
border-left: 4px solid
하드코딩 px, GitHub/Medium 편향
Alert
✓, ⚠ 텍스트 아이콘
SVG만 허용
Card
box-shadow: 0 4px 6px
Shadow 금지
Button
border-radius: 8px 이상
토큰만 사용
2. "그냥 만들어줘" 요청 대응
사용자가 구체적인 스타일 없이 요청하면 LLM이 임의로 결정하지 않고 되묻도록 했다.
❌ 잘못된 대응:
"Blockquote 컴포넌트를 만들겠습니다."
→ 훈련 데이터 기반으로 왼쪽 border 스타일 생성
✅ 올바른 대응:
"Blockquote 컴포넌트를 만들기 전에 스타일을 확인하고 싶습니다.
1. 배경색만 다른 단순한 박스 스타일?
2. 왼쪽에 아이콘이 있는 스타일?
3. 테두리가 있는 스타일?
4. 기타 (설명해주세요)
어떤 스타일을 원하시나요?"이 규칙 하나로 LLM의 "멋대로 디자인" 문제가 상당히 줄었다.
3. 필수 제약 14가지
토큰 사용 규칙 외에도 UI 품질을 위한 제약들을 정의했다:
- 2.1 Border Radius: 기본값 4px, 8px 이상은 예외적 상황만
- 2.4 화면당 컴포넌트 수: 최대 7개 (Miller's Law)
- 2.6 컨테이너 중첩 금지: 불필요한 wrapper div 금지
- 2.7 단일 시각적 피드백: hover 시 배경색 하나만 변경
- 2.8 이모지/텍스트 아이콘 금지: SVG만 사용
- 2.9 Shadow 사용 제한: Modal/Dropdown/Toast만 허용
- 2.11 Header > Sidebar 위계: 레이아웃 구조 강제
4. Generation Protocol 4단계
LLM이 UI를 생성할 때 따라야 하는 검증 프로세스를 정의했다:
## 3. Generation Protocol
### Step 1: 목적 파악 (Purpose)
- 이 UI의 주요 사용자 액션은?
- 기존 컴포넌트로 해결 가능한가?
### Step 2: 토큰/컴포넌트 선택 (Selection)
- 사용할 색상 토큰 목록 (최대 3개)
- @design-geniefy/ui 컴포넌트 중 재사용 가능한 것
### Step 3: 검증 (Validation)
- [ ] 하드코딩 색상 없음
- [ ] 이모지/텍스트 아이콘 없음
- [ ] shadow 없음 (예외 제외)
- ...
### Step 4: 위반 시 거부 (Rejection)
❌ 제약 위반 발견
위반 항목:
1. [C-2.3] 하드코딩 색상: color: #333 → var(--color-foreground) 사용위반이 발생하면 생성을 거부하고 수정하도록 강제한다. 그냥 경고가 아니라 거부다.
자동 검증: lint-design-rules.sh
규칙을 정해도 위반을 잡아내지 못하면 무용지물이다. PostToolUse Hook으로 컴포넌트 파일 작성 후 자동 검증을 돌린다.
컴포넌트를 작성할 때마다 즉시 피드백이 온다. LLM도 이 피드백을 받고 자동으로 수정한다.
bash
#!/bin/bash
# design-rules.md 위반 탐지 스크립트
# 1. 텍스트 아이콘/이모지 탐지
TEXT_ICONS=$(grep -E '[""]|[✓✔✅⚠️❌✕]' "$FILE_PATH")
if [ -n "$TEXT_ICONS" ]; then
echo "❌ [2.8 위반] 텍스트 아이콘/이모지 사용 금지"
fi
# 2. 하드코딩 색상 탐지
HARDCODED_COLORS=$(grep -E "#[0-9a-fA-F]{3,8}" "$FILE_PATH" | grep -v "var(--")
if [ -n "$HARDCODED_COLORS" ]; then
echo "❌ [2.3 위반] 하드코딩 색상 사용 금지"
fi
결과: 일관된 UI 생성
이 시스템을 도입한 후:
Before:
- LLM에게 "카드 만들어줘" → box-shadow, border-radius: 12px 난무
- 수동으로 토큰으로 교체
- 다음 요청에서 또 반복
After:
- LLM에게 "카드 만들어줘" → 스타일 확인 질문
- "배경과 border로 구분되는 스타일" 선택
- var(--radius-lg), var(--spacing-4), border: 1px solid var(--color-border) 자동 적용
- 위반 시 자동 거부 및 수정
배운 것
1. LLM은 명시적 제약이 필요하다
"토큰 써라"는 충분하지 않다. "GitHub 스타일 쓰지 마", "border-left: 4px 쓰지 마" 같은 구체적인 금지 목록이 필요하다. 훈련 데이터 패턴을 명시적으로 차단해야 한다.
2. 검증 자동화가 핵심이다
규칙을 정해도 지키지 않으면 의미 없다. Hook과 스크립트로 자동 검증하고, 위반 시 즉각 피드백을 주는 시스템이 필요하다.
3. 규칙도 버전 관리가 필요하다
design-rules.md를 프로젝트에 복사하지 않고 node_modules에서 참조하는 이유가 여기 있다. 규칙이 업데이트되면 npm 업데이트 한 번으로 모든 프로젝트에 반영된다.
다음 단계
현재 design-rules.md는 v1 상태다. 앞으로 추가할 것들:
- 접근성 규칙 (aria-label 필수 등)
- 반응형 검증 (고정 width 탐지)
- 컴포넌트별 세부 규칙 (Button의 variant별 토큰 매핑 등)
LLM이 일관된 UI를 생성하게 만드는 건 규칙을 잘 정의하고, 자동으로 강제하는 시스템을 만드는 일이다. "예쁘게 만들어줘"는 이제 금지어다.