Claude Code에서 반응형 퍼블리싱 자동화: Skill vs Agent 아키텍처
문제: AI가 "추측"하는 이유
Figma 디자인을 반응형 코드로 변환할 때, 브레이크포인트가 4개(모바일/태블릿/데스크톱/와이드)라면 각각의 디자인 스펙을 Figma API로 조회해야 한다. 문제는 이 데이터가 매우 크다는 것.
하나의 브레이크포인트를 get_design_context로 조회하면 수백 줄의 JSON이 반환된다. 4개 브레이크포인트 × 5개 섹션이면 20번의 API 호출, 수천 줄의 데이터가 된다.
Claude Code의 컨텍스트 윈도우는 유한하다. 데이터가 쌓이면 앞부분을 잊기 시작하고, 잊은 부분은 추측으로 대체한다.
실제 동작:
1. lg(와이드) 시안 조회 ✅ (컨텍스트 여유)
2. md(데스크톱) 시안 조회 ✅ (아직 괜찮음)
3. sm(태블릿) 시안 조회 ⚠️ (lg 데이터가 밀려남)
4. base(모바일) 시안 조회 💥 (md 데이터도 흐릿해짐)
5. 코드 구현 시 → "sm은 md와 비슷하겠지" → 추측 시작이것은 AI의 "게으름"이 아니라 기술적 한계에서 발생하는 구조적 문제다.
해결 1: 섹션 단위로 쪼개기
페이지 전체를 한번에 처리하는 대신, 섹션별로 반복한다.
❌ 기존: 페이지 전체 × 4BP = 거대한 컨텍스트
✅ 개선: 섹션1 × 4BP → 구현 → 섹션2 × 4BP → 구현 → ...한 섹션의 4BP 데이터는 컨텍스트에 충분히 담긴다. 구현이 끝나면 그 섹션의 Figma 데이터는 더 이상 필요 없으므로, 다음 섹션 작업 시 자연스럽게 밀려나도 문제없다.
해결 2: Skill이 아니라 Agent로
Claude Code에는 커스텀 로직을 정의하는 두 가지 방법이 있다.
Skill (.claude/skills/)
스킬은 메인 컨텍스트에 내용이 합쳐진다.
[메인 컨텍스트 = 1개의 윈도우]
├── 시스템 프롬프트
├── 스킬 내용 로드 ← 여기에 추가됨
├── 사용자 대화 히스토리
├── 섹션1 Figma 조회 결과 ← 누적
├── 섹션1 코드 수정 결과 ← 누적
├── 섹션2 Figma 조회 결과 ← 누적
└── 💥 컨텍스트 포화스킬에서 Task()로 서브에이전트를 spawn할 수 있지만, 오케스트레이션 자체가 메인 컨텍스트에서 돌아가므로 결과를 계속 받아서 누적하게 된다.
Agent (.claude/agents/)
에이전트는 별도 프로세스로 실행된다.
[메인 컨텍스트] [에이전트 = 별도 프로세스]
├── 사용자 대화 ├── 에이전트 시스템 프롬프트 (.md)
├── Task() 호출 1줄 ├── 섹션1: 4BP 조회 → 비교 → 구현
├── ← 최종 결과 요약만 수신 ├── 섹션2: 4BP 조회 → 비교 → 구현
│ ├── ... (자체 윈도우에서 처리)
└── 메인은 깨끗 └── 완료 → 결과 반환에이전트의 .md 파일이 시스템 프롬프트로 자동 로드되므로:
- 브레이크포인트 정의, 병합 규칙, 컴포넌트 목록 등이 항상 포함됨
- 내가(AI가) 프롬프트를 즉석에서 작성할 필요 없음 → 재현성 보장
- 메인 컨텍스트가 오염되지 않음 → 대화 계속 가능
아키텍처: Skill → Agent 위임 패턴
최종 구조는 스킬이 에이전트의 진입점 역할을 한다.
사용자: /responsive-publish 메인 페이지 URL([base, sm, md, lg])
│
├── Skill (SKILL.md) — 얇은 래퍼
│ "responsive-publisher 에이전트에 위임하라"
│ └── Task(subagent_type: "responsive-publisher", prompt: 사용자 입력)
│
└── Agent (responsive-publisher.md) — 전용 컨텍스트
├── STEP 0: URL 파싱 + 파일 경로 결정
├── PHASE 1: base 조회 → 섹션 식별
├── PHASE 2: 섹션별 루프
│ ├── 섹션1: BP별 조회 → 비교 → 구현
│ ├── 섹션2: BP별 조회 → 비교 → 구현
│ └── ...
├── PHASE 3: 이미지/아이콘 자산 처리
├── PHASE 4: type-check + 완료 보고
└── → 결과 요약만 메인에 반환왜 Skill을 유지하는가?
사용자는 /responsive-publish라는 슬래시 커맨드로 호출한다. Agent를 직접 호출하려면 Task(subagent_type: "responsive-publisher")를 사용자가 알아야 하는데, 이건 불편하다. Skill이 이 진입점 역할을 해준다.
Agent 파일 구조
# .claude/agents/responsive-publisher.md
---
name: responsive-publisher
description: 반응형 퍼블리싱 에이전트
---
## 프로젝트 컨텍스트
- 앱, 스택, 브레이크포인트 정의
## 기존 컴포넌트 목록
- Header, Footer, ProductCard, ...
## PHASE 1: 섹션 식별
- base URL로 전체 구조 파악
## PHASE 2: 섹션별 루프
- 조회 → 비교 → 구현 반복
- 병합 규칙 (cascade, textStyle, 표시/숨김 패턴)
## PHASE 3~4: 자산 처리 + 검증이 파일이 에이전트의 시스템 프롬프트가 된다. 매번 동일한 규칙으로 실행되므로 "이번엔 잘 써야지"라는 불확실성이 없다.
임시 서브에이전트 vs 구조화된 에이전트
| "서브에이전트로 해줘" | /responsive-publish | |
|---|---|---|
| 프롬프트 | AI가 즉석 작성 → 매번 다름 | .md 파일에 고정 → 항상 동일 |
| 규칙 누락 | 빠뜨릴 수 있음 | 파일에 내장, 빠뜨릴 수 없음 |
| 재현성 | ❌ | ✅ |
| 유지보수 | 대화로만 전달 | .md 수정 → 다음 호출부터 반영 |
| 메인 컨텍스트 | 프롬프트 작성 과정이 남음 | Task() 1줄만 남음 |
교훈
- AI의 추측은 게으름이 아니라 컨텍스트 한계의 결과다. 데이터를 쪼개서 한계 안에 들어오게 해야 한다.
- 규칙은 대화가 아니라 파일에 저장해야 한다. 대화 속 규칙은 컨텍스트가 밀리면 사라진다.
- Skill은 진입점, Agent는 실행 환경이다. 둘을 조합하면 사용자 경험(슬래시 커맨드)과 실행 품질(전용 컨텍스트)을 모두 잡을 수 있다.