AI가 만든 화면의 ‘티’를 규칙으로 잡는다: pbakaus/impeccable의 디자인 스킬 24개 명령·61개 결정론 검출기·에이전트 훅·Rust 엔진 심층 해부와 박스 실측

Claude Code나 Codex에 “랜딩 페이지 하나 만들어 줘”라고 하면 결과물이 묘하게 닮아 있다. Inter 글꼴, 보라에서 파랑으로 넘어가는 그라데이션, 제목 위의 작은 알약 모양 라벨, 카드 안에 또 카드, 한쪽에만 굵은 색 테두리를 두른 카드. 디자이너들은 이걸 ‘AI 슬롭(slop)’의 티라고 부른다. pbakaus/impeccable은 이 문제를 두 갈래로 다룬다. 하나는 코딩 에이전트에게 디자인 어휘와 절차를 가르치는 스킬(명령 24개)이고, 다른 하나는 LLM 없이 HTML·CSS·JSX와 렌더된 페이지를 검사하는 결정론적 검출기 61개 규칙이다. 둘은 Rust로 짠 단일 엔진 바이너리 위에서 묶이고, 에이전트가 파일을 고칠 때마다 도는 훅으로 이어진다. 오늘(2026-10-22) GitHub Trending Rust 일간 13위(+669)에 올랐다.

Impeccable 한눈에: 보라 그라데이션·한쪽 굵은 테두리·카드 속 카드 같은 AI 생성 UI의 티를 61개 결정론 규칙으로 짚어 정돈된 화면으로 고치게 한다
Impeccable 한눈에: 보라 그라데이션·한쪽 굵은 테두리·카드 속 카드 같은 AI 생성 UI의 티를 61개 결정론 규칙으로 짚어 정돈된 화면으로 고치게 한다

이 글은 기능 소개보다 도입 전에 판단할 거리를 다룬다. ① 텍스트 스킬과 Rust 엔진이 어떻게 나뉘는지(16개 크레이트 구조), ② 61개 규칙이 무엇을 잡고 정적 스캔과 브라우저 렌더 스캔이 어떻게 다른지, ③ 훅이 에이전트 문맥에 무엇을 주입하는지, ④ 설치·다운로드 검증·텔레메트리 같은 신뢰 경계를 본다. 그리고 박스(리눅스 x64 VM)에 격리 HOME, DO_NOT_TRACK=1·IMPECCABLE_NO_TELEMETRY=1, API 키 없음 조건으로 엔진 0.1.16 릴리스 바이너리를 받아 저장소 픽스처 227개 스캔, 직접 만든 ‘슬롭’ 페이지와 ‘정돈된’ 페이지의 정적·크롬 렌더·모바일 폭 비교, Claude Code 훅 입력을 흉내 낸 PostToolUse·Stop 훅 실행, 오프라인·온라인 설치를 직접 돌렸다. 수치는 2026-10-22 11:53~12:20 KST 실측이거나 GitHub·npm API와 저장소 문서에서 확인한 값이다.

한눈에 보기: 오늘 기준 스냅숏

항목 값
저장소 github.com/pbakaus/impeccable (생성 2025-11-16 10:52 KST) · 만든 사람 Paul Bakaus · 홈페이지 impeccable.style
라이선스 Apache-2.0. iOS·Android 참고 문서 2편은 ehmo/platform-design-skills(MIT)를 다시 쓴 것이라고 NOTICE.md에 명시
버전 스킬 4.7.0 · CLI 4.7.0(2026-10-20 02:52 KST) · 엔진 0.1.16(2026-10-20 02:30 KST). 릴리스는 skill/cli/engine 태그가 따로 붙어 89개
GitHub 지표 84,494 stars · 5,051 forks · 열린 이슈+PR 48 · 기여자 약 59명(익명 포함, API 기준) · 마지막 커밋 e132b1e(2026-10-22 11:34 KST)
Trending Rust 일간 #13(+669, 11:53 KST). 전체 일간 목록에는 없음
npm impeccable 주간 다운로드 136,966(2026-10-12~10-18). npm 패키지는 엔진 바이너리를 부르는 얇은 셔임
언어 구성 엔진은 Rust 워크스페이스(16 크레이트), 스킬은 Markdown, 확장·라이브 모드는 JS. 런타임에 Node 불필요(npx 설치 때만 필요)
지원 하네스 Claude Code, Cursor, Codex CLI, GitHub Copilot, Gemini CLI, Grok Build, Hermes Agent, OpenCode, Kiro, Trae 등 README 기준 17종

무엇이 들어 있나: 스킬·검출기·훅·라이브 모드

README는 출발점을 숨기지 않는다. Anthropic의 frontend-design 스킬이 Claude에서 처음 널리 쓰인 디자인 스킬이었고, Impeccable은 거기서 시작했다고 적는다. 차이는 ‘글로 된 지침’에 ‘기계가 확인하는 규칙’을 붙였다는 데 있다. 모델에게 “Inter 쓰지 마”라고 쓰는 것만으로는 지켜진다는 보장이 없으니, 결과물을 다시 스캔해 어겼는지 확인하는 루프를 만든 것이다.

구성 요소 실체 하는 일
스킬 /impeccable SKILL.md(11,906바이트, 1,594단어) + reference 문서 42편(약 441KB) 디자인 절차·금지 목록·모드별 지침을 모델 문맥에 공급. 필요한 reference만 골라 읽게 라우팅
프로젝트 맥락 파일 PRODUCT.md, DESIGN.md, .impeccable/config.json init이 대상 사용자·목적·제약·어조를 PRODUCT.md에 기록. 시각 체계는 DESIGN.md로 분리
검출기 detect 규칙 61개(슬롭 31 · 품질 30) 파일·디렉터리·URL을 LLM 없이 검사. 텍스트·JSON 출력, 종료 코드 0/1/2
디자인 훅 Claude Code·Codex·Cursor·Grok Build·Copilot용 매니페스트 파일 편집 후·턴 종료 시 엔진이 돌아 발견 사항을 모델 문맥에 주입
라이브 모드 /impeccable live, generate 로컬 개발 서버 페이지에 도우미를 주입해 요소 단위 변형을 브라우저에서 비교·선택
브라우저 확장 Chrome 확장 1.4.0(권한 activeTab·scripting·storage·webNavigation·offscreen, 호스트 <all_urls>) 렌더된 페이지에서 같은 결정론 규칙을 돌림

명령 24개는 네 묶음으로 보면 쉽다

묶음 명령 용도
준비·문서화 init, document, extract, shape 제품 맥락 기록, 기존 코드에서 DESIGN.md 생성, 토큰·컴포넌트 추출, 코드 전 UX 계획
진단 audit, critique audit는 접근성·성능·반응형 같은 기술 검사, critique는 위계·명료성 같은 UX 리뷰
방향 조정 bolder, quieter, distill, colorize, typeset, layout, animate, delight, overdrive 같은 화면을 더 대담하게·차분하게·단순하게, 또는 색·글꼴·배치·움직임 축 하나만 손본다
마감·확장 polish, harden, clarify, adapt, optimize, onboard, craft, live, generate 출시 전 정리, 오류·국제화·넘침 처리, 문구, 기기 대응, 성능, 첫 사용 흐름, 전체 제작 흐름, 브라우저 변형

/impeccable pin audit처럼 자주 쓰는 명령을 독립 단축 명령으로 고정할 수도 있다. 실무에서 의미 있는 것은 명령 이름이 곧 팀의 디자인 어휘가 된다는 점이다. “여기 좀 더 예쁘게”가 아니라 “이 섹션 quieter, 그다음 harden”처럼 지시가 짧고 재현 가능해진다.

구조: SKILL.md와 명령 24개·참고 문서 42편으로 된 텍스트 스킬이 셸 런처를 거쳐 Rust 엔진(detect·정적 HTML·Chrome CDP·hook·live·context)을 부르고, 결과는 CLI·CI, 에이전트 훅, 브라우저 확장으로 나간다
구조: SKILL.md와 명령 24개·참고 문서 42편으로 된 텍스트 스킬이 셸 런처를 거쳐 Rust 엔진(detect·정적 HTML·Chrome CDP·hook·live·context)을 부르고, 결과는 CLI·CI, 에이전트 훅, 브라우저 확장으로 나간다

아키텍처: 텍스트 스킬 + Rust 엔진 하나

원래 Node로 짠 CLI였던 것을 Rust로 다시 짠 결과, 지금 구조는 “스킬 폴더 안의 셸 런처 → 플랫폼별 정적 바이너리”다. 런처(scripts/impeccable, Windows는 impeccable.cmd)는 $IMPECCABLE_BIN → 옆에 놓인 바이너리 → ~/.impeccable/bin → 버전 고정 캐시 → PATH 순으로 엔진을 찾고, 없으면 GitHub 릴리스에서 내려받는다. 이때 .sha256 사이드카와 대조해 맞지 않거나 사이드카를 못 받으면 실행을 거부한다(fail closed). 각 동작의 관찰 가능한 결과는 docs/CLI-CONTRACT.md에 명세되어 있고 tests/oracle/의 골든 파일 1,219개로 바이트 단위까지 고정한다.

크레이트 src 줄 수 역할
core 67,848 모든 check_*·scan_* 규칙 로직과 휴리스틱, 브라우저 규칙 어댑터, 대비 판단
live 34,024 라이브 모드 서버·래핑·수동 편집 반영, Svelte/Vue 처리
context 21,888 context·doctor·concept-seed 등 스킬이 부르는 맥락 동사, 롤 API 클라이언트(텔레메트리 포함)
detect 13,970 impeccable detect: 파일 순회, 설정·무시 규칙, 출력 형식, 정규식 엔진
foundation 13,085 색 계산, 발견 사항 타입, 규칙 레지스트리, 인라인 무시, Dom 트레이트
html 12,850 정적 HTML 엔진: 파서, CSS 캐스케이드, 정적 DOM, 규칙 어댑터
browser 11,466 URL 엔진: Chrome 탐색, CDP 연결, 스냅숏, 시각 검사
comp-verbs / comp 10,860 / 3,585 시안(comp) 우선 제작 흐름의 비교·폰트 매칭·래스터 계산
hook 6,331 디자인 훅(편집 후·편집 전·관리)
skills / cli 5,071 / 4,041 install·update·check·link(옛 npm CLI 동사), 동사 라우터와 종료 코드
common / wasm / bundle / xtask 3,791 / 1,398 / 466 / 135 입출력·HTTP 서버 코어, 페이지 내 번들용 wasm 내보내기, 번들러, 빌드 보조

위 줄 수는 박스에서 각 크레이트 src/의 .rs 파일을 센 값으로, 합계 약 21만 줄이고 크레이트별 tests/에 약 2만 7천 줄이 더 있다. 디자인 “취향”을 다루는 도구치고는 상당히 무거운 엔지니어링이다. 특히 규칙 로직이 core 한 곳에 있고 정적 엔진(html)과 렌더 엔진(browser), 브라우저 확장(wasm)이 같은 규칙을 어댑터로 감싸 쓰는 구조라, 이론상 세 경로의 판정이 한 레지스트리에서 나온다. 다만 아래 실측에서 보듯 입력으로 받는 정보가 달라서 실제로 잡히는 규칙은 경로마다 다르다.

61개 규칙: ‘슬롭’ 31개와 ‘품질’ 30개

규칙 카탈로그(antipatterns.json)는 두 범주로 나뉜다. slop은 AI 생성 UI의 통계적 습관이고, quality는 사람이 만들었어도 문제인 일반 품질 항목이다. 일부는 advisory로 분류되어 목록에는 나오지만 실패 건수와 종료 코드에는 들어가지 않는다.

묶음 규칙 id(일부) 잡는 것
slop · 색·빛 ai-color-palette, gradient-text, dark-glow, radial-halo, radial-spotlight-glow, cream-palette 보라·바이올렛 그라데이션, 글자에 그라데이션, 색 있는 글로 그림자, 크림·베이지 팔레트
slop · 형태 side-tab, border-accent-on-rounded, nested-cards, icon-tile-stack, gpt-thin-border-wide-shadow, codex-grid-background, repeating-stripes-gradient 한쪽 굵은 테두리 카드, 카드 속 카드, 제목 위 둥근 아이콘 타일, 얇은 테두리+넓은 그림자, 장식용 격자 배경
slop · 글꼴·위계 overused-font, flat-type-hierarchy, oversized-h1, extreme-negative-tracking, italic-serif-display Inter·Roboto·Geist 등 과다 사용 글꼴, 납작한 크기 위계, 거대한 히어로 제목, 짓눌린 자간
slop · 장식·움직임 hero-eyebrow-chip, kicker-above-heading, numbered-section-labels, pulsing-dot, blinking-cursor, marquee, bounce-easing 제목 위 알약 라벨, 01·02 번호 라벨, 깜빡이는 상태 점, 자동 흐르는 띠, 튕기는 이징
slop · 문구 marketing-buzzword, em-dash-overuse, aphoristic-cadence, theater-slop-phrase supercharge·seamless·enterprise-grade 같은 상투어, 줄표 남발, 경구식 리듬
quality · 가독성 low-contrast, gray-on-color, tiny-text, tight-leading, line-length, all-caps-body, wide-tracking, justified-text WCAG AA 대비 미달, 색 배경 위 회색 글자, 너무 작은 본문, 좁은 행간, 너무 긴 줄
quality · 구조·배치 skipped-heading, cramped-padding, text-overflow, text-occlusion, first-viewport-column-overflow, edge-flush-cards, clipped-overflow-container 제목 단계 건너뜀, 비좁은 여백, 넘치거나 가려진 글자, 첫 화면에서 한 열만 길게 늘어짐
quality · 런타임·자산 broken-image, script-error, content-hidden-at-rest, buried-raster 깨진 이미지, 로드 시 스크립트 오류, 애니메이션 전엔 안 보이는 콘텐츠
quality · 디자인 시스템 design-system-font, -color, -radius, -font-size DESIGN.md·.impeccable/design.json에 없는 글꼴·색·모서리·크기 사용
규칙은 ‘취향’을 코드로 굳힌 것이다. 대비 미달이나 제목 단계 건너뜀은 누구에게나 문제지만, Inter 금지나 크림 팔레트 경고는 의견이다. 브랜드 글꼴이 Inter라면 npx impeccable ignores add-value overused-font Inter --reason "Brand font"처럼 예외를 명시적으로 남기라는 것이 공식 권장이다. 실측에서도 정돈된 페이지가 크림 배경 하나로 경고를 받았다.

정적 스캔과 렌더 스캔은 다른 도구라고 생각하라

정적(파일) 엔진 렌더(URL) 엔진
입력 로컬 HTML·CSS·JSX/TSX·Vue·Svelte·Astro 파일, 디렉터리 URL(설치된 Chrome·Chromium·Edge 사용) 또는 --cdp로 Electron 등 실행 중 앱
보는 것 소스에 쓰인 선언과 정적 캐스케이드 계산된 스타일, 실제 레이아웃, 접근 가능한 외부 스타일시트
강점 빠르다(픽스처 227개 1.1초), 브라우저 불필요, CI·훅에 적합, 오프라인 동작 중첩 카드·이징·넘침·줄바꿈 낙오(straggler) 같은 렌더 의존 규칙
약점 렌더해야 알 수 있는 규칙은 못 잡음 느림(페이지당 2.5~4.7초 실측), 교차 출처 CSS는 CORS 없으면 못 읽음, 로컬에 없는 웹폰트는 대체 글꼴로 판정될 수 있음
옵션 --no-config, --no-design-system, --no-inline-ignores --viewport 390x844(모바일 폭), 동의 배너·온보딩 오버레이 자동 숨김(--no-consent-hiding로 해제)

설치: 네 가지 경로와 각각이 건드리는 것

# 권장: 프로젝트 루트에서 (감지된 하네스에 스킬+훅 설치)
npx impeccable install                      # 대화형
npx impeccable install -y --providers=claude,codex --scope=project
npx impeccable update                       # 갱신

# 하네스 없이 검출기만
npx impeccable detect src/
npx impeccable detect --json . > findings.json      # CI용
npx impeccable detect https://example.com --viewport 390x844

# 텔레메트리 끄기 (아래 별도 설명)
npx impeccable telemetry off      # 또는 DO_NOT_TRACK=1 / IMPECCABLE_NO_TELEMETRY=1
경로 건드리는 것 비고
CLI 설치기 npx impeccable install .claude/, .agents/, .cursor/ 등 하네스 폴더에 스킬 복사 + 엔진 바이너리 + 훅 매니페스트 가장 간단. 실측에서 Claude+Codex 지정 시 파일 128개, 엔진 바이너리가 두 폴더에 각각 들어가 23MB씩
Git 서브모듈 + link .impeccable 서브모듈에서 심링크 팀이 버전을 커밋으로 고정하고 리뷰하기 좋음
플러그인 Claude Code 마켓플레이스, Grok Build #plugin, VS Code 확장(Copilot용, 훅 없음), Cursor 플러그인 하네스 고유 업데이트 흐름을 따름
수동 복사 빌드된 dist/를 직접 복사 디버깅·에어갭용 대안

원격 스킬 ZIP은 설치 전에 Ed25519 서명으로 검증된다(docs/BUNDLE-SIGNING.md). 서명은 ZIP의 SHA-256·바이트 길이·릴리스 버전·아티팩트 이름·키 ID를 묶고, 신뢰 키는 바이너리에 컴파일된 목록뿐이라 서명 파일이 새 키를 끌어들일 수 없다. 박스에서 네트워크를 끊고(unshare -rn) 설치하면 “Could not verify skill bundle … Nothing was installed”로 아무것도 쓰지 않고 멈췄다. 공급망 관점에서는 바람직한 동작이지만, 에어갭 환경에서는 서브모듈이나 수동 복사를 써야 한다는 뜻이기도 하다.

디자인 훅의 두 계층: 편집 직후에는 대비·그라데이션 글자·글로우 같은 즉시 계층만(박스 실측 5건, 55ms), 턴 종료 시 딥 패스가 나머지 규칙을 한 번에(7건, 52ms) 모델 문맥에 주입한다
디자인 훅의 두 계층: 편집 직후에는 대비·그라데이션 글자·글로우 같은 즉시 계층만(박스 실측 5건, 55ms), 턴 종료 시 딥 패스가 나머지 규칙을 한 번에(7건, 52ms) 모델 문맥에 주입한다

디자인 훅: 편집 직후 ‘즉시 계층’, 턴 끝에 ‘딥 패스’

훅은 이 프로젝트에서 가장 실무적인 부분이다. 규칙은 두 계층으로 나뉜다. 편집마다 도는 즉시 계층은 깨진 이미지, 넘침, 대비·가독성 실패, 그라데이션 글자, 글로 그림자, 디자인 시스템 이탈처럼 기계적이고 애매하지 않은 것만 보고한다. 문구 리듬, 팔레트·글꼴 취향, 배치 리듬은 Stop 이벤트의 딥 패스로 미뤄 세션 동안 건드린 UI 파일 전체에 한 번만 보고한다. 편집마다 취향 지적이 쏟아지면 에이전트가 원래 작업을 잃어버리기 때문이다.

하네스 파일 이벤트 주의
Claude Code .claude/settings.local.json SessionStart, PostToolUse(Edit|Write, 5초 제한), Stop(30초 제한) 명령 훅은 모델 도구 승인과 별개로 실행. 무인 실행 전 훅 검토 권장(README)
Codex CLI .codex/hooks.json PostToolUse(Edit|Write|apply_patch), Stop. Windows용 commandWindows 별도 설치·갱신 후 /hooks에서 프로젝트 훅을 직접 승인해야 동작
Cursor .cursor/hooks.json 편집 전 게이트(hook-before-edit) Stop 훅이 일관되게 오지 않아 딥 패스 대신 편집 전 검사
Grok Build .grok/hooks/impeccable.json 편집 후 + Stop(end_turn만) /hooks-trust 또는 --trust 필요
GitHub Copilot 프로젝트 훅 매니페스트 편집마다 전체 규칙 Stop 계열 이벤트가 모델에 문맥을 돌려주지 않아 계층 분리 없음

박스에서 슬롭 페이지를 index.html로 둔 임시 git 프로젝트에 Claude·Codex용으로 설치한 뒤, Claude Code가 훅에 넘기는 형태의 JSON(hook_event_name, tool_name: Write, tool_input.file_path)을 표준 입력으로 넣어 런처를 직접 실행했다. 네트워크는 끊은 상태였다.

이벤트 실행 시간 보고 건수 내용
PostToolUse (Write) 55ms 5건 gradient-text, gray-on-color, low-contrast×2, dark-glow — 즉시 계층만
Stop 52ms 7건 side-tab, hero-eyebrow-chip, overused-font, skipped-heading, ai-color-palette 등 나머지. 전부 [attribution unknown] 표시

출력은 {"hookSpecificOutput":{"hookEventName":…,"additionalContext":"[impeccable@1] Design hook findings…"}} 형태로, 발견 사항이 모델 문맥에 직접 주입된다. 지시문은 “진짜 문제면 고치고, 확실한 오탐이나 승인된 예외면 가장 좁은 무시 규칙을 직접 남기고 밝혀라, 그리고 무엇을 고치고 무엇을 남겼는지 답에 적어라”다. Stop 패스는 이번 세션 전부터 있던 문제일 수 있는 항목에 ‘attribution unknown’을 붙여 에이전트가 범위를 넓히지 않도록 한다. 편집 전 기준선(baseline)이 확인된 경우에만 기존 문제를 걸러 낸다. 50ms대 실행이라 편집 루프 지연은 체감하기 어려운 수준이다.

신뢰 경계 하나: 훅 지시문은 에이전트가 스스로 무시 규칙(.impeccable/config.json의 detector.ignore*, 인라인 impeccable-disable)을 추가하도록 허용한다. 공개 의무를 함께 걸어 두었지만, CI에서 검출기를 품질 게이트로 쓴다면 --no-inline-ignores나 --no-config로 원본 스캔을 따로 돌리거나 무시 규칙 변경을 코드 리뷰 대상으로 묶어 두는 편이 안전하다. 실측에서 인라인 무시 한 줄로 종료 코드가 2→0이 됐고, --no-inline-ignores로 다시 2가 됐다.

박스 실측

항목 내용
바이너리 릴리스 engine-v0.1.16의 impeccable-linux-x64(21,339,792바이트). .sha256 사이드카와 해시 일치(a890a5b4…1787), engine-probe → impeccable-engine 0.1.16
격리 작업 폴더 안 별도 HOME, DO_NOT_TRACK=1, IMPECCABLE_NO_TELEMETRY=1, API 키·LLM 없음. 파일 스캔과 훅은 unshare -rn으로 네트워크를 끊고 실행
렌더 스캔 박스에 설치된 google-chrome, 로컬 127.0.0.1 정적 서버(네트워크 격리 없이)
시험 대상 저장소 tests/fixtures/antipatterns(항목 227개, 파일 254개), 직접 작성한 슬롭·정돈 페이지 2종, 임시 git 프로젝트 설치·훅
돌리지 않은 것 실제 LLM과 스킬 명령(/impeccable craft 등)의 생성 품질, 라이브 모드, 브라우저 확장, 소스 빌드(cargo build)·오라클 테스트

① 공식 픽스처 227개 스캔

옵션 발견 건수 걸린 규칙 수 비고
기본 2,325 46 advisory 1,215 · warning 1,109 · error 1. 그중 design-system-color만 968건
--no-design-system 1,197 42 warning 1,021 · advisory 175 · error 1
--no-config 1,197 42 설정·무시·DESIGN.md를 모두 끈 원본 스캔. 위와 동일
--no-advisory 1,110 34 advisory 제외(디자인 시스템 경고 포함)

3회 반복 실행 시간은 1.14·1.127·1.124초였다(종료 코드 2). 눈여겨볼 점은 기본 실행과 --no-design-system 사이의 차이 1,128건이다. 픽스처 폴더에는 DESIGN.md가 없는데도, 검출기가 상위 디렉터리를 거슬러 올라가 저장소 루트의 DESIGN.md(Impeccable 사이트 자체의 디자인 시스템)를 읽고 픽스처 전체를 그 기준으로 평가했기 때문이다. 모노레포나 하위 폴더 단위로 스캔할 때 엉뚱한 디자인 시스템이 기준이 될 수 있다는 실무 함정이다. 카탈로그 61개 중 정적 스캔에서 한 번도 걸리지 않은 규칙은 15개였고, 대부분 넘침·가려짐·첫 화면 열 넘침·줄바꿈 낙오·스크립트 오류처럼 렌더해야 판단할 수 있는 것들이다.

박스 실측: 직접 만든 슬롭 페이지는 정적 18건·렌더 22건, 정돈된 페이지도 크림 배경으로 1건. 픽스처 227개 스캔 1.1초, 상위 DESIGN.md를 끄면 발견 2,325건이 1,197건으로 준다
박스 실측: 직접 만든 슬롭 페이지는 정적 18건·렌더 22건, 정돈된 페이지도 크림 배경으로 1건. 픽스처 227개 스캔 1.1초, 상위 DESIGN.md를 끄면 발견 2,325건이 1,197건으로 준다

② 직접 만든 ‘슬롭’ 페이지 vs ‘정돈된’ 페이지

슬롭 페이지에는 일부러 전형적인 티를 넣었다. Inter, 보라→파랑 그라데이션 제목(96px, 자간 −0.06em), 알약 라벨 “✨ Introducing Nimbus 2.0”, 보라 글로 버튼, 튕기는 cubic-bezier 이징, 왼쪽 4px 보라 테두리 카드 3개와 그 안의 중첩 카드, 그라데이션 아이콘 타일, 깜빡이는 초록 점, supercharge·seamless·enterprise-grade 같은 문구와 줄표. 정돈된 페이지는 세리프 본문·68ch 줄 길이·짙은 녹색 버튼 하나·구체적인 문구로 만들었다.

규칙 슬롭·정적 슬롭·렌더 1280 슬롭·렌더 390 정돈·정적 정돈·렌더
side-tab 3 3 3 0 0
nested-cards 0 3 3 0 0
gradient-text 2 1 1 0 0
ai-color-palette 1 5 5 0 0
dark-glow 2 1 1 0 0
hero-eyebrow-chip 1 1 1 0 0
overused-font 1 0 0 0 0
marketing-buzzword 1 0 0 0 0
bounce-easing 0 1 1 0 0
pulsing-dot 1 1 1 0 0
low-contrast 4 4 4 0 0
gray-on-color 1 0 0 0 0
skipped-heading 1 1 1 0 0
straggler 0 1 0 0 0
text-overflow 0 0 1 0 0
cream-palette 0 0 0 1 1
합계 18 22 22 1 1

결과는 세 가지로 요약된다. 첫째, 슬롭은 확실히 잡는다. 정적 18건, 렌더 22건으로 의도한 티 대부분이 걸렸고, 대비 계산은 “2.2:1 (need 4.5:1) — text #6b7280 on #452f7a”처럼 그라데이션 배경의 대표색까지 풀어 근거를 댔다. 둘째, 정적과 렌더가 잡는 규칙이 다르다. 중첩 카드·튕기는 이징·줄바꿈 낙오는 렌더에서만, 과다 사용 글꼴·마케팅 상투어·색 배경 위 회색은 정적에서만 나왔다. 렌더 스캔에서 Inter가 빠진 것은 박스에 Inter가 설치되어 있지 않아 대체 글꼴로 계산된 영향으로 보인다(추정). 모바일 폭(390×844)에서는 96px 제목이 text-overflow로 새로 걸렸다. 셋째, 정돈된 페이지도 크림 배경(#f6f4ef) 하나로 cream-palette 경고를 받아 종료 코드 2였다. 이걸 CI 게이트로 그대로 쓰면 의도한 브랜드 선택도 실패로 처리되니 무시 규칙 운영이 필수다. 렌더 스캔 시간은 슬롭 4,673ms, 정돈 2,470ms였다.

반대로 놓친 것도 있다. 아이콘 타일(icon-tile-stack), 거대한 h1(oversized-h1), 짓눌린 자간(extreme-negative-tracking), 줄표 남발(em-dash-overuse)은 어느 경로에서도 걸리지 않았다. 규칙마다 임계값이 있어(예: 줄표는 일정 밀도 이상) 짧은 데모 페이지에서는 조건을 채우지 못했을 수 있다. “검출기가 조용하다 = 슬롭이 없다”가 아니라는 점은 README도 “깨끗한 결과는 증거이지 증명이 아니다”라고 적어 두었다.

③ 문서와 릴리스의 어긋남, 그리고 표준 입력

README는 detect --list-rules(규칙 카탈로그 출력)와 --github(GitHub Actions 주석) 옵션을 안내하지만, 현재 릴리스 엔진 0.1.16의 detect --help에는 둘 다 없다. 커밋 기록을 보면 두 기능은 각각 2026-10-22 04:43 KST, 05:47 KST에 main에 들어갔고, 엔진 0.1.16은 그보다 앞선 2026-10-20 02:30 KST에 나왔다. 즉 README가 다음 릴리스를 앞서 설명하는 상태다. 또 0.1.16에서 대상 없이 --list-rules를 주고 표준 입력을 열어 두면 엔진이 표준 입력을 기다리며 멈췄다. 스크립트나 CI에서 부를 때는 </dev/null로 표준 입력을 닫거나 대상을 명시하는 습관이 안전하다.

텔레메트리와 네트워크 표면

동작 외부 통신 내용
파일·디렉터리 detect 없음 네트워크를 끊은 상태에서 정상 동작(실측)
디자인 훅 없음(엔진이 이미 있을 때) 오프라인에서 55ms·52ms로 동작(실측). 엔진이 없으면 첫 실행 때 런처가 내려받음 — Claude Code에서는 모델 도구 승인을 거부해도 훅이 내려받을 수 있다고 README가 경고
URL detect 대상 사이트 로컬 Chrome으로 페이지를 엶. 운영 사이트 검사용
install / update / check impeccable.style → GitHub 릴리스 스킬 ZIP·서명 다운로드. 오프라인이면 아무것도 설치하지 않고 실패(실측)
새 디자인 시작 시 ‘롤(roll)’ impeccable.style/api 시각 방향 카탈로그에서 ‘패’를 받는 기능 자체가 서버 요청. 텔레메트리를 꺼도 요청은 가고 X-Impeccable-Telemetry: off 헤더로 기록하지 말라고 알림
선택 핑(텔레메트리) impeccable.style/api/chosen 어떤 카드가 선택됐는지(카탈로그 id, 위치, 재추첨 회차, 클라이언트 버전). 프로젝트 이름·파일·코드·PRODUCT.md는 보내지 않는다고 명시. DO_NOT_TRACK·IMPECCABLE_NO_TELEMETRY·telemetry off로 차단

박스에서 impeccable telemetry status는 “telemetry: off (DO_NOT_TRACK is set). Rolls still work; the roll API is told not to record them”을 출력했다. 핵심은 검출기와 훅은 오프라인에서도 완결되고, 서버 통신은 설치·갱신과 ‘새 디자인 방향 고르기’ 흐름에 몰려 있다는 점이다. 사내 정책상 외부 통신이 민감하다면 검출기 중심으로 쓰고 "telemetry": false를 프로젝트 .impeccable/config.json에 커밋해 팀 전체를 끄는 방법이 문서화되어 있다.

보안·운영 체크포인트

항목 실제 동작 대응
라이브 모드의 셸 실행 복사 편집을 적용하면 package.json의 선택 스크립트 impeccable:manual-edit-validate를 사용자 권한으로 셸 실행 낯선 저장소에서는 라이브 모드 전에 해당 스크립트를 확인. 운영 사이트·HTTPS 배포본에는 주입 불가(공식 미지원)
하네스 훅의 자동 실행 Claude Code 명령 훅은 모델 도구 승인과 독립적으로 실행 무인 실행이면 훅을 검토하거나 --settings '{"disableAllHooks": true}'
바이너리 다운로드 런처는 SHA-256 사이드카, 설치기는 Ed25519 서명으로 검증, 실패 시 거부 사이드카와 바이너리가 같은 릴리스에서 오므로 GitHub 릴리스 자체 탈취까지 막지는 못함. 서명 키 목록은 바이너리에 고정
저장소 오염 .impeccable/questions/ 등 런타임 상태는 스스로 .gitignore를 만들어 커밋을 막음 이미 커밋된 파일은 git rm --cached 안내
용량 Claude+Codex 동시 설치 시 엔진 바이너리 사본 2개(폴더당 23MB) 모노레포·컨테이너 이미지 크기 고려. 서브모듈+link 방식이면 중복을 줄일 수 있음
확장 권한 Chrome 확장은 <all_urls> 호스트 권한 사내 브라우저 정책 검토 대상

비슷한 도구와 비교

도구 겨냥하는 문제 방식 Impeccable과의 관계
Impeccable AI 생성 UI의 ‘티’ + 일반 디자인 품질 스킬(지침) + 결정론 규칙 61개 + 훅 에이전트 루프 안에서 생성→검사→수정. 취향 규칙이 많아 예외 관리 필요
Anthropic frontend-design 스킬 에이전트의 프런트엔드 디자인 품질 지침 텍스트 중심 스킬 가볍고 단순. 결과를 기계적으로 다시 확인하는 검출기는 없음(Impeccable이 출발점으로 밝힌 스킬)
axe-core / Lighthouse 접근성(axe), 성능·접근성·SEO 감사(Lighthouse) 렌더된 DOM 대상 규칙 엔진·감사 표준 기반·업계 표준 도구. ‘보라 그라데이션’ 같은 미적 습관은 다루지 않음. 대비·제목 구조는 겹침
stylelint CSS 코드 스타일·오류 CSS 정적 린터 + 플러그인 규칙을 직접 정의할 수 있으나 렌더 결과·문구·AI 습관은 범위 밖
사람의 디자인 리뷰 브랜드·맥락·의도 판단 검출기가 놓친 임계값 아래의 문제와 ‘좋은 위반’을 구분. 대체 불가

현실적인 조합은 axe-core 같은 접근성 엔진을 기준선으로 두고, Impeccable 검출기를 ‘AI 습관 린터’로 얹는 것이다. 대비·제목 단계는 둘이 겹치므로 CI에서 두 번 실패하지 않게 한쪽을 advisory로 내리는 정리가 필요하다.

도입 판단: 이런 팀에 맞고, 이렇게 시작하라

상황 판단 이유·방법
코딩 에이전트로 UI를 자주 만든다 적합 훅만으로 편집 루프에 50ms대 검사가 붙는다. Stop 딥 패스가 있는 Claude Code·Codex·Grok Build에서 효과가 가장 크다
디자인 시스템(DESIGN.md)이 있다 적합, 단 범위 확인 design-system-* 규칙이 이탈을 잡는다. 하위 폴더 스캔 시 상위 DESIGN.md를 끌어오는지 --no-design-system과 비교해 확인
CI 품질 게이트로 쓰고 싶다 조건부 취향 규칙 예외를 먼저 정리하고, 처음엔 --json 결과를 기록만 하다가 규칙을 골라 실패 처리. 무시 규칙 변경은 리뷰 대상으로
외부 통신이 엄격히 제한된다 검출기 위주 설치는 서브모듈/수동 복사, 엔진은 사내 미러에 두고 IMPECCABLE_BIN 지정, 텔레메트리는 프로젝트 설정으로 차단
브랜드가 Inter·크림 팔레트 등 ‘슬롭 목록’과 겹친다 예외 등록 필수 ignores add-value에 이유를 남겨 의도를 문서화
# 1) 먼저 검출기만: 현재 상태를 기록
npx impeccable detect --json --no-design-system src/ > baseline.json </dev/null

# 2) 의도한 선택은 예외로 남기기
npx impeccable ignores add-value overused-font Inter --reason "Brand font"
npx impeccable ignores add-file "src/legacy/**"

# 3) 렌더 기준으로 한 번 더 (모바일 폭 포함)
npx impeccable detect http://localhost:3000 --viewport 390x844

# 4) 에이전트 훅 설치 (Codex는 이후 /hooks 에서 승인)
npx impeccable install -y --providers=claude,codex --scope=project

정리하면 Impeccable의 가치는 “AI가 디자인을 잘하게 만든다”는 큰 약속보다 “AI가 반복하는 실수를 기계적으로 짚어 다시 고치게 만든다”는 좁고 검증 가능한 루프에 있다. 박스 실측에서 그 루프는 빠르고(훅 50ms대, 픽스처 227개 1.1초) 오프라인에서도 돌았으며, 서명·해시 검증도 실패하면 멈추는 쪽으로 짜여 있었다. 반면 규칙의 상당수는 의견이고, 정적·렌더 경로가 서로 다른 것을 잡으며, 상위 DESIGN.md를 끌어오는 동작과 문서–릴리스 어긋남 같은 운영상의 모서리가 있다. 도입한다면 검출기를 먼저 기록용으로 돌려 팀의 예외 목록을 만든 뒤 훅과 게이트로 넓히는 순서를 권한다.