컨텍스트 주입
AI 에이전트에게 디자인 시스템 컨텍스트를 효과적으로 전달하는 방법
AI가 디자인 시스템을 일관되게 사용하려면 적절한 컨텍스트가 주입되어야 합니다. CLAUDE.md, 커스텀 명령, MCP 서버를 활용한 컨텍스트 관리 전략을 다룹니다.
컨텍스트 주입 전략
CLAUDE.md 디자인 시스템 섹션
기본 구조
# CLAUDE.md
## Design System
### 컴포넌트 사용 원칙
1. 직접 HTML/스타일링 대신 디자인 시스템 컴포넌트 사용
2. 하드코딩된 값 대신 토큰 참조
3. 접근성 요구사항 준수
### 컴포넌트 선택 가이드
#### 버튼 계열
| 용도 | 컴포넌트 | 예시 |
| ----------- | ------------------------ | ------------ |
| 액션 트리거 | `<Button>` | 저장, 삭제 |
| 페이지 이동 | `<Link>` | 더보기, 상세 |
| 상태 토글 | `<Toggle>` | 즐겨찾기 |
| 메뉴 트리거 | `<DropdownMenu.Trigger>` | 옵션 |
#### 레이아웃 계열
| 용도 | 컴포넌트 |
| ------------- | ------------- |
| Flex 컨테이너 | `<Flex>` |
| Grid 컨테이너 | `<Grid>` |
| 카드 컨테이너 | `<Card>` |
| 섹션 구분 | `<Separator>` |
#### 피드백 계열
| 용도 | 컴포넌트 |
| ------------- | --------------------- |
| 인라인 알림 | `<Alert>` |
| 토스트 알림 | `<Toast>` / `toast()` |
| 확인 대화상자 | `<AlertDialog>` |
| 툴팁 | `<Tooltip>` |
### 토큰 사용
#### 색상
```tsx
// ✅ Good
<div className="bg-background text-foreground">...</div>
<div className="text-destructive">...</div>
// ❌ Bad
<div style={{ background: '#ffffff' }}>...</div>
<div className="text-red-500">...</div>
```
#### 간격
```tsx
// ✅ Good
<div className="p-4 gap-2">...</div>
<div className="space-y-4">...</div>
// ❌ Bad
<div style={{ padding: '16px' }}>...</div>
<div style={{ gap: '8px' }}>...</div>
```
### variant 선택 규칙
#### Button variant
- `default`: 주요 액션 (저장, 확인)
- `destructive`: 위험 액션 (삭제, 초기화)
- `outline`: 보조 액션 (취소)
- `ghost`: 최소 강조 (아이콘 버튼, 툴바)
- `link`: 인라인 링크
#### Alert variant
- `default`: 일반 정보
- `destructive`: 에러, 경고
### 접근성 필수사항
- 아이콘 버튼: `aria-label` 필수
- 폼 필드: `<Label>` 연결 필수
- 모달: 포커스 트랩 자동 적용 확인
- 동적 콘텐츠: Live Region 사용
### 마이크로카피 (콘텐츠 시스템)
- 버튼 레이블은 표준 용어 사용: `저장`, `취소`, `확인`, `삭제`
- 에러 메시지는 “문제 + 해결” 형태로 짧게: `비밀번호가 일치하지 않습니다. 다시 확인해주세요.`
- 사용자 탓/비난 표현 금지: `잘못 입력했습니다` ❌ → `입력을 확인해주세요` ✅프로젝트별 커스터마이징
# CLAUDE.md (프로젝트별)
## Project-Specific Design Rules
### 브랜드 색상
이 프로젝트는 기본 primary 대신 브랜드 색상을 사용합니다:
- Primary: `bg-brand` / `text-brand`
- Primary Foreground: `text-brand-foreground`
### 버튼 스타일
CTA 버튼은 항상 `size="lg"`를 사용합니다:
```tsx
<Button size="lg">시작하기</Button>
```
### 간격 규칙
- 섹션 간: `space-y-8` 또는 `gap-8`
- 카드 내부: `p-6`
- 인라인 요소: `gap-2`
### 금지 사항
- `<div className="flex">` 대신 `<Flex>` 사용
- 인라인 스타일 금지 (예외: 동적 값)
- `!important` 사용 금지모듈화된 규칙 파일
모듈 구조
.claude/
├── CLAUDE.md # 메인 (import 선언)
└── rules/
├── components.md # 컴포넌트 규칙
├── tokens.md # 토큰 규칙
├── patterns.md # UI 패턴
└── accessibility.md # 접근성 규칙components.md
# Component Rules
## Import Convention
```tsx
// 개별 import (권장)
import { Button } from '@/components/ui/button'
import { Card, CardContent } from '@/components/ui/card'
// 배럴 import (피하기 - 번들 크기)
// import { Button, Card } from '@/components/ui'
```
## Composition Patterns
### Card with Actions
```tsx
<Card>
<CardHeader>
<CardTitle>제목</CardTitle>
<CardDescription>설명</CardDescription>
</CardHeader>
<CardContent>{/* 본문 */}</CardContent>
<CardFooter className="justify-end gap-2">
<Button variant="outline">취소</Button>
<Button>확인</Button>
</CardFooter>
</Card>
```
### Form Field
```tsx
<div className="space-y-2">
<Label htmlFor="email">이메일</Label>
<Input id="email" type="email" placeholder="name@example.com" />
<p className="text-sm text-muted-foreground">비즈니스 이메일을 입력하세요.</p>
</div>
```patterns.md
# UI Patterns
## Page Layout
```tsx
<main className="container py-8">
<header className="mb-8">
<h1 className="text-3xl font-bold">페이지 제목</h1>
<p className="text-muted-foreground">페이지 설명</p>
</header>
<section className="space-y-8">{/* 콘텐츠 */}</section>
</main>
```
## Data Display
### Empty State
```tsx
<div className="flex flex-col items-center justify-center py-12 text-center">
<Icon className="h-12 w-12 text-muted-foreground mb-4" />
<h3 className="text-lg font-medium">데이터가 없습니다</h3>
<p className="text-sm text-muted-foreground mb-4">새 항목을 추가해보세요.</p>
<Button>
<PlusIcon className="mr-2 h-4 w-4" />
추가하기
</Button>
</div>
```
### Loading State
```tsx
<div className="flex items-center justify-center py-12">
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
</div>
```
### Error State
```tsx
<Alert variant="destructive">
<AlertCircle className="h-4 w-4" />
<AlertTitle>오류가 발생했습니다</AlertTitle>
<AlertDescription>
{error.message}
<Button variant="link" onClick={retry}>
다시 시도
</Button>
</AlertDescription>
</Alert>
```MCP 서버 연동
디자인 시스템 MCP 서버
// mcp/design-system-server/index.ts
import { Server } from '@modelcontextprotocol/sdk/server/index.js'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
const server = new Server(
{ name: 'design-system', version: '1.0.0' },
{ capabilities: { tools: {}, resources: {} } }
)
// 도구 정의
server.setRequestHandler('tools/list', async () => ({
tools: [
{
name: 'get_component_docs',
description: '컴포넌트 문서 조회',
inputSchema: {
type: 'object',
properties: {
component: { type: 'string', description: '컴포넌트 이름' },
},
required: ['component'],
},
},
{
name: 'find_pattern',
description: 'UI 패턴 검색',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string', description: '검색어 (예: login form, data table)' },
},
required: ['query'],
},
},
{
name: 'validate_usage',
description: '컴포넌트 사용법 검증',
inputSchema: {
type: 'object',
properties: {
code: { type: 'string', description: '검증할 코드' },
},
required: ['code'],
},
},
],
}))
// 도구 실행
server.setRequestHandler('tools/call', async (request) => {
const { name, arguments: args } = request.params
switch (name) {
case 'get_component_docs':
return await getComponentDocs(args.component)
case 'find_pattern':
return await findPattern(args.query)
case 'validate_usage':
return await validateUsage(args.code)
default:
throw new Error(`Unknown tool: ${name}`)
}
})
// 리소스 정의
server.setRequestHandler('resources/list', async () => ({
resources: [
{
uri: 'ds://tokens/colors',
name: '색상 토큰',
mimeType: 'application/json',
},
{
uri: 'ds://tokens/spacing',
name: '간격 토큰',
mimeType: 'application/json',
},
{
uri: 'ds://components/index',
name: '컴포넌트 인덱스',
mimeType: 'application/json',
},
],
}))
const transport = new StdioServerTransport()
await server.connect(transport)MCP 설정
// .claude/mcp.json
{
"mcpServers": {
"design-system": {
"command": "node",
"args": ["./mcp/design-system-server/index.js"],
"env": {
"DS_ROOT": "./packages/ui"
}
}
}
}문서 역할과 컨텍스트 계층 구조
AGENTS.md, CLAUDE.md, DESIGN.md 역할 분리
AI 에이전트가 UI를 만들 때 가장 흔한 문제는 하나의 문서에 구현 규칙과 시각 규칙을 모두 몰아넣는 것입니다.
추천 역할 분리는 아래와 같습니다.
| 문서 | 핵심 질문 | 담아야 할 것 |
|---|---|---|
AGENTS.md | "이 저장소에서 무엇을 어떻게 구현해야 하는가?" | 파일 경계, 기술 스택, 코딩 규칙, 금지 사항 |
CLAUDE.md | "이 프로젝트에서 어떤 컴포넌트와 패턴을 우선 써야 하는가?" | DS quick reference, variant 선택 규칙, 예시 |
DESIGN.md | "이 프로젝트는 어떤 분위기와 시각 규칙을 가져야 하는가?" | 브랜드 성격, 색/타이포 역할, layout 철학, do/don't |
세 문서를 하나로 합치면 초반엔 편해 보여도, 결국 변경 주기와 독자가 달라 유지보수가 어려워집니다.
AGENTS.md는 구현 규칙이라 더 안정적이어야 합니다.CLAUDE.md는 실전 작업 가이드라 더 짧고 선택 중심이어야 합니다.DESIGN.md는 시각 규칙이라 브랜드 변화와 함께 자주 다듬어져야 합니다.
권장 충돌 우선순위
구현 가능 여부와 파일 경계는 AGENTS.md가 우선합니다.
컴포넌트 선택과 variant 규칙은 CLAUDE.md/component docs가 우선합니다.
화면 분위기와 조형 방향은 DESIGN.md가 담당합니다.
문서 계층 자체의 설계 원칙은 DESIGN.md 인터페이스 장과 함께 보는 편이 좋습니다. 실제 품질 제어 루프는 에이전틱 디자인 품질 제어 장에서 이어집니다.
컨텍스트 우선순위
-
세션 컨텍스트 (가장 높음)
- 현재 대화의 지시사항
- 에러 피드백
-
프로젝트 컨텍스트
- 프로젝트
AGENTS.md - 프로젝트
CLAUDE.md - 프로젝트
DESIGN.md
- 프로젝트
-
전역 컨텍스트 (기본값)
- 디자인 시스템 문서
- 기본 규칙
MCP 생태계 확장
2026년 주요 디자인 도구들이 MCP를 채택하면서 컨텍스트 주입의 새로운 채널이 열렸습니다.
| MCP 서버 | 제공자 | 컨텍스트 |
|---|---|---|
| Figma MCP | Figma | 디자인 파일, 변수, 컴포넌트 |
| Storybook MCP | Storybook (개발중) | 컴포넌트 매니페스트, 스토리 |
| Panda CSS MCP | Panda CSS | 토큰, 스타일 계층, 네이밍 규칙 |
MCP 서버 기반 자동 컨텍스트 주입
MCP 서버가 코드베이스를 스캔하여 토큰 정의, 컴포넌트 라이브러리, 스타일 계층, 네이밍 규칙을 구조화된 규칙 파일로 출력합니다. 이 파일이 AI 에이전트의 시스템 레벨 가이드로 작동하여, 수동 컨텍스트 관리 없이도 디자인 시스템을 일관되게 따르는 코드를 생성할 수 있습니다.
정적 규칙 → 동적 MCP 컨텍스트 전환
기존에는 CLAUDE.md나 .cursorrules에 디자인 시스템 규칙을 수동으로 작성했습니다. MCP 서버를 활용하면 코드베이스 변경에 맞춰 컨텍스트가 자동으로 업데이트되어, 규칙 파일이 오래되거나 실제 코드와 불일치하는 문제를 해결합니다.