전편: AI가 만든 UI가 어딘가 '어색한' 이유 — 그리고 그걸 고치는 한 가지 원칙에서 "축마다 값 하나"라는 정합성 원칙을 다뤘습니다. 이번 글은 그 다음 이야기 — *원칙만으론 부족했고, 강제 장치가 필요했다*는 걸 배운 과정입니다.
룰을 줘도 안 지키더라
전편을 쓰고 나서 저는 그 원칙들을 74개 룰로 정리해 오픈소스(StyleSeed)로 공개했습니다. Claude Code·Cursor·Codex가 UI를 만들기 전에 읽는 디자인 룰셋이죠.
그런데 이상한 일이 생겼습니다. 제가 만들면 잘 나오는데, 룰만 받아간 사람들 결과물은 여전히 "AI 티"가 났어요. 같은 74개 룰인데요.
몇 주를 파고든 결론: 격차는 룰이 아니라 루프에 있었습니다. 저는 무의식적으로 이 순서를 돌고 있었어요.
디자인 결정 고정(락) → 빌드 → 채점 → 80점 미만이면 수정 → 재채점 → 통과 후에만 확인
반면 룰만 받은 에이전트는 읽고, 끄덕이고, 첫 초안을 그대로 보여줍니다. 사람으로 치면 코드리뷰 체크리스트를 벽에 붙여두고 리뷰 없이 머지하는 격이죠. 룰은 지식이고, 루프는 규율입니다. 지식은 전달됐는데 규율이 전달되지 않았던 겁니다.
그래서 루프를 강제했습니다
v2.7부터 StyleSeed의 정문은 룰 문서가 아니라 강제 루프입니다.
/ss-build inventory dashboard
/ss-build는 이렇게 동작합니다:
-
락 먼저 — 프로젝트에
STYLESEED.md(키컬러·폰트·모서리·모션이 적힌 디자인 락 파일)가 없으면 UI 코드를 쓰기를 거부하고 락부터 만듭니다. "AI가 만든 티"의 1등 원인이 매 프롬프트마다 결정이 초기화되는 드리프트거든요. - 빌드 — 락과 74개 룰 기준으로 만듭니다.
-
게이트 —
/ss-score가 8개 카테고리(색 규율·위계·레이아웃·카드·상태·모션·정합성·독창성)로 0~100 채점하고, 80점 미만이면 사용자에게 보여주지 않고 감점 항목을 스스로 고친 뒤 재채점합니다. - 통과한 것만 최종 점수와 함께 보여줍니다.
핵심 설계는 "80점은 천장이 아니라 바닥"이라는 것. 100점을 쫓느라 출시가 늦어지는 것도 실패 모드라서, 게이트는 명백히-제네릭한 초안이 사용자에게 도달하는 것만 막습니다.
코드는 통과했는데 픽셀이 어색하다면
게이트를 몇 달 돌리면서 알게 된 것: 최악의 "AI 티" 몇 개는 코드에 존재하지 않습니다. 픽셀에만 존재해요.
- 웹폰트가 조용히 실패해서 Times New Roman으로 렌더된 히어로
- 코드상 문제없는데 화면 아래 1/3이 죽은 여백
- 각각 정당한 두 색이 렌더되니 "강조색 2개"로 읽히는 화면
- 포컬 포인트 없이 균일하게 나열된 카드 그리드
그래서 v2.10에 비주얼 게이트(/ss-verify)를 추가했습니다. 화면을 실제로 렌더 → 스크린샷 → 에이전트가 이미지를 직접 보고 채점합니다. 코드 게이트(ss-score)와 픽셀 게이트(ss-verify), 두 단계 통과가 기본 루프가 됐습니다.
첫 희생자: 제 랜딩페이지 (58/100)
게이트를 만들었으면 자기한테 먼저 돌려야죠. 게이트 도입 전에 만들었던 저희 랜딩 초기 버전을 넣었더니:
| 카테고리 | 점수 | 잡힌 것 |
|---|---|---|
| 색 규율 | 7/16 | 언락 상태의 기본 인디고 + 그라디언트 히어로 텍스트 |
| 독창성 | 3/10 | 기능마다 반복되는 아이콘칩 클리셰, 목업 화면, 포컬 없음 |
| 정합성 | 5/12 | 반짝이 배지 + 그라디언트 헤드라인 + 플랫 버튼 — 언어 3개 혼재 |
| 위계·타이포 | 12/16 | 숫자/단위 2:1 미적용 |
| 상태·접근성 | 12/18 | 포커스 링 누락, 대비 미달 |
| 나머지 3개 | 19/28 | 오프그리드 간격, 1px 테두리 분리, 임의 페이드 |
| 합계 | 58/100 (F) |
만든 사람 입장에서 꽤 굴욕적인데, 동시에 이 도구를 계속 만들 이유이기도 했습니다. 게이트가 잡은 건 전부 기계적으로 고칠 수 있는 것들이었거든요. 강조색 하나로 고정, 목업 대신 실제 제품 화면을 포컬로, 아이콘칩 카드를 넘버링 플로우로 — 58 → 86. 감점 내역 전체는 채점표 페이지에 공개해뒀습니다.
커버 이미지가 그 비포/애프터입니다. 같은 제품, 같은 프롬프트 — 룰만 바꿨습니다.
Hacker News에서 또 한 번 (96→100)
이 글을 쓰기 몇 시간 전, Show HN에 올렸다가 이런 댓글을 받았습니다.
"Lighthouse 접근성 감사에서 떨어지는 요소가 꽤 있는데요."
돌려보니 사실이었습니다. 96점, 실패 요소 19개 — 다크 섹션의 11px 라벨 대비 미달 16개, aria-label이 보이는 텍스트를 포함하지 않는 버튼 3개. 접근성 채점 기준을 가진 도구의 홈페이지가, 최근 수정 후 게이트를 다시 안 돌려서 드리프트한 겁니다.
두 시간 안에 고쳐서 100점으로 만들고 답글로 보고했습니다. 교훈은 58점 때와 같습니다:
게이트는 한 번 통과하는 시험이 아니라, 수정할 때마다 다시 돌리는 루프다.
자기 도구의 규칙을 자기가 어기는 건 부끄러운 일이 아니라 — 게이트가 없으면 누구나(만든 사람조차) 드리프트한다는 증거에 가깝습니다.
정합성 다음 단계: 프리셋
전편의 반론 중 이런 게 있었습니다. "정합성을 지켜도 여전히 제네릭해 보이면?" 맞는 말입니다. 일관된 화면도 얼마든지 밋밋할 수 있어요. 정합성은 필요조건이지 충분조건이 아닙니다.
그래서 v2.8에 프리셋(/ss-restyle)을 넣었습니다 — swiss · editorial · technical · warm-dtc · minimal-mono · brutalist-lite. 각각이 모서리·타입·밀도·시그니처 무브까지 통째로 맞춰진 "하나의 좌표"라, 정합성을 깨지 않고 룩 전체를 갈아탑니다.
같은 제품이 구조부터 다른 6가지 화면이 됩니다. 각각 일관되고, 서로 다르고, 어느 것도 "기본값" 냄새가 나지 않는 것이 목표였습니다.
정리
- 룰만 주면 에이전트는 루프를 건너뛴다. 지식이 아니라 규율을 전달해야 한다 — 게이트를 강제하는 커맨드로.
- 코드 게이트 + 픽셀 게이트, 두 단계. 최악의 티는 렌더된 화면에만 존재한다.
- 게이트는 만든 사람부터 계속 통과해야 한다. 내 랜딩 58점, HN 지적 후 접근성 96점 — 두 번 다 게이트를 건너뛴 내 잘못이었다.
전부 오픈소스(MIT)입니다: github.com/bitjaru/styleseed — npx skills add bitjaru/styleseed 한 줄이면 Claude Code·Cursor·Codex에 붙습니다. 룰이 틀렸거나 너무 경직된 곳을 찾으시면 이슈로 알려주세요. 그게 이 룰셋이 자라는 방식입니다.

Top comments (0)