본문으로 건너뛰기

Claude Code에서 반응형 퍼블리싱 자동화: Skill vs Agent 아키텍처

·8 min read

문제: 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줄만 남음

교훈

  1. AI의 추측은 게으름이 아니라 컨텍스트 한계의 결과다. 데이터를 쪼개서 한계 안에 들어오게 해야 한다.
  2. 규칙은 대화가 아니라 파일에 저장해야 한다. 대화 속 규칙은 컨텍스트가 밀리면 사라진다.
  3. Skill은 진입점, Agent는 실행 환경이다. 둘을 조합하면 사용자 경험(슬래시 커맨드)과 실행 품질(전용 컨텍스트)을 모두 잡을 수 있다.