프로젝트마다 다른 색상과 간격, 반복되는 설정 작업을 해결하기 위해 토큰과 컴포넌트를 중앙에서 관리하고 명령어 하나로 배포하는 시스템을 만들기
프로젝트마다 다른 UI, 설정에 30분씩
프로젝트 A는 Primary 색상으로 #3B82F6을 쓰고, 프로젝트 B는 #2563EB를 쓴다. 같은 조직인데 브랜드 컬러가 프로젝트마다 다르다. 신규 프로젝트를 시작할 때마다 tokens.css를 복사하고, 패키지를 설치하고, 규칙 문서를 찾아 읽는 데 30분 이상 소요된다. 중앙에서 토큰을 업데이트해도 각 프로젝트가 수동으로 반영해야 하니 버전이 파편화된다.
처음엔 개발자가 만든 토큰을 다른 저장소에 수동으로 복사했다
초기에는 디자인 토큰을 정의한 tokens.css 파일을 만들어두고, 프로젝트마다 복사해서 쓰는 방식이었다. 문서에 "여기서 복사하세요"라고 적어두고, 개발자가 직접 파일을 가져가도록 했다. 컴포넌트도 마찬가지였다. Button 컴포넌트가 필요하면 이전 프로젝트에서 코드를 복사해 왔다.
이 방식의 문제는 명확했다. 중앙에서 토큰을 수정해도 기존 프로젝트에는 반영되지 않았다. 각 프로젝트가 서로 다른 버전의 토큰을 쓰고 있으니 UI 일관성이 무너졌다. 컴포넌트를 복사해서 쓰다 보니 같은 Button이 프로젝트마다 조금씩 다르게 구현되었다.
중앙 집중화가 필요했다
해결 방법은 명확했다. Single Source of Truth. 모든 토큰과 컴포넌트를 중앙 저장소에서 관리하고, 각 프로젝트는 이를 참조만 하도록 바꾸는 것이었다. 내가 생각한 구상도는 대략 이렇다.
┌─────────────────────────────────────────────────────────────┐
│ geniefy/design-system (중앙) │
│ │
│ components/ tokens.css docs/ │
│ │ │ │
│ ▼ ▼ │
│ npm publish CDN (jsDelivr) │
│ @geniefy/ui 즉시 반영 │
└───────────────────────┬─────────────────────────────────────┘
│
┌─────────────┴─────────────┐
▼ ▲
Downstream Upstream
(자동 업데이트) (자동 기여)
│ │
┌─────────┴───────────────────────────┴───────────────────────┐
│ 사용자 프로젝트 │
│ │
│ Dependabot → PR → Auto-merge Write → Hook → GitHub │
│ (새 버전 감지) (components/ 생성 시) │
└─────────────────────────────────────────────────────────────┘바이브코더들을 위한 디자인 시스템은 기존의 디자인시스템과는 구조가 다르다. 근간이 되는 token.css와 이 값들을 기반으로 작성되는 component의 경우 구조는 같지만, 여기에 작업을 할 때 에이전트가 참조할 design system guide docs.md 파일이 필요하다. 에이전트가 함부로 작업을 하지 못하게 강한 제약을 걸고, 무엇을 참조하여 작업할지 적어놓은 지침 말이다. 그리고 이것들로 이루어진 디자인 시스템을 커스텀 커맨드 하나만으로 작동시키고자 한 게 나의 목적이었다. 그러기 위해서 하나의 명령어로 수행할 여러 로직들을 구현해야만 했다.
토큰은 즉시 반영이 필요했다. Primary 색상을 #3B82F6에서 #327039로 바꾸면 모든 프로젝트에 즉시 적용되어야 했다. 하지만 컴포넌트는 달랐다. Button의 API가 바뀌면 기존 프로젝트가 깨질 수 있었다. 버전 관리가 필요했다.
결국 하이브리드 전략을 택했다. 토큰은 CDN으로, 컴포넌트는 npm으로 배포하기로 했다.
tokens.css는 jsDelivr CDN으로 배포했다. GitHub에 push하면 CDN이 자동으로 캐시를 무효화하고 최신 파일을 제공한다. 각 프로젝트는 index.html에 CDN 링크만 추가하면 끝이다.
html<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/geniefy/design-system/tokens.css">
컴포넌트는 npm 패키지로 배포했다. main 브랜치에 push하면 GitHub Actions가 자동으로 npm에 배포한다. 각 프로젝트는 package.json에 버전을 명시해서 Breaking Change로부터 보호받는다.
npm install @geniefy/[email protected]
하지만 여전히 문제가 있었다. 중앙에서 v1.2.0을 배포했는데 어느 프로젝트가 아직 v1.0.0을 쓰고 있는지 알 수 없었다. 관리자가 일일이 독촉할 수도 없는 노릇이었다. 그래서 GitHub Dependabot을 활용해 PR없이 자동으로 머지가 되는 방법을 이용하기로 했다. 새 버전이 배포되면 Dependabot이 자동으로 PR을 생성한다. CI가 통과하면 자동으로 머지된다. minor/patch 업데이트는 자동으로 적용되고, major 업데이트는 수동 검토를 거친다.
이제 중앙에서 배포하면 모든 프로젝트가 자동으로 업데이트된다. 버전 파편화 문제가 해결되었다.
/setup-design, 단 하나의 명령어로 이 모든 걸 구현하기
CDN 링크를 추가하고, npm 패키지를 설치하고, 규칙 문서를 복사하는 작업을 매번 수동으로 하면 사실 도입 안하느니만 못한 시스템이 된다. 그렇기 때문에 이 모든 과정을 Claude Code 커맨드 하나에 담아두었다.
/setup-design
이 명령어 하나로 다음 작업이 자동 실행된다:
1. @geniefy/ui npm 패키지 설치
2. index.html에 tokens.css CDN 링크 추가
3. design-rules.md를 .claude/skills/에 복사
4. PostToolUse Hook 등록 (AI가 코드 생성 시 자동 검증)
5. 설정 검증 및 완료 메시지
Generation Protocol로 품질을 통제하기
양방향 동기화 구조에서 가장 위험한 것은 각 프로젝트가 자유롭게 컴포넌트를 생성하는 것이었다. 토큰을 쓰지 않고 color: red 같은 하드코딩 색상을 쓰면 디자인 일관성이 무너진다. 기존 컴포넌트가 있는데 중복 으로 만들면 유지보수 비용이 늘어난다.
해결책은 생성 단계에서 통제하는 것이었다. design-rules.md라는 규칙 문서를 만들고, AI가 UI를 생성할 때 자동으로 참조하도록 했다.
얼핏 보면 design-rules.md는 개발자의 자유를 제한하는 것처럼 보인다. 원하는 색상을 쓸 수 없고, 원하는 간격을 줄 수 없다.
그러나 이 제약은 역설적으로 더 큰 자유를 가능하게 한다:
의사결정 피로 감소: "이 버튼의 패딩을 몇 px로 할까?"라는 질문을 할 필요가 없다.
--spacing-2를 쓰면 된다.리뷰 시간 단축: 토큰만 사용했는지 확인하면 된다. 시각적 일관성은 시스템이 보장한다.
안전한 실험: 토큰 값을 변경해서 전체 시스템의 룩앤필을 한 번에 바꿀 수 있다. 개별 컴포넌트를 건드릴 필요 없다.
AI 협업 가능: 명확한 제약이 있어야 AI가 "올바른" 코드를 생성할 수 있다. 모호함은 AI의 적이다.요청: "빨간 버튼 만들어줘"
같은 이유로 다른 제약도 걸어놨다. token.css의 경우 CDN으로 즉시 반영되는 만큼, 토큰명을 함부로 삭제하거나 변경하면 모든 프로젝트가 동시에 깨진다. 이를 방지하기 위해 세 가지 보호 장치를 만들었다:
1. CODEOWNERS: tokens.css 변경 시 관리자 리뷰 필수
2. CI Script: PR에서 토큰명 삭제를 감지하면 경고
3. Generation Protocol: AI가 토큰을 쓰지 않은 코드를 생성하면 거부
토큰 값을 변경하는 것은 허용되지만 (의도적 디자인 변경), 토큰명을 삭제하는 것은 차단된다.
design-rules.md는 정적인 문서가 아니다. 팀이 새로운 패턴을 발견하면 규칙이 추가되고, 더 이상 유효하지 않은 규칙은 제거된다. 이는 token값도, component 값도 마찬가지다.
배운 것
배포 전략은 자산의 성격에 따라 달라야 한다. 토큰은 즉시 반영이 필요하니 CDN으로, 컴포넌트는 안정성이 중요하니 npm으로 배포했다. 하나의 방식으로 모든 것을 해결하려 하지 않았다.
자동화는 설정뿐 아니라 품질 관리에도 적용된다. /setup-design으로 설정을 자동화했고, Generation Protocol로 코드 생성 단계에서 품질을 통제했다. 사후 검토보다 사전 차단이 효과적이었다.
좋은 시스템은 사용자가 신경 쓸 것이 적다. Dependabot이 자동으로 업데이트하고, CI가 토큰 삭제를 감지하고, AI가 규칙을 강제한다. 바이브코더들은 그냥 코드만 작성하면 된다.
바이브코딩 시대의 디자인 시스템은 뿌리가 되는 기본 형태만 유지하면 모두가 다양한 컴포넌트를 추가할 수 있고, 모두가 이를 가져다 쓸 수 있는 형태가 되어야 한다고 생각한다. 자산이 SSOT로 관리되면서 참조할 저장소를 한 곳으로 집중했기 때문에, 사람과 AI는 이 곳에 모여있는 에셋들을 쉽게 필터링할 수가 있기 때문이다. 이런 방식의 협업이 앞으로 가까운 시일 내에 다양한 조직에서 사용될지 모르는 일이다.
임시 배포된 지피터스의 디자인 시스템은 이곳에서 확인 가능합니다.