AI + Design #1: 검증기가 내 문서가 거짓말한 것을 잡아내다
요약
작성자는 AI 기반 디자인 시스템에서 '드리프트 체커'라는 도구를 개발하여, 문서화된 규칙과 실제 코드 간의 불일치(drift)를 검증했습니다. 이 과정에서 자신의 문서 자체가 AI에게 잘못된 정보를 학습시키고 있음을 발견했습니다. 이는 정적 문서만으로는 부족하며, 서버 측 로직을 통해 코드를 깊이 있게 검증해야 함을 시사합니다.
핵심 포인트
- AI가 생성한 코드의 오류를 잡아내는 '드리프트 체커' 개발.
- 문서화된 규칙과 실제 구현 간의 불일치(drift) 문제 발견.
- 단순 문서 요청만으로는 부족하며, 서버 측 검증 로직이 필수적임.
- 코드 구조와 토큰 시스템을 깊이 있게 분석하는 도구 설계 필요.
새로 만든 드리프트 체커(drift checker)를 처음으로 전체 실행했을 때, 나 자신의 디자인 시스템에서 122개의 오류가 출력되었다.
그중 약 119개는 파서의 잘못이었다. 문서에서는 "Select.Trigger"라고 되어 있고 코드에서는 SelectTrigger인데 이것이 같은 것임을 알지 못하는 식의 노이즈였다. 나는 파서를 수정하고 다시 실행했다. 세 개의 오류가 살아남았다. 이 세 개 모두 진짜였고, 모두 llms.txt에 있었으며, 이는 내 정성껏 관리한 문서들을 읽는 모든 AI 도구들이 잘못된 것을 학습해왔다는 의미였다.
내 배지(Badge) 문서는 컴포넌트에 존재하지 않는 xl 크기의 radius 값을 나열했고, 존재하는 base를 누락했다. 차트(Chart) 예제의 import 라인에는 Chart 자체가 빠져 있었다. 이것을 복사해서 붙여넣으면 첫 렌더링 시 undefined-symbol 오류가 발생할 것이었다. 그리고 DropdownMenu.RadioGroup은 몇 달 전에 출시되었음에도 불구하고 문서화되지 않았다.
나는 이 도구를 AI가 내 규칙들을 깨뜨리는 것을 잡아내기 위해 만들었다. 그 첫 번째 발견은 바로 내 문서 자체가 AI에게 거짓말을 하고 있었다는 것이었다.
정적 파일만으로는 충분하지 않은 이유
Design to Code #5에서 나는 llms.txt에 대해 글을 썼다. 이것은 AI 도구들이 컴포넌트 API와 토큰 규칙을 알 수 있도록 내가 유지하는 여섯 가지 변형(variants)이다. 나는 그 포스트를 다음과 같은 관찰로 마무리했다. 긴 세션 동안, 처음에 명확하게 활성화되었던 규칙들이 조용히 적용되지 않게 된다는 것이다. 분명하게 거부되는 것이 아니라, 희미해진다.
이것이 문서(documentation)가 인터페이스로서 가진 구조적인 문제이다: 그것은 정중한 요청일 뿐이다. 모델은 그것을 읽고 동의하지만, 네 번째 작업을 수행할 때 어쨌든 bg-blue-500을 작성한다. 왜냐하면 '하지 말라'는 내용이 컨텍스트에서 주의 범위 밖으로 스크롤되어 나갔기 때문이다. 더 좋은 문장으로 이것을 고칠 수는 없다. 이 문서에는 _아니오_라고 말할 방법이 없다.
서버가 실제로 하는 일
아홉 개의 도구 중 세 개가 가장 많은 역할을 합니다.
suggest_tokens는 하드코딩을 방지하는(anti-hardcoding) 도구입니다. AI가 #FF5733를 작성하려고 할 때, 먼저 사용자에게 물어보도록 되어 있으며 이 도구는 OKLab 색상 거리(color distance)를 이용해 가장 가까운 실제 토큰으로 답변합니다. 이 경우 ΔE 0.053의 red-500이 근접하지만 정확하지 않습니다. 그리고 정확한 일치가 없을 때, 이 도구는 "가장 가까운 것을 고르세요"라고 말하지 않습니다. 대신 AI에게 사용자에게 토큰 시스템을 우회할지 여부를 물어보라는 지침 프롬프트를 반환합니다. 그 결정은 모델이 내릴 수 있는 것이 아니었습니다.
validate_code는 제가 실제로 원했던 도구입니다. 생성된 TSX를 입력하면 AST(추상 구문 트리)를 파싱하고, cn() 호출이나 템플릿 리터럴 안에 숨겨진 것들을 포함하여 모든 className을 추출한 다음, 열네 가지 규칙을 확인합니다: 순수 팔레트 색상(raw palette colors), 임의 값(arbitrary values), dark: 접두사(자체적으로 테마 전환되는 의미론적 토큰), leading-* 재정의(타이포그래피 토큰이 폰트 크기와 줄 높이를 쌍으로 지정하는 것), 인라인 스타일, 컴포넌트가 존재하는 곳에 네이티브 <button>을 사용한 경우 등입니다. 위반 사항은 영어, 일본어 또는 한국어로 라인 번호와 수정 제안과 함께 반환됩니다.
세 번째는 도구라기보다는 파이프라인(pipeline)에 가깝습니다. 서버가 컴포넌트에 대해 아는 모든 것은 llms-full.txt에서 생성되며—그리고 실제 소스 내보내기(source exports), CVA 변형 정의(variant definitions), CLI 레지스트리라는 다른 세 가지 진실의 출처와 교차 확인됩니다. 동일한 시스템에 대한 네 개의 기록이 존재하며, 만약 쌍 중 어느 하나라도 벗어나면 빌드가 실패합니다. 이 검사기가 Badge xl의 거짓말을 잡아냈습니다. v0.3.7의 변경 로그에는 일반적인 버그 수정으로 배포되었는데, 실제로도 그러했습니다—문서에 있는 버그는 여전히 버그이며, 다만 충돌을 일으키는 대신 AI 출력을 손상시킬 뿐입니다.
(디버깅 우회 비용이 들었던 사소한 세부 사항: 리소스 URI. 저는 제 이름을 7onic://rules/core로 지정했는데 SDK가 모든 요청에 "Invalid URL"이라는 메시지로 거부했습니다. URL 스킴은 숫자로 시작할 수 없습니다. 이제는 design://7onic/입니다.)
두 번 맞았던 카운트
빌드 중간 단계에서 파이프라인은 내 디자인 시스템에 41개의 컴포넌트가 있다고 주장했습니다. 모든 공개 페이지, README, llms.txt 헤더 — 모두 42개라고 말합니다.
저는 정말 불편한 시간을 보내며 수십 개의 파일을 거쳐 '42'를 수정할 준비를 하다가, 결국 모든 것을 손으로 다시 세보기로 결정했습니다. 두 숫자 모두 맞습니다. 공개 카운트는 사용자가 문서를 탐색하는 방식대로 네 가지 차트 유형을 네 개의 컴포넌트로 간주하고, 내부 유틸리티 두 개는 계산하지 않았습니다. 반면, 기계가 센 것은 통합된 Chart 소스 하나와 그 유틸리티들입니다. 같은 시스템에 대한 두 가지 다른 조사이며, 둘 다 내부적으로 일관성이 있습니다. 저는 다시는 거의 '수정'할 뻔한 실수를 하지 않기 위해 이 정의를 적어두었습니다.
이것을 언급하는 이유는 이것이 이번 주의 작은 교훈이기 때문입니다: 디자인 시스템을 기계적으로 검사하는 어려운 부분은 검사기를 작성하는 것이 아닙니다. 그것은 여러분 자신의 사실 중 얼마나 많은 부분이 정확하게 정의되지 않았는지 발견하는 것입니다.
검증기 역시 틀렸다
공정성을 위해서는 반대 방향도 보고해야 합니다. '시각적 오버라이드 없음(no-visual-override)' 규칙의 첫 번째 버전은 <DropdownMenuItem className="text-error">Delete</DropdownMenuItem>를 위반으로 플래그했습니다. 그 패턴은 제 자체 문서에도 있습니다 — 메뉴 항목에 의미론적 텍스트 색상을 적용하는 것이 파괴적인 동작을 표시하는 방법입니다. 이 규칙은 자신이 강제하는 시스템보다 더 엄격했습니다.
이러한 문제 유형에 대한 해결책은 게이트가 되었습니다: 모든 출시 전에 검증기는 llms.txt의 42개 검증된 예제 전체에서 오류와 경고를 모두 '0'으로 만들어야 합니다. 문서가 검증기를 규율하고, 검증기가 문서를 규율합니다. 어느 쪽도 상사가 아닙니다.
그러다가 엔드투엔드(end-to-end) 하네스가 실제 stdio 위에서 전체 과정을 구동했습니다 — 각각 깨끗한 버전과 심어 놓은 위반 사항을 담은 손상된 버전을 가진 다섯 가지 가짜 빌드 시나리오가 있었습니다. 현재 점수: 15개의 심어진 위반 사항 중 15개 감지, 클린 실행에서는 오탐(false alarm) 제로였습니다. 저는 매번 출시 전에 이것을 재실행하고 여전히 완전히 신뢰하지 않는데, 제가 결정하기로는 이것이 올바른 정도의 신뢰입니다.
설치 단계 없이 배포하기
배포판(Distribution)에는 제가 중요하게 생각하는 제약 조건이 하나 있었습니다: 사용자가 아무것도 설치할 필요 없이 이 모든 것을 얻을 수 있어야 한다는 것입니다. 서버 번들은 커밋된 dist/ 디렉터리로 묶이며, 다섯 가지 종속성(dependencies)은 내장됩니다. Claude Code의 경우 플러그인 형태로 제공되며, 단 하나의 명령어로 전체가 3.3 MB에 들어옵니다.
이곳에는 상처에서 비롯된 디자인 결정이 하나 있었습니다. 만약 Claude Code 플러그인의 루트 디렉터리에 package.json 파일이 포함되어 있다면, 설치 프로그램은 친절하게도 npm ci를 실행하여 전체 종속성 트리를 모든 사용자 캐시에 가져옵니다. 저는 이 아키텍처의 초기 프로토타입이 그렇게 수백 메가바이트로 부풀어 오르는 것을 목격했습니다. 따라서 여기 플러그인의 루트는 의도적으로 package.json을 포함하지 않습니다. 실제 빌드에 대한 심볼릭 링크(Symlinks)만 있을 뿐, 설치할 것이 없고 해결해야 할 것도 없습니다.
실제로 배포되는 방식
서버가 이틀 동안 운영되었으니, 이것은 최종 평가라기보다는 첫인상으로 받아들여 주십시오.
제가 이미 말할 수 있는 것은 다음과 같습니다: 문서(docs)와 강제 적용(enforcement)이 표류하는 것이 아니라 수렴하고 있다는 것입니다. 왜냐하면 이제 이들이 서로를 기반으로 생성되고 확인되기 때문입니다. 따라서 빌드 과정에서 어딘가 빨간불이 들어오지 않는 한, 문서는 조용히 썩어버릴 수 없습니다. llms.txt는 쓸모없게 되지 않았습니다. 오히려 도구들이 컴파일하는 원천(source)이 되었습니다. 정중한 요청은 여전히 존재합니다. 다만 이제는 경비원(bouncer)이 생긴 것뿐입니다.
제가 아직 모르는 것은 다른 사람들의 손에서, 다른 에이전트들과 함께, 저의 코드베이스가 아닌 곳에서 이것이 어떻게 작동할지 하는 점입니다. 다국어 쿼리(그림자는 그림자 토큰을 찾고, チャット入力은 ChatInput을 찾습니다)는 사람들이 영어로 코딩하더라도 자신의 언어로 디자인에 대해 생각한다는 이론을 바탕으로 구축되었습니다. 합리적인 이론이지만, 현장 데이터는 전무합니다.
만져보고 싶다면: claude plugin marketplace add itonys/7onic && claude plugin install 7onic-design@7onic를 사용하거나, 긴 방법인 7onic.design/components/mcp로 접속할 수 있습니다.
About 7onic — 디자인과 코드가 절대 어긋나지 않는 오픈 소스 React 디자인 시스템입니다. 무료이며, MIT 라이선스를 따릅니다. 문서 및 인터랙티브 플레이그라운드는 7onic.design에서 확인할 수 있습니다. 소스 코드는 GitHub에 있으며, 별점(star)은 환영합니다. 이 시리즈의 더 많은 게시물은 blog.7onic.design에서 확인하세요. X(@7onicHQ)에서 업데이트를 팔로우하세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기