Fixture-first prompting: 시드 데이터가 모델의 구축 결과물을 어떻게 바꾸는가
요약
LLM을 활용한 디자인-투-코드 워크플로우에서 시드 데이터(Fixture)가 UI 생성 결과에 미치는 결정적인 영향을 분석합니다. 프롬프트보다 타입 정의와 시드 데이터를 모델이 더 중요하게 취급하므로, 다양한 케이스를 포함한 픽스처 작성이 필수적임을 강조합니다.
핵심 포인트
- 모델은 프롬프트보다 타입 정의와 시드 데이터를 더 신뢰함
- 시드 데이터의 복잡성에 따라 UI의 레이아웃과 기능이 결정됨
- 데이터가 채워진 상태, 비어 있는 상태, 로딩, 에러 등 4가지 변형 권장
- 동일한 프롬프트라도 시드 데이터에 따라 결과물 품질이 달라짐
TL;DR
- 모델은 프롬프트를 훑어보고, 타입 정의(types)를 주의 깊게 읽으며, 시드 데이터(seed data)를 절대적인 진리로 취급합니다.
- 세 개의 짧은 해피 패스(happy-path) 행은 데모 UI를 생성하지만, 20개의 복잡한 행은 실제 UI를 생성합니다.
- Figma 프레임과 프롬프트를 작성하기 전에 픽스처(fixture)를 작성하세요.
- 엔티티(entity)당 네 가지 픽스처 변형을 배포하세요: 데이터가 채워진 상태(populated), 비어 있는 상태(empty), 로딩 중(loading), 에러(error).
- 동일한 프롬프트 + 다른 시드 = 다른 제품.
올해 제 디자인-투-코드(design-to-code) 워크플로우에서 가장 큰 변화는 새로운 도구가 아니었습니다. 그것은 시드 데이터 파일을 기능 티켓(feature ticket)의 끝에서 앞으로 옮긴 것이었습니다. 픽스처가 앞장서게 되면, 모델은 픽스처가 암시하는 UI를 구축하기 시작합니다. 그리고 픽스처는 Figma 프레임과 달리 엔지니어, PM, 디자이너 모두가 머지 충돌(merge pain) 없이 동일한 파일에서 편집할 수 있는 것입니다.
다음은 워크플로우와 이것이 작동하는 이유, 그리고 모델이 좋은 결과물과 나쁜 결과물을 생성하게 만드는 시드 데이터의 구체적인 형태에 대한 설명입니다.
모델이 실제로 읽는 디자인 브리프는 바로 당신의 시드 데이터입니다
LLM에게 대시보드를 구축해 달라고 요청할 때, 모델은 당신이 생각하는 것만큼 프롬프트를 긴밀하게 읽지 않습니다. 모델은 다음과 같이 읽습니다:
- 프롬프트 (훑어봄)
- 타입 정의 (carefully, 주의 깊게)
- 시드 / 모의 데이터 (seed / mock data) (절대적인 진리로 — 이것이 UI가 수용해야 하는 내용입니다)
만약 mockUsers.ts에 이름이 4글자이고 아바타가 없는 사용자 3명이 있다면, 모델은 짧은 이름과 이니셜을 보여주는 UI를 구축합니다. 만약 mockUsers.ts에 "Amélie", "李", "Björn-Alexander"와 같은 이름과 60자 길이의 기업용 이메일 주소가 섞인 40명의 사용자가 있다면, 모델은 데이터를 강제된 조건에 맞춰 텍스트를 생략(truncate)하거나 줄바꿈(wrap)하고 아바타를 위한 공간을 확보하는 UI를 구축합니다.
동일한 프롬프트. 다른 시드. 다른 제품.
Before / after: 동일한 프롬프트, 두 개의 시드 파일
프롬프트 (두 실행 모두 동일): "검색 바와 테이블이 있는 고객 목록 페이지를 구축해줘."
시드 A (대부분의 사람들이 픽스처로 배포하는 형태)
export const customers = [
{ id: 1, name: "Alice", email: "a@x.com", plan: "pro" },
{ id: 2, name: "Bob", email: "b@x.com", plan: "free" },
...
모델이 구축한 결과물: 4개의 컬럼이 있고 왼쪽 정렬된 테이블, 빈 상태 (empty state) 없음, 페이지네이션 (pagination) 없음, 플랜 배지 (plan badge) 스타일링 없음 — 그저 일반 텍스트뿐입니다.
Seed B (UI 스트레스 테스트를 위해 설계된 픽스처)
export const customers = [
{
id: "cus_9f3a2b",
...
Seed B를 바탕으로 모델이 구축한 결과물: 플랜 배지 (plan badges)가 포함된 테이블 (plan이 알려진 집합 중 하나였기 때문), lastActiveAt을 위한 상대적 시간 포맷터 (relative-time formatter) (날짜가 다양하고 일부가 오래되었기 때문), 이니셜을 사용한 아바타 폴백 (avatar fallbacks) (하나가 null이었기 때문), 툴팁이 포함된 이메일 생략 처리 (email truncation) (하나가 길었기 때문), 그리고 각 이름 아래의 태그 칩 (tag chip) 행.
프롬프트는 동일했습니다. 시드(seed)가 모든 디자인 작업을 수행했습니다.
시드 우선 워크플로 (seed-first workflow): 피그마(Figma) 이전에 픽스처를, 프롬프트 이전에 픽스처를
제가 현재 실행하는 순서는 다음과 같습니다:
- 픽스처를 먼저 작성합니다. 피그마(Figma)를 하기 전에, 프롬프트를 작성하기 전에, 티켓 설명을 쓰기 전에 — 도메인의 복잡한 현실을 온전히 나타내는 15~20개의 시드 데이터 (seed data) 행을 작성합니다. 긴 이름, 누락된 필드, 오래된 타임스탬프 (timestamps), 하나의 극단적인 이상치 (outlier) 등을 포함합니다.
- PM 및 디자이너에게 픽스처를 보여줍니다. 이는 목업 (mock)보다 빠릅니다. 모두가 JSON을 보며 "태그 (tags)"가 실제로 존재하는 기능인지, MRR이 정수 센트 단위여야 하는지 아니면 부동 소수점 (float)이어야 하는지, 혹은 오른쪽에서 왼쪽으로 읽는 이름 (right-to-left names)을 고려해야 하는지에 대해 논쟁할 수 있습니다. 조율(alignment)이 2일 대신 20분 만에 이루어집니다.
- 그다음 피그마 (Figma) 초안을 잡거나 프롬프트를 작성합니다. 이제 두 작업 모두 픽스처를 신뢰할 수 있는 단일 출처 (source of truth)로 참조합니다. 디자이너는 시드 내에서 가장 긴 문자열을 수용할 수 있도록 컴포넌트 크기를 조정합니다. 프롬프트에는 "
theme.ts의 디자인 토큰 (design tokens)을 사용하여fixtures/customers.ts에 암시된 UI를 구축해줘"라고 작성합니다. - 모델이 생성합니다. 픽스처가 포괄적이기 때문에, UI도 첫 번째 패스 (pass)에서 포괄적으로 생성됩니다. 반복 횟수 (iteration count)가 줄어듭니다.
우리 팀의 경우, 이 순서로 전환한 후 "초안에서 검토 가능한 UI"까지 걸리는 평균 시간이 약 3시간에서 약 50분으로 단축되었습니다. 모델이 빨라졌기 때문이 아니라, 입력값 (inputs)이 더 밀도 있게 변했기 때문입니다.
안티 패턴 (Anti-patterns): AI 출력물을 붕괴시키는 3가지 시드 형태
AI가 신뢰할 수 없는 나쁜 코드를 생성하게 만드는 시드들:
- 세 개의 행복한 행 (The three happy rows). 모든 필드가 채워져 있고, 모든 문자열은 짧으며, 모든 날짜는 최근입니다. 모델은 오직 데모용으로만 작동하는 UI를 구축합니다.
- 단일 행 시드 (The single-row seed). 모델이 가변성 (variability)을 추론할 수 없으므로, 빈 상태 (empty state), 페이지네이션 (pagination), 정렬 (sort) 등을 구축하지 않습니다. 나중에 이 모든 것을 직접 수정해야 할 것입니다.
- 로렘 입숨 시드 (The lorem-ipsum seed). 의미론적 힌트 (semantic hints)가 없는 자리 채우기 텍스트입니다. "lorem ipsum dolor sit amet"는 모델에게 이것이 제목인지, 자기소개인지, 아니면 댓글인지 알려주지 않습니다. 모호한 입력은 모호한 출력으로 이어집니다.
좋은 시드는 작성하기는 지루하지만 효과는 극적입니다. 기능당 30분을 할애하세요. 이는 전체 사이클에서 가장 높은 투자 대비 수익률 (ROI)을 보이는 30분입니다.
반복 가능한 폴더 구조
세 가지 제품에 걸쳐 우리가 정착한 구조는 다음과 같습니다:
src/
fixtures/
customers.ts # 15-20개 행, 무질서한 현실성 (messy realism)
...
모든 피스처 (fixture) 파일은 네 가지 변형을 가집니다: 데이터가 채워진 상태 (populated), 빈 상태 (empty), 로딩 중 (loading), 에러 (error). 그런 다음 프롬프트에 "src/fixtures/customers.*에 있는 피스처를 사용하여 고객(customers)에 대한 네 가지 상태를 구축하라"고 입력하면, 데이터가 항상 존재한다고 가정하는 단일 화면 대신 한 번의 생성 패스 (generation pass)로 네 가지 화면을 모두 얻을 수 있습니다.
Storybook은 시각적 회귀 테스트 (visual regression)를 위해 피스처를 자동으로 가져옵니다. Playwright는 E2E 테스트를 위해 이를 가져옵니다. 디자이너는 코드 샌드박스 (code sandbox)에서 JSON을 열어 값을 실시간으로 편집할 수 있습니다. 하나의 산출물 (artifact)이 네 명의 소비자에게 전달되며, 코드 리뷰가 가능한 저장소 (repo) 내에 존재하게 됩니다.
새로운 프로젝트를 설정하면서 이러한 스캐폴딩 (scaffolding)을 다시 만들고 싶지 않다면, '상태별 피스처 (fixture-per-state)' 패턴은 훌륭한 템플릿 스타터 (template starter) 내부에 기본 워크플로로 포함되어 있는 종류입니다. AppLighter의 사례를 보면 fixtures/, stories/, e2e/ 폴더들이 첫날부터 어떻게 서로 연결되어, 모델이 당신의 첫 번째 프롬프트부터 구축할 수 있는 좋은 뼈대 (bones)를 갖게 되는지 확인할 수 있습니다.
일반적인 원칙은 포스트잇 한 장에 적을 수 있을 정도로 간단합니다: 모델은 당신의 프롬프트로부터 제품을 설계하는 것이 아닙니다. 모델은 당신의 데이터로부터 제품을 설계합니다. 그러므로 데이터를 먼저 설계하십시오.
현재 당신의 피스처 (fixture) 파일은 어떤 모습인가요? 세 개의 행복한 행 (happy rows)인가요, 아니면 엉망진창인 버전인가요? 당신이 의도적으로 심어둔 가장 지저분한 엣지 케이스 (edge case)를 댓글로 남겨주세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기