
요약
안녕하세요, 당근 디자인 시스템 팀에서 프론트 엔드 개발을 하고 있는 조이라고 해요.
요즘 AI로 화면을 만든다는 이야기가 많아졌어요. v0, Bolt, Lovable 같은 도구들이 프롬프트 한 줄로 UI를 뚝딱 만들어주는 시대가 됐죠. 그런데 디자인 시스템을 운영하는 팀 입장에서 보면, “그럴듯한 화면”과 “우리 제품다운 화면”은 완전히 다른 문제예요.
당근에는 SEED라는 디자인 시스템이 있어요. 컴포넌트, 토큰, 레이아웃 규칙, 카피 가이드까지 — 하나의 화면을 만들 때 지켜야 할 결정이 수십 가지예요. AI가 아무리 예쁜 화면을 그려줘도, 이 결정들을 모르면 “당근스러운 화면”이 나올 수 없어요. 결국 핵심은 픽셀을 그리는 게 아니라, 디자인 시스템이 요구하는 결정들을 자동화하는 것이었어요.
이 글에서는 그 고민에서 출발한 도구 Kraft가 어드민 → CLI → 에이전트로 형태를 바꿔가며, “의사결정 자동화”에 초점을 맞춰온 과정을 정리해보려고 해요. 디자인 시스템에 AI를 접목하고 싶지만 “어디서부터 시작해야 하지?”라는 질문 앞에서 멈춰 있는 분들께 이 글이 도움이 되길 바래요.
배경: 화면 하나 만드는 게 이렇게 어려운 일이었나?
당근에서는 새로운 화면이 필요할 때마다 보통 이런 흐름을 거쳤어요.
기획자가 요구사항을 정리하고, 디자이너가 피그마에서 화면을 그리고, 개발자가 그걸 코드로 옮기는 거예요. 이 과정이 짧으면 며칠, 길면 몇 주가 걸렸어요.
아이디어를 빠르게 검증하고 싶을 때, 화면을 만드는 것 자체가 병목이 됐어요. 그래서 자연스럽게 AI 바이브 코딩 도구들을 많이 활용하게 됐어요. Lovable, v0, Bolt 같은 도구로 프롬프트 한 줄에 화면을 뚝딱 만들어보는 거죠.
실제로 꽤 잘 됐어요. 빠르고, 진입 장벽도 낮았어요. 하지만 쓰다 보니 한계가 분명했어요.
기존 도구들로는 풀리지 않았던 것들
Lovable, v0 같은 바이브 코딩 도구
- SEED 디자인 시스템 컴포넌트를 쓸 수 없었어요. 이 도구들은 자체 컴포넌트(shadcn/ui, Tailwind 기반 등)로 화면을 만들어요. 결과물이 아무리 예뻐도 당근 앱에 그대로 넣을 수 없어요. SEED의 ActionButton, AppBar, BottomSheet 같은 컴포넌트가 아니라 범용 <Button>, <Modal>이 나오니까요.
- 아이콘, 토큰 같은 패키지 맥락을 주입할 수 없었어요. 당근에는 @karrotmarket/icon 같은 자체 아이콘 패키지가 있고, 색상/여백/radius도 SEED 토큰으로 관리해요. 외부 도구는 이런 패키지의 존재 자체를 몰라요.
- 결과물이 일회성이었어요. 한 번 생성하면 끝이에요. 디자인 시스템이 업데이트되거나 컴포넌트 API가 바뀌어도, 이미 만들어진 화면에는 반영할 방법이 없었어요.

Figma Make (Figma AI)
- 피그마라는 캔버스에 갇혀 있었어요. 결과물이 피그마 레이어로 나와요. 코드가 아니라 디자인 파일이에요. 결국 개발자가 다시 코드로 옮겨야 해요 — 처음에 해결하려던 “개발자 병목” 문제가 그대로 남아요.
- 컴포넌트 외의 맥락 주입이 어려웠어요. SEED 컴포넌트 라이브러리를 피그마에 연결할 수는 있지만, 아이콘 패키지, spacing 토큰의 맥락별 규칙, 폼 패턴 같은 “코드 레벨의 지식”은 주입하기 어려웠어요.
- 템플릿 동기화가 안 됐어요. 피그마에서 템플릿을 만들어 여러 프로젝트에서 쓰다가, 원본 템플릿이 업데이트되면? 이미 그 템플릿을 기반으로 만든 프로젝트들에는 변경이 반영되지 않았어요. 각각 수동으로 업데이트해야 했어요.

그래서 질문이 바뀌었어요
기존 도구들을 충분히 써본 뒤에야, 진짜 질문이 뭔지 알게 됐어요. “AI로 화면을 그리게 할 것인가?”가 아니라 “어떤 결정을 AI에게 맡길 것인가?”였어요.
바이브 코딩 도구는 “화면을 빠르게 그리는 것”에 집중했고, Figma AI는 “디자인 파일을 빠르게 만드는 것”에 집중했어요. 하지만 우리에게 필요한 건 그 사이에 있었어요
SEED 디자인 시스템의 규칙을 알고 있는 상태에서, 코드로 바로 쓸 수 있는 화면을 만드는 것. 컴포넌트 선택, 토큰 적용, 레이아웃 구조, 카피 톤, 상태 처리까지 — 디자인 시스템이 요구하는 수십 가지 결정을 자동화하는 것이 핵심이었어요.
이게 Kraft를 만들게 된 이유예요.

Kraft 란?
Kraft는 프롬프트만으로 SEED(디자인 시스템) 기반의 화면을 만들고, 빠르게 확인/공유/반복할 수 있게 해주는 도구예요. 단순히 “AI가 화면을 그려줌”이 아니라, ‘당근스러운 화면’을 만들어내기 위한 의사결정 자동화 도구예요.
Kraft는 같은 목표를 향해 여러 형태로 발전 중이고, 각 형태는 “사용자”와 “확장성”의 범위를 다르게 설정한 결과예요.
Kraft의 3가지 형태: 어드민 → CLI → 에이전트
어드민: 빠른 생성·프리뷰·배포
초기 Kraft는 웹 기반 에디터/대시보드 형태로, 프롬프트 → 프리뷰 → 배포 → 웹뷰에서 확인(QR/스킴) 흐름을 빠르게 제공했어요.
처음 만들 때의 가설은 단순했어요. “SEED 컴포넌트를 아는 AI에게 프롬프트를 주면, 바로 쓸 수 있는 화면이 나올 거다.” 그래서 웹에서 바로 접근할 수 있는 어드민 형태로 만들었어요.
- 강점은 확실했어요
- 진입 장벽이 낮았어요. 설치 없이 URL만 열면 바로 쓸 수 있었어요.
- 공유가 쉬웠어요. QR이나 딥링크로 만든 화면을 바로 웹뷰에서 확인할 수 있었어요.
- “프롬프트 → 프리뷰 → 배포 → 확인”까지 한 번에 이어졌어요.
- 디자이너/PM/엔지니어 상관없이, “아이디어를 10초 만에 화면으로” 볼 수 있었어요.

어드민에서 부딪힌 벽
하지만 실제로 쓰다 보니 한계가 드러났어요.
“중고거래팀이 쓸 때랑 부동산팀이 쓸 때, 같은 결과가 나와요.”
어드민은 모든 사용자에게 똑같은 에이전트를 제공했어요. 중고거래 도메인의 정책이나 부동산 도메인의 특수한 화면 패턴을 주입할 방법이 없었어요. 웹 기반이라 사용자의 로컬 환경(프로젝트 폴더, 기존 코드)에 접근할 수 없었거든요.
팀마다 “우리 화면은 이래야 해”가 달랐는데, 어드민은 그 차이를 반영할 수 없었어요. 결국 범용 도구가 갖는 태생적 한계였어요.
한편, 이 시기에 Claude Code 같은 AI 코딩 도구가 직군을 넘나들며 확산되고 있었어요. 개발자뿐 아니라 PM, 디자이너도 로컬에서 AI 도구를 돌리는 게 낯설지 않은 분위기가 된 거예요. “웹에서 접근성을 확보한다”는 어드민의 전제가 흔들리기 시작했어요.
그래서 사용자의 로컬 환경 기반으로 동작하는 에디터 를 만들기로 했어요.
CLI : 로컬 세션 기반의 확장 가능한 작업
어드민의 핵심 한계는 “사용자의 맥락에 접근할 수 없다”는 거였어요. 그래서 CLI로 옮겼어요. kraft 명령어 한 줄이면 로컬에서 에디터가 뜨고, 에이전트도 함께 구동돼요.

CLI로 옮기면서 가장 크게 바뀐 건 컨텍스트 주입이었어요.
- 에이전트가 로컬 프로젝트 폴더를 읽을 수 있게 됐어요. 기존 화면 코드, 도메인별 정책 문서, 팀 컨벤션 파일을 에이전트가 직접 참조할 수 있어요.
- 프로젝트/세션 단위로 작업이 분리되니, “중고거래팀의 화면”과 “부동산팀의 화면”이 자연스럽게 달라질 수 있었어요.
- 시작점도 다양해졌어요 — 빈 화면, 템플릿, 피그마 URL, 기존 코드 ZIP 등 여러 진입점을 열어뒀어요.
이 CLI 패키지는 에디터 프론트엔드와 에이전트 백엔드를 한 번에 번들링해서, npx 한 줄로 전체 환경이 구동되는 구조예요. 빌드 시점에 에디터 정적 파일, 에이전트 서버 코드, 디자인 스킬 파일, 프롬프트 템플릿까지 모두 하나로 묶어요. 이렇게 하면 "설치 → 실행"까지의 마찰이 거의 없으면서도, 로컬 프로젝트의 컨텍스트를 에이전트가 바로 읽을 수 있는 구조가 돼요.
CLI에서 부딪힌 벽
CLI로 옮기면서 컨텍스트 문제는 풀렸어요. 하지만 새로운 문제가 보이기 시작했어요.
“프롬프트를 잘 써야 좋은 결과가 나와요.” CLI든 어드민이든, 결국 “프롬프트 한 줄 → 코드 생성”이라는 구조는 같았어요. 사용자가 “거래 후기 작성 화면 만들어줘”라고만 쓰면, 에이전트는 많은 걸 스스로 결정해야 해요. 별점을 어떤 UI로 보여줄지, 에러 상태는 어떻게 처리할지, CTA 버튼은 언제 활성화할지 — 이런 질문들에 대한 답 없이 “일단 그럴듯하게” 만들어버리는 거예요.
생성 결과의 품질이 들쑥날쑥했어요. 같은 프롬프트를 두 번 넣으면 다른 화면이 나왔어요. 첫 번째는 SEED 토큰을 잘 쓰다가, 두 번째는 hex 값을 하드코딩하고. 첫 번째는 에러 상태를 처리하다가, 두 번째는 해피 패스만 구현하고. 사용자 입장에서 “이 도구를 믿고 쓸 수 있나?”라는 의문이 생기는 거예요.
이전 세션에서 배운 게 다음 세션에 반영되지 않았어요. 사용자가 “중고거래에서는 CTA를 항상 brandSolid로 해줘”라고 교정하면 그 세션에서는 반영돼요. 하지만 새 세션을 열면? 백지 상태에서 다시 시작이에요. 같은 교정을 매번 반복하는 건 도구가 아니라 사람이 해야 할 일이었어요.
이 세 가지 문제의 공통점은, “생성” 앞뒤로 아무것도 없다는 거였어요. 생성 전에 요구사항을 구체화하는 과정도 없고, 생성 후에 품질을 검증하는 과정도 없고, 세션을 넘어 학습하는 과정도 없었어요. “프롬프트 → 코드”라는 한 번의 점프만 있었어요.
그래서 사용자가 만든 화면 데이터를 학습할 수 있는 에이전트를 만들어서 붙이기로 헸어요.
에이전트: 결정과 검증을 자동화하는 루프
CLI에서 배운 교훈은 명확했어요. “한 번에 잘 만들어줘”는 안 된다. 구체화하고, 만들고, 검증하고, 기억하는 루프가 필요하다.
Kraft 에이전트는 이 루프를 구조화한 거예요.
요구사항 구체화(Clarify) → 이전 결정 기억(Memory) → 레퍼런스 케이스 참고(Cases) → 생성(Generate) → 검증(Verify) → 메모리 축적(Memory Write) 를 통해, “디자인 시스템에 충실하면서도 서비스 맥락에 맞는 화면”을 만들도록 설계한 워크플로우예요.
왜 에이전트가 필요했을까요? 제가 생각한 답은 아래와 같아요.
- 프롬프트가 모호하면 결과도 모호하다 → Clarify 단계에서 에이전트가 먼저 역질문해요. “이 화면에서 에러 상태는 어떻게 보여줄까요?”, “별점 입력은 탭 방식인가요, 슬라이드 방식인가요?” 사용자가 프롬프트를 잘 쓰는 대신, 에이전트가 부족한 결정을 채워주는 거예요.
- 생성 품질이 들쑥날쑥하다 → Verify 단계에서 SEED 가이드라인 준수 여부, 토큰 사용 정확도, 필수 상태 처리 여부를 자동으로 채점해요. 사람이 리뷰하기 전에 기계가 먼저 거르는 거예요.
- 이전 세션의 교정이 날아간다 → Memory 단계에서 이전 결정과 교정 내역을 자동으로 참고해요. “지난번에 이 도메인에서는 이렇게 결정했다”가 다음 세션에 반영돼요.
에이전트의 큰 흐름
- ① Clarify: 요구사항이 모호하면 먼저 역질문해서 구체화해요(어떤 상태를 보여줄지, 어떤 행동을 담을지 등 확정해요).
- ② Memory Read: 과거 유사 작업의 결정과 근거를 기억에서 참고해요.
- ③ Cases: 유사 레퍼런스를 찾아 패턴을 파악해요.
- ④ Generate: 구체화된 요구사항 + 메모리 + 케이스로 화면을 생성해요.
- ⑤ Verify: 가이드라인 준수/화면 품질 등을 검사해 객관성을 확보해요.
- ⑥ Memory Write: 이번 결정을 메모리에 축적해 다음 생성 품질을 높여요.
에이전트 아키텍처: 안에서 실제로 어떻게 돌아가는지
글의 앞부분에서 에이전트 루프를 개념적으로 설명했다면, 그 루프가 실제 코드로 어떻게 구현되었는지를 조금 더 깊이 들여다볼게요.
하네스 구조: 두 개의 모드와 위임된 코딩 에이전트
처음에는 “설계 에이전트, 코딩 에이전트, 지휘 에이전트를 따로 두고 자유롭게 협업시키자”는 멀티 에이전트 구조를 떠올렸어요. 하지만 실제로 만들어보니, 에이전트 사이의 통신 오버헤드가 크고 맥락이 전달되면서 손실되는 문제가 있었어요. “설계 에이전트가 결정한 의도”를 “코딩 에이전트”에게 넘길 때, 미묘한 뉘앙스가 빠지는 거죠.
그래서 선택한 게 하네스(Harness) 패턴 + 외부 위임이에요. 설계와 의사결정은 Mastra 툴을 활용한 하네스 안에 두 개의 모드(Plan / Orchestra) 로 묶어두고, 실제 코드 작성처럼 이미 잘 만들어진 도구가 있는 작업은 Claude Code(Claude Agent SDK) 에 위임하는 하이브리드 구조예요.
사용자 프롬프트
│
├─── 사용자가 검토 모드 선택 ───┐
│ ▼
│ ┌──────────────────┐
│ │ 검토 모드 │
│ │ (Plan Agent) │
│ │ 설계+스펙 저장 │
│ │ → ask_user 승인 │
│ │ (코드 X) │
│ └────────┬─────────┘
│ │ 승인
│ ▼
└────── 기본값 ──────►┌──────────────────┐
│ 실행 모드 │
│ (Orchestra) │
│ 설계 → 검증 → │
│ 코드 → 갱신 │
│ (end-to-end) │
└────────┬─────────┘
│ runCodingAgent
▼
┌──────────────────────────┐
│ Claude Code │
│ (Claude Agent SDK) │
│ - Edit / Write / Read │
│ - Bash / Glob / Grep │
│ - mcp(seed-docs) │
│ 로컬 `claude` 바이너리 │
│ 를 spawn 해서 실행 │
└──────────────────────────┘
공유: Memory / Skills / Workspace / Tools
검토 모드 (Plan Agent)
- 사용자 요청을 분석해 의도를 구체화하고, DesignSpec을 만들어 저장한 뒤, ask_user 도구로 승인을 요청하고 멈춰요.
- runCodingAgent에 접근 자체가 차단되어 있어요(이 모드의 도구 목록에서 의도적으로 제외). "코드를 만들 수 없는 모드"인 거예요.
- 사용자가 승인하면 같은 세션에서 모드가 실행 모드로 넘어가서 코드 생성을 이어가요.
- 언제 쓰나: 화면 구조나 컴포넌트 선택을 사용자와 먼저 맞춰두고 싶을 때, 비싼 작업을 시작하기 전에 한 번 끊고 가고 싶을 때.
실행 모드 (Orchestra Agent, 기본값)
- 사용자 요청을 받아 의도 구체화 → DesignSpec 저장 → 검증 → 코드 생성 → 스펙 갱신까지 혼자서 한 번에 처리해요.
- 검토 모드가 가진 모든 설계 도구에 더해 runCodingAgent까지 갖고 있어요. 즉 "원샷 자동" 트랙이에요.
- 검토 모드의 승인을 받고 넘어왔을 때는 앞단(Clarify, Cases)을 건너뛰고 검증 단계부터 이어가요.
- 언제 쓰나: 빠르게 화면을 뽑아보거나, 단순 수정 요청처럼 별도 합의가 필요 없을 때
Coding Agent: Claude Code 위임 도구: 우리가 따로 만든 Mastra 에이전트가 아니에요. @anthropic-ai/claude-agent-sdk 의 query()를 호출해서, 로컬에 설치된 claude 바이너리를 spawn하고 코드 작성을 맡기는 도구예요.
Edit/Write/Read/Bash/Glob/Grep 과 SEED 문서 MCP만 화이트리스트로 열어두고, 결과(파일 변경, 도구 호출 이벤트, 세션 ID)를 받아 Mastra 쪽으로 흘려보내요. 즉 “Claude Code를 도구처럼 임베드하는 어댑터” 예요.
이 구조가 좋았던 건, 설계의 맥락은 우리가 직접 통제하면서도, 코드 작성처럼 이미 강력한 도구가 있는 영역은 그걸 그대로 활용할 수 있다는 점이에요.
Plan Mode는 사용자에게 “무엇을 만들지” 합의하는 데만 집중하고, Orchestra Mode는 합의된 결정을 흔들림 없이 실행하는 데만 집중하고, 코드 작성은 Claude Code가 가진 파일 편집·검색·실행 도구 생태계를 그대로 빌려 써요.
도구 묶음: 설계 도구와 코딩 도구
도구는 크게 두 묶음이에요.
설계 도구 — 코드를 쓰지 않아요. 대신 “무엇을 만들지”를 결정해요.
- clarifyScreenIntent: 모호한 요구사항을 역질문으로 구체화해요
- fetchSeedGuideline: SEED 컴포넌트 API 문서를 실시간 조회해요
- lookupScreenCases: 유사한 화면 레퍼런스를 찾아 패턴을 참고해요
- saveDesignSpec / readDesignSpec: 설계 의도를 DesignSpec JSON으로 저장/조회해요
- validateDesignSpec: DesignSpec이 SEED 규칙에 맞는지 자동 검증해요
- reverseDesignFromCode: 기존 코드에서 DesignSpec을 역생성해요
코딩 도구 — 설계 도구가 만든 DesignSpec을 받아서 “어떻게 만들지”를 실행해요.
- runCodingAgent: Claude Code(Claude Agent SDK)에게 구현을 위임해요. 로컬 claude 바이너리를 spawn해서 파일 읽기/쓰기/수정, SEED 문서 MCP 조회, 빌드 실행을 모두 그쪽에서 처리해요.
이 구조가 좋았던 건, 디자인 지식을 “도구”로 분리하면서도 맥락은 하네스 하나로 유지할 수 있었다는 거예요. 시스템 프롬프트에는 SEED의 디자인 원칙 7가지, 화면 패턴, spacing/radius/typography 규칙 같은 디자인 지식이 촘촘하게 들어가 있고, 각 도구는 그 지식을 실행하는 손과 발이 되는 거예요.
요청 라우팅: 의도별 분기
Orchestra Mode는 사용자 메시지를 4가지 의도 중 하나로 분류해요.
- 파일 읽기/확인/탐색 (“이미지 읽어줘”, “폴더에 뭐 있는지 봐봐”) → 디자인 도구를 거치지 않고 바로 coding-agent에 위임
- 화면 설계/수정/구현 요청 → 디자인 Phase를 따라 DesignSpec 검증 후 codeing-agent 호출
- 대화/질문 (SEED 디자인 시스템 관련) → Kraft로서 직접 응답
- 모호한 요청 → 거절하지 말고, 반드시 ask_user 도구로 의도를 되묻기
핵심은 4번이에요. 모호한 요청이 들어오면 추측해서 만들지도, 거절하지도 않고, 사용자에게 선택지를 제시해 의도를 명확히 한 뒤에 진행해요.
화면 설계 Phase 파이프라인
기본값인 실행 모드는 화면 설계 요청 하나로 앞단부터 뒷단까지 전체 루프를 혼자 돌려요. 검토 모드는 이 중 앞단(설계+승인)만 따로 떼어내 사용자 승인을 받고 멈추는 별개 트랙이고요.
실행 모드 (기본 — end-to-end)
- Clarify: clarifyScreenIntent로 의도 구체화
- Memory Read: readDesignSpec / 누적 메모리 참조
- Cases: lookupScreenCases로 유사 레퍼런스 조회
- Initial Spec: saveDesignSpec으로 DesignSpec JSON 저장
- Validate: validateDesignSpec으로 SEED 규칙 준수 자동 검증. 오류가 있으면 최대 2회까지 자가 수정 후 재검증.
- Code Generation: runCodingAgent를 호출해 실제 React 코드를 생성/수정 (Claude Code가 처리).
- DesignSpec 갱신: 코드 변경이 끝나면 다시 saveDesignSpec을 호출해 최신 상태를 동기화. 이번 변경 내역은 designDecisions에 기록돼서 다음 세션의 컨텍스트가 돼요.
DesignSpec: “설계 의도”를 코드와 분리하는 중간 표현
대부분의 AI UI 생성 도구는 프롬프트 → 코드를 직접 연결해요. Kraft는 다르게 접근했어요. 프롬프트와 코드 사이에 DesignSpec JSON이라는 중간 표현을 두었어요.
{
"title": "거래 후기 작성",
"screenType": "form",
"serviceDomain": "중고거래",
"structure": {
"description": "상단에 거래 상대 정보, 중앙에 별점 입력, 하단에 텍스트 후기 영역",
"tree": [
{ "name": "AppScreen", "children": [
{ "name": "AppBar", "note": "뒤로가기 + 제목" },
{ "name": "AppScreenContent", "children": [
{ "name": "TradePartnerInfo", "note": "프로필 + 거래 물품" },
{ "name": "RatingInput", "note": "1~5 별점" },
{ "name": "ReviewTextArea", "note": "후기 텍스트 입력" }
]},
{ "name": "BottomCTA", "note": "후기 등록 버튼" }
]}
]
},
"components": [
{
"component": "ActionButton",
"importFrom": "@seed-design/react",
"usage": "하단 CTA",
"props": { "variant": "brandSolid", "size": "large" }
}
],
"designTokens": {
"colors": ["bg.layerDefault", "fg.neutral"],
"typography": ["t7Bold", "t5Regular"],
"spacing": ["x4", "x6"]
},
"designDecisions": [
{
"topic": "별점 UI",
"decision": "5개 별 아이콘을 탭하는 방식",
"rationale": "슬라이더보다 직관적이고, 모바일에서 오탭 가능성이 낮음"
}
]
}이 중간 표현이 주는 이점이 몇 가지 있어요.
- 설계 의도의 추적성: “왜 이 컴포넌트를 선택했는지”가 designDecisions에 기록돼요. 코드만 보면 알 수 없는 맥락이 남아요.
- 수정의 정밀함: 화면을 수정할 때 코드를 직접 고치는 게 아니라, DesignSpec의 해당 부분을 먼저 수정하고 코드를 재생성해요. “별점을 슬라이더로 바꿔줘”라고 하면 designDecisions의 근거까지 함께 업데이트돼요.
- 시맨틱 토큰 강제: designTokens에는 #FF6F0F 같은 하드코딩 값이 아니라 bg.layerDefault 같은 SEED 시맨틱 토큰 이름만 들어가요. 이것만으로도 "당근스러운 색상"이 자동으로 보장돼요.
- 역공학 가능: 기존 코드가 있으면 reverseDesignFromCode 도구로 코드 → DesignSpec을 역생성할 수 있어요. 기존 화면을 에이전트의 수정 루프에 태울 수 있는 거예요.
스킬 시스템: 디자인 시스템 지식을 모듈로 관리하기
“당근스러운 화면”을 만들려면 에이전트가 SEED 디자인 시스템의 규칙을 알아야 해요. 그런데 이 규칙을 시스템 프롬프트에 전부 때려넣으면 토큰이 낭비되고, 맥락에 안 맞는 규칙이 노이즈가 돼요.
그래서 Kraft는 디자인 지식을 스킬(Skill) 이라는 마크다운 모듈로 분리했어요. 에이전트가 필요한 시점에 필요한 스킬만 로드하는 방식이에요.
현재 구현된 스킬은 이래요.
| 스킬 | 역할 | 예시 |
| --- | --- | --- |
| `spacing-constraint` | 여백 규칙 (x0.5~x16 토큰) | "카드 내부 패딩은 최소 x4, 리스트 아이템 간격은 x3" |
| `radius-constraint` | 모서리 규칙 (r0.5~rFull) | "버튼은 rFull, 카드는 r3, 입력 필드는 r2" |
| `typography-constraint` | 타이포 규칙 (t1~t10) | "한 화면 내 타이포 단계는 4단계 이내" |
| `screen-patterns` | 화면 레이아웃 규칙 | "폼 화면의 에러 표시 8가지 패턴" |
| `small-writing-guide` | UI 카피 규칙 | "CTA 버튼은 동사로 시작, 12자 이내" |
| `design-principles` | SEED 디자인 원칙 7가지 | "연결된 경험, 사용자를 위한 개선, 직관적인 경험..." |
| `eval-self-check` | 코드 작성 후 자체 점검 규칙 | "색상 토큰/컴포넌트/간격/타이포/아이콘/레이아웃/애니메이션 7대 영역 셀프 체크" |
예를 들어, 에이전트가 “리뷰 작성 폼 화면”을 만들 때는 screen-patterns(폼 레이아웃 규칙)과 spacing-constraint(입력 필드 간격)가 로드되지만, small-writing-guide(카피 규칙)는 아직 필요 없어요. 카피를 결정하는 단계에서 비로소 로드돼요.
이 방식의 장점은 디자인 시스템의 규칙이 업데이트되면 스킬 파일만 수정하면 된다는 거예요. 시스템 프롬프트 전체를 건드릴 필요가 없어요.
평가(Eval): 생성 결과를 자동으로 채점하기
에이전트가 코드를 생성한 뒤, “이게 진짜 SEED 가이드를 잘 따르는지”를 어떻게 확인할 수 있을까요? 사람이 매번 리뷰하는 건 스케일이 안 돼요.
Kraft는 11개의 자동 평가 기준(scorer)을 만들어서 생성 코드의 품질을 점수로 매기는 구조를 갖고 있어요. 코드 정적 분석 기반 7개와 LLM 기반 4개로 나뉘어요.
코드 기반 채점기 (7개) — 결정론적으로 빠르게 검증할 수 있는 항목
- color-tokens: 하드코딩된 hex 값 대신 시맨틱 토큰을 사용했는지
- typography: 화면 내 텍스트 크기의 단계가 논리적인지
- layout-structure: VStack/HStack/Flex 사용이 SEED 패턴에 맞는지
- spacing-rules: spacing 토큰이 컨텍스트에 맞게 쓰였는지
- component-compliance: SEED 컴포넌트의 props를 올바르게 사용했는지
- icon-usage: SEED 아이콘 라이브러리 사용 규칙 준수 여부
- animation-stability: 애니메이션 사용이 디자인 시스템 규칙에 맞는지
LLM 기반 채점기 (4개) — 정성적 판단이 필요한 항목
- ux-patterns: UX 패턴이 화면 유형에 적절한지
- interaction-quality: 인터랙션 흐름이 자연스러운지
- flow-patterns: 화면 간 플로우가 사용자의 의도와 맞는지
- form-patterns: 폼 화면의 상태 처리(에러, 로딩, 빈 상태 등)가 충실한지
이 평가 시스템은 Verify 단계에서 동작해요. 낮은 점수가 나오면 에이전트가 스스로 “어디가 문제인지” 피드백을 받아 수정할 수 있는 루프가 만들어져요.

크로스세션 디자인 메모리: 학습하는 에이전트
에이전트가 한 세션에서 내린 좋은 결정이 다음 세션에서도 유지되면 좋겠다는 요구가 자연스럽게 생겼어요. 예를 들어, “중고거래 도메인에서는 CTA 버튼을 항상 brandSolid로 쓴다”는 결정을 매번 다시 내리는 건 낭비예요.
Kraft는 이를 크로스세션 디자인 메모리로 해결했어요.
- Decision Log 누적: 매 생성마다 designDecisions가 .design-memory/decision-log.jsonl에 세션 단위로 쌓여요.
- 원칙 자동 추출: 누적된 결정 로그에서 같은 패턴이 임계치 이상 반복되면, 자동으로 “도메인별 디자인 원칙”으로 승격시켜 .design-memory/principles.json에 저장해요.
- 다음 세션에 주입: 새 세션이 시작되면 readDesignPrinciples 도구로 이전에 축적된 원칙을 Memory Read 단계에서 자동으로 참고해요.
서버가 재시작되더라도 LibSQL 기반 메모리 스토어(orchestra-memory.db)에 이전 대화 컨텍스트가 보존되어 있어서, 작업의 연속성이 유지돼요.

세 형태의 공통 목표
Kraft의 세 형태는 서로 다른 제품이 아니라, ”결국에는 당근만의 당근스러운 화면을 만드는 것”이라는 같은 목적을 향한 서로 다른 레이어예요.
- 어드민: 웹 기반, 빠른 진입
- CLI: 로컬 기반 토대
- 에이전트: CLI 위에서 동작하는 자동화 루프
어드민이 “누구나 빠르게 생성/배포/확인”하는 진입점을 열었다면, CLI는 로컬 기반의 확장 가능한 토대가 됐고, 에이전트는 그 CLI 위에서 결정과 검증을 자동화하는 레이어예요. 디자인 시스템의 지식이 실제 생산성으로 이어지는 구조를 최종적으로 만들고자 했어요.

배운 것들
Kraft를 만들면서 몇 가지 교훈이 있었어요.
“프롬프트 → 코드” 직접 연결의 함정
처음에는 “프롬프트를 잘 쓰면 좋은 코드가 나올 거다”라고 생각했어요. 하지만 실제로는 그렇지 않았어요. 디자인 시스템에는 프롬프트에 담기 어려운 암묵적 규칙이 너무 많았어요. “카드 안의 여백은 x4 이상이어야 한다”, “한 화면에서 타이포 단계는 4개를 넘기지 않는다” 같은 규칙은 사용자가 프롬프트에 명시하지 않아요. 이걸 에이전트가 스스로 알고 있어야 해요. DesignSpec 중간 표현과 스킬 시스템은 이 문제를 해결하기 위한 구조적 답이었어요.
검증 없는 생성은 의미가 없다
AI가 “그럴듯한” 화면을 만드는 건 어렵지 않아요. 문제는 “디자인 시스템을 준수하는” 화면을 만드는 거예요. 두 번째로 생성한 화면이 첫 번째와 전혀 다른 스타일이면, 도구로서의 신뢰가 깨져요. 11개 scorer 기반의 Eval 시스템은 “매번 일관된 품질”을 보장하기 위한 장치예요. 사람이 리뷰하기 전에, 기계가 먼저 걸러주는 거예요.
다음에 풀어야 할 과제들


Kraft가 사내 공지로 한번 알려지고, 구성원분들에게 소개가 되면서 다음 단계가 조금씩 보이기 시작했어요. 단순히 기능을 더 붙이는 것보다, 도구가 실무 워크플로우 안에 자연스럽게 자리 잡도록 만드는 게 진짜 과제라는 생각이 들어요.
사용자 요청 기반의 기능 확장
공지 이후 받은 문의들을 보면, 사람마다 Kraft에서 풀고 싶은 문제가 조금씩 달라요. 누군가는 빠른 프로토타입이 필요하고, 누군가는 디자인 시스템 학습용으로 쓰고 싶어해요. 이 요청들을 단순히 “기능 추가”로 받아들이지 않고, 어떤 워크플로우의 일부인지 먼저 이해하려고 해요. 비슷한 요청이 여러 번 들어오면 그건 도구가 비워둔 자리예요.
멀티 캔버스 뷰 지원
지금은 한 화면을 만드는 데 집중하고 있지만, 실무자분들은 보통 “이 화면들의 흐름”을 보면서 작업해요. 거래 완료 → 후기 작성 → 작성 완료 같은 플로우가 한 화면에 모여 있어야 일관성을 잡고 빠진 단계를 발견할 수 있어요. 캔버스 뷰에서 여러 화면을 한눈에 보고, 화면 간의 상태 전달과 톤을 에이전트가 함께 다루는 구조를 만들려고 해요.
실무 워크플로우와의 통합
Kraft가 별도 도구로 떠다니지 않고, 디자이너·개발자가 이미 쓰는 흐름 안에 녹아 들어가야 해요. Figma에서 시작해 Kraft로 넘어오는 경로, Kraft에서 만든 결과를 다시 팀 라이브러리로 되돌리는 경로, PR 리뷰 단계에서 SEED 준수 여부를 자동으로 짚어주는 경로 — 이런 접점들을 어떻게 매끄럽게 만들지가 다음 큰 숙제예요. 도구는 워크플로우를 바꾸려 하기보다, 워크플로우에 스며들어야 한다고 생각해요.
디자인 결정 DB와 학습형 에이전트
지금 메모리는 세션 단위로 누적되는 수준이에요. 한 단계 더 나아가서, 사용자들의 디자인 결정들이 DB로 쌓이고 — 어떤 도메인에서 어떤 패턴을 선택했는지, 왜 그 결정을 내렸는지 — 그 데이터를 바탕으로 에이전트가 동적으로 학습하게 만들고 싶어요. 사용자가 한 번 교정한 결정이 다음 사람에게도 자동으로 적용되고, 시간이 지날수록 “당근다운 판단”의 해상도가 올라가는 구조예요. 이게 되면 Kraft는 단순한 생성 도구가 아니라, 팀의 디자인 의사결정이 누적되는 살아있는 시스템이 돼요.
프롬프트 한 줄로 화면이 나오는 시대, ‘당근스러운 화면’을 만드는 법 was originally published in 당근 테크 블로그 on Medium, where people are continuing the conversation by highlighting and responding to this story.