전체 라이브러리를 덤프하지 않고 디자인 시스템 준수를 위한 프롬프팅
요약
AI 에이전트에게 디자인 시스템 준수를 요청할 때 전체 라이브러리를 제공하는 '카탈로그 덤프' 방식은 오히려 혼란을 야기합니다. 대신, 핵심 기본 요소와 유효 속성만 담은 '작고 명확한 계약(small, sharp contract)' 형태의 간결한 컨텍스트 패키지를 사용하는 것이 효과적입니다. 이를 통해 에이전트가 재발명하는 것을 막고 일관된 UI 생성을 유도할 수 있습니다.
핵심 포인트
- 카탈로그 전체를 붙여넣는 것은 제약 조건보다 영감 보드처럼 읽힙니다.
- '작고 명확한 계약' 형태로 핵심 기본 요소와 속성만 제공해야 합니다.
- 준수(compliance)는 임포트/속성 허용 목록, 토큰 규칙 등으로 정의되어야 합니다.
- 프롬프트의 목표는 재발명(reinvent-the-wheel)을 막고 일관성을 확보하는 것입니다.
저는 예전에 에이전트 프롬프트에 디자인 시스템의 절반을 붙여넣곤 했습니다. '우리 버튼(Button)이 어떤 건지 알게 하려고' 말이죠. 그 결과는 더 길고, 느렸으며, 어쩐지 여전히 하드코딩된 헥스 코드(hex)를 가진 새로운 PrimaryButton을 만들어내는 것이었습니다.
더 많은 컨텍스트가 곧 더 나은 준수(compliance)를 의미하는 것은 아닙니다. 에이전트들은 컴포넌트 카탈로그에 압도당합니다. 그들이 필요로 하는 것은 **작고 명확한 계약(small, sharp contract)**입니다. 즉, 어떤 기본 요소(primitives)가 존재하는지, 어떤 속성(props)이 유효한지, 그리고 차이점(diff)이 적용되었을 때 '완료'의 모습이 무엇인지에 대한 정보입니다.
다음은 재발명(reinvent-the-wheel)하는 PR을 막아낸 프롬프팅 패턴입니다.
실패 모드: 카탈로그 덤프 (The failure mode: catalog dump)
이런 형태의 프롬프트는 조용히 실패합니다:
여기 우리 전체
components/ui트리가 있습니다(40개 파일 붙여넣기). 디자인 시스템에 맞는 설정 양식(settings form)을 만들어 주세요.
제가 받은 결과물은 다음과 같았습니다:
Card를 복제한 새로운SettingsCard- 토큰 임포트 옆의 인라인 스타일(Inline styles)
- 우리 시스템의
Switch대신 커스텀 토글(toggle) - 간격 스케일(spacing scale)에 없는 '충분히 가까운' 간격
모델은 라이브러리를 봤습니다. 하지만 그것을 유일하게 허용되는 표면(surface)으로 취급하지 않았습니다. 카탈로그 덤프는 제약 조건(constraints)이라기보다는 영감 보드처럼 읽힙니다.
프롬프트에서 '준수'가 의미하는 것
저는 준수를 에이전트가 실패할 수 있는 네 가지 검사 항목으로 정의합니다:
- 임포트 허용 목록 (Import allowlist) —
@/components/ui/*(또는 사용 중인 패키지)에서만 가져오고, 병렬적인 기본 요소(parallel primitives)는 금지. - 속성 허용 목록 (Prop allowlist) — 문서화된 변형(
size,tone,intent)을 사용하고,big/fancy같은 것을 임의로 만들지 않기. - 토큰 규칙 (Token rule) — 색상/간격/반경은 토큰에서 가져와야 하며, JSX 내에 원시 헥스(raw hex)/rgb/px 매직 넘버를 사용하지 않기.
- 구성 규칙 (Composition rule) — 기존 기본 요소들로 화면을 조립해야 하며, 새로운 컴포넌트는 명시적인 '새로운 기본 요소 승인' 플래그가 필요함.
프롬프트에 이 네 가지 항목이 언급되지 않으면, 에이전트는 '우리 시스템을 사용한다'기보다는 '설정 양식처럼 보이게 한다'는 것에 최적화할 것입니다.
제가 실제로 붙여넣는 간결한 컨텍스트 팩 (The slim context pack I actually paste)
전체 라이브러리 대신, 저는 **디자인 시스템 치트 시트(design-system cheat sheet)**를 약 80~120줄 분량으로 유지하며, 공개 API가 변경될 때마다 이를 업데이트합니다:
사용 가능한(Legal) UI 컴포넌트 가져오기
- @/components/ui/Button — variants: primary | secondary | ghost | danger; sizes: sm | md | lg
- @/components/ui/Input — 항상 Label과 쌍으로 사용해야 하며, 도움말 텍스트 해킹(helper text hacks)이 아닌
errorprop을 통해 오류를 표시합니다.
...
이것이 에이전트가 대부분의 기능 작업에 대해 얻는 전체 “라이브러리”입니다. Storybook 링크와 전체 속성 테이블은 리포지토리에 존재하며, 프롬프트가 **결정 영역(decision surface)**을 전달합니다.
효과적인 프롬프트 구조
제가 기본적으로 요청하는 내용은 다음과 같습니다:
아래의 Legal UI imports만을 사용하여 X를 구축하세요.
새로운 기본 요소(primitives)는 만들지 마세요.
누락된 부분이 있다면 멈추고 그 격차를 명시하세요 — 컴포넌트를 지어내지 마세요.
토큰 및 구성 기본값에 맞추세요.
완료되면, 통과/실패 여부를 포함한 승인 체크리스트(Acceptance checklist)를 붙여넣으세요.
그다음 치트 시트를 첨부합니다. 짧고, 지루하며, 명시적인 중단 규칙이 담겨 있습니다.
“멈추고 격차를 명시하라”는 문장이 중요합니다. 이것이 없으면 에이전트는 유사품으로 구멍을 채웁니다. 이것이 있으면 “허용 목록에 DatePicker가 없습니다 — 네이티브 input type=date를 사용하거나 기본 티켓을 열까요?”라는 한 줄짜리 질문을 받게 됩니다. 이는 200줄짜리 사용자 지정 달력보다 더 나은 결과입니다.
법적(Legal)한 것뿐만 아니라 불법적인 차이점의 예시를 제공하세요
긍정적인 예시는 도움이 됩니다. 부정적인 예시는 경계(fence)를 가르칩니다:
- // 불법: 새로운 병렬 기본 요소(primitive)
- export function FancyButton(...) { ... }
...
저는 치트 시트에 3~5개의 불법 스니펫을 유지합니다. 에이전트는 구체적일 때 “이렇게 하지 마세요”라는 패턴 매칭을 매우 열심히 합니다.
프롬프트에서 영향 범위(blast radius)를 제한하세요
작업의 규모가 너무 크면 디자인 시스템 준수는 무너집니다:
“청구 설정 페이지를 재구축하고 UI를 현대화하세요.”
지어낼 수 있는 여지가 너무 많습니다. 저는 다음과 같이 분할합니다:
- 와이어 데이터 + 기존 레이아웃 셸(layout shells)
- 한 번에 하나의 컨트롤 클러스터 교체 (계획 → 결제 방법 → 인보이스)
- 그 후에만 빈 상태/오류 상태를 요청합니다.
각 단계마다 동일한 치트 시트를 재사용합니다. 준수는 국지적으로 유지됩니다. 검토는 여전히 검토 가능하게 유지됩니다.
프롬프트에서 제외하는 것들
- 모든 컴포넌트에 대한 전체 Storybook MDX 파일
- Button의 내부 구현 (focus ring CSS, motion tokens)
- 모든 상태에 대한 Figma 스크린샷 (레이아웃이 중요하면 하나의 화면만 첨부할 것)
- 전체 토큰(tokens) JSON
이는 프롬프트 문제가 아니라 검색(retrieval) 문제입니다. 에이전트가 prop이 필요하다면 타입 파일(type file)을 열 수 있습니다. 저는 소스 코드를 붙여넣으라고 지시하는 것이 아니라, Button.tsx 또는 패키지 내보내기(package exports)를 가리킵니다.
빠른 사전 병합 검사 (pre-merge smell check) (사람 또는 봇)
PR을 신뢰하기 전에:
- diff에서 hex /
rgb(검색 (rg사용) - 티켓 태그가 없는
components/ui하위의 새 파일들 - 임의의
../shared/Button경로로부터 가져온 임포트(Imports) - 이미
Stack이 소유하고 있는 간격(spacing)을 재구현하는 클래스 이름들
만약 위 항목 중 어떤 것이 발견된다면, 프롬프트가 실패했거나 에이전트가 정지 규칙(stop rule)을 무시한 것입니다. 저는 diff뿐만 아니라 치트 시트 자체를 수정합니다.
핵심 요점 (Takeaway)
디자인 시스템 준수(Design-system compliance)는 컨텍스트 창(context-window) 문제가 아니라 **제약 조건 문제(constraint problem)**입니다. 라이브러리 전체를 덤프하는 것은 모델이 리믹스(remix)하도록 훈련시킵니다. 반면, 슬림한 허용 목록(allowlist), 토큰 규칙, 불법 예시, 그리고 '지어내지 말고 — 질문하라'는 강력한 정지 규칙을 제공하는 것이 모델이 구성(compose)하도록 훈련시킵니다.
저는 여전히 검토합니다. 치트 시트는 단지 '이것이 우리 시스템처럼 보이는가?'라는 과정을 직감적인 느낌(gut feel) 대신 체크리스트로 만들어 줄 뿐입니다. 이것이 에이전트 UI diff가 의도적으로 지루하게 유지되는 유일한 방법이기 때문입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기