UI 감사 방법론
이 스킬은 무엇이 좋은 UI인지 말하지 않는다. 어떻게 재고, 어떻게 검증하고, 어떻게 기록하는지만 다룬다. 무엇을 문제로 볼지는 프로젝트가 정한다.
원칙은 하나다 — 인상으로 말하지 마라. "좀 AI 같네요"는 보고가 아니다.
rounded-xl 25회가 보고다.
두 가지 실패 모드
작업 전에 이것부터 읽어라.
- 없는 문제를 만들어낸다. 깨끗한 항목까지 지적해서 고칠 것을 지어낸다. 어떤 지표가 0이면 그건 빈칸이 아니라 지켜야 할 상태다
- 이미 내린 판정을 잊는다. 지난번에 "확인함, 문제 아님"으로 끝낸 항목이 다음 감사에 또 올라온다. 그래서 판정을 파일에 적는다
베이스라인이 먼저다
이 스킬 혼자서는 절반만 동작한다. 무엇이 정상인지 모르는 채로 숫자만 뽑게 된다.
<프로젝트>/.claude/ui-baseline.md
없으면 ../../references/BASELINE-TEMPLATE.md를 복사해서 채운다. 담기는 것은 넷이다.
- 이 앱의 정체 — 웹인가 데스크탑인가, 뷰포트가 고정인가, 테마가 몇 개인가
- 건드리면 안 되는 것 — 팔레트, 프레임워크 관례, 프로젝트 규칙이 정한 것
- 지표 목록 — 이 프로젝트가 무엇을 세기로 했는지, 그리고 감사 시점 → 현재 값. "현재" 열이 회귀 감지선이다
- 판정 기록 — "확인했고 문제 아님"으로 끝낸 항목, 근거, 재점화 조건
지표를 고르는 건 프로젝트의 몫이다. 이 스킬은 고르는 법이 아니라 세는 법을 준다.
1. 대상 파일 확인
명령이 무엇을 훑는지부터 정한다. 프레임워크마다 UI가 사는 확장자가 다르다.
for e in svelte vue jsx tsx astro html css scss; do
n=$(git ls-files "*.$e" | wc -l); [ "$n" -gt 0 ] && echo " .$e $n개"
done
아래 예시는 *.svelte다. 결과에 맞춰 --include를 바꿔 쓴다.
2. 세는 법 — 그리고 세 가지 함정
지표가 무엇이든 아래 함정은 똑같이 걸린다. 실제로 오측정이 나온 사례들이다.
함정 1 — 부분집합만 세고 전체라고 믿는다
크기·형태로 필터를 걸면 같은 문제의 다른 형태를 통째로 놓친다.
grep -rn "text-[45]xl" src --include=*.svelte # 큰 것만 → 9건
# 전수 조사 → 85건. 버튼 레이블과 상태 표시에 박힌 것이 전부 빠져 있었다
정량 지표를 만들 때는 먼저 필터 없이 전수를 세고, 그다음에 분류하라.
함정 2 — 정규식이 템플릿 문법을 먹는다
grep -rn "#[0-9a-fA-F]\{3,8\}" src --include=*.svelte # 14건 (오탐)
grep -rn "#[0-9a-fA-F]\{3,8\}\b" src --include=*.svelte # 2건 (실제)
\b가 없으면 Svelte의 {#each}가 #eac로 걸린다. Vue의 #default,
JSX의 #region 주석도 같은 방식으로 샌다. 경계를 명시하라.
함정 3 — 정상인 것까지 긁는다
grep -rn "\[[0-9]*px\]" src --include=*.svelte # 11건 — 레이아웃 치수 포함
grep -rn "text-\[[0-9]*px\]" src --include=*.svelte # 7건 — 폰트만
w-[260px] 같은 치수는 고정 크기 앱에서 정상이다. 무엇이 정상인지 모르면
지표가 아니라 소음을 센다. 그래서 베이스라인이 먼저다.
옵션 접미사를 놓치지 않기
grep -rho "rounded-[a-z0-9]*" src --include=*.svelte | sort -u # 4종
grep -rhoE "rounded(-[a-z0-9]+)?" src --include=*.svelte | sort -u # 5종
접미사 없는 형태(rounded, border, shadow)를 잡으려면 -E와 ?가 필요하다.
투명도·수식어 변형을 합산하지 않기
grep -rhoE "bg-accent/?[0-9]*" src --include=*.svelte | grep -c '^bg-accent$'
bg-accent/80 같은 변형까지 세면 21이 39가 된다. 호버 전용 클래스도 마찬가지다 —
평상시 화면에 안 보이는 것을 노출량에 넣으면 과다로 오판한다.
3. 렌더로 검증 (레이아웃·색이 걸릴 때만)
클래스 이름만 세는 감사면 건너뛴다. 레이아웃이 의심되거나 색이 실제로
적용되는지 확인해야 하면 ../../references/RENDER-VERIFICATION.md를 따른다.
거기 든 핵심 하나만 먼저 말하면 — 스크린샷을 근거로 레이아웃 버그를 주장하지 마라. OS 배율이 100%가 아닌 화면에서 창 크기대로 캡처하면 오른쪽이 잘려서 없는 오버플로가 보인다. 실제로 그렇게 오보한 사례가 있다.
스크린샷과 측정값이 어긋나면 측정값을 믿어라. 같은 코드가 브라우저에서 멀쩡한데 앱에서만 깨져 보이면 관측을 의심한다.
4. 보고
파일:줄 번호와 고칠 코드까지 낸다. "개선하세요" 같은 말은 쓰지 마라.
src/components/Card.tsx:63 transition-all
→ 색만 바뀌는 자리다. transition-colors
베이스라인의 "현재" 열과 대조해서 나아졌는지 나빠졌는지를 말한다. 절대값만 나열하면 판단할 근거가 없다.
5. 수정
승인 없이 고치지 마라. 사용자가 "고쳐"라고 하면 그때 편집한다.
한 커밋에 한 종류만. 반경 통일이면 반경만, 전환이면 전환만. 섞으면 되돌리기가 불가능해진다.
일괄 치환이 위험한 경우를 항상 확인하라 — 같은 클래스가 다른 이유로 쓰이는
자리가 있다. 예를 들어 transition-all 12건 중 5건이 진행바였고, 거기에
transition-colors를 걸었으면 애니메이션이 사라졌을 것이다.
수정 후 그 프로젝트의 타입 검사·빌드를 돌리고, 베이스라인의 "현재" 열을 갱신한다. 그게 다음 감사의 기준선이다.
6. 판정을 기록한다
"확인했고 문제 아님"으로 끝낸 항목은 근거와 재점화 조건까지 베이스라인에 적는다. 안 적으면 다음 감사에 똑같이 올라온다.
| 액센트 사용 | 77회 | 문제 없음 | 불투명 bg-accent가 21회 초과 시 |
근거는 숫자로 쓴다. "괜찮아 보임"이 아니라 "77회 중 27회가 호버 전용이라 평상시 노출은 50회".
이슈가 없으면
짧게 끝내라. 실패 모드 1번을 기억할 것.