- Restore the step-0 interview as a mechanical gate the skill explicitly depends on; add harness.md (per-harness question tools, limits, fallbacks) and brief-interview.md (slots, question cards, rounds). - Add 10 reference docs absorbed from external design skills (accessibility, interaction-feel, elevation, color, icons, product-copy, component-systems, critique, change-review, print-email) and extend existing references. - Add a review-only route and two hard-gate clauses (truncated content reachability, three-flashes limit). - design-gate: split tap targets into WCAG 2.5.8 and 44px contract layers, run axe-core when available, and fix false positives found on a real site (decorative alt="", stacked wordmark line count, url-only pages). - lint-skill: fail if the interview gate section or its links disappear. - Ship agents/openai.yaml and THIRD_PARTY_NOTICES.md.
28 KiB
preflight — 출시 전 감사
5단계에서 읽는다. 자기 결과물을 남의 것처럼 본다. 통과 못 한 항목은 4단계로 돌아가 고친다.
슬롭 지문 검출과 자가 채점표는 references/antipatterns.md 에 있다. 이 문서는 그 외 전부를 다룬다.
0. 먼저 기계로 검사한다
무엇에 돌리는가부터 정해라.
- 정적 HTML/CSS 프로젝트 → 소스 그대로
- React·Vue·Astro 등 프레임워크 프로젝트 → 프로덕션 빌드 결과에 돌린다. 소스만 보면 렌더된 DOM 이 없어 대비·가로 스크롤·LCP 를 잴 수 없다.
pnpm build && pnpm preview로 띄우고 그 URL 을 검사해라 - 소스만 보고 "측정 불가"로 남기지 마라. 미측정은 통과가 아니다
grep 검사는 주석과 문자열을 제외해라. "100vh 금지"라고 쓴 주석이 '지원 범위의 뷰포트에서 의도하지 않은 가로 스크롤·겹침·조작 불능이 없다' 하드 게이트 검사에 걸리는 오탐이 실제로 나왔다.
사람 눈보다 정확하고 빠르다. 셋 다 돌려라.
A. 이펙트 전부 끄기
/* 임시로 주입해서 확인한다 */
*, *::before, *::after {
filter: none !important;
backdrop-filter: none !important;
animation: none !important;
transition: none !important;
transform: none !important;
}
canvas { display: none !important; }
이 상태에서 페이지가 여전히 읽히고 구조가 살아 있어야 한다. 무너지면 이펙트가 구조를 대신하고 있는 것이다. 4-1로 돌아가라.
B. 스타일 후보 grep
references/antipatterns.md의 grep 목록을 소스에 돌려 보라 CTA, 전체 대문자 헤드라인, 번호 매긴 단계 같은 반복 후보를 찾는다. 검출은 실패가 아니다. 프로젝트 계약·브리프·실제 렌더를 대조해 결정을 기록한다.
C. 카피 경쟁사 치환
브랜드가 특별하다고 주장하는 문구에만 제품·회사 이름을 경쟁사 이름으로 바꿔 읽는 진단 질문을 쓴다. 다른 업체에도 그대로 성립하면 근거와 구체성을 재검토한다. 수업·가격·대상·위치·FAQ·CTA 같은 안내는 치환만으로 실패시키지 않는다. 독자의 실제 질문에 대한 구체적 답, 검증 가능한 사실, 자연스러운 업종 표현을 먼저 확인한다.
낯선 업종이나 추상 표현의 용법이 불확실할 때만 공식 실제 사례를 소규모로 조사해 용어를 참고한다. 그 사례의 주장·실적·후기를 가져오지 않으며, 현재 프로젝트의 사실로 바꾸어 말하지 않는다.
D. 죽은 코드·토큰 위생 (design-gate 내장 검사)
- CSS 클래스가 HTML·JS 어디에도 등장하지 않으면 죽은 것이다. 컴포넌트를 없앨 때 HTML·CSS·JS 를 삼위일체로 지웠는지 대조한다(동적 클래스
is-${type}·seg-${n}처럼 조립되는 접두사는 게이트 설정의deadCssIgnore로 제외한다) - 토큰 파일이 있는데 다른 CSS 파일에 색 리터럴(hex·rgb)이 남아 있으면 실패다. 반지름 리터럴도 마찬가지 — 눈 검사로는 절대 전부 못 잡는다(실측: 8건의 상수색이 눈 검사를 통과했다)
theme-color메타가 실제 배경색과 다르면 낡은 토큰이다. 프리셋 전환에서 브랜드 표면(theme-color·파비콘·og:image)이 누락됐다는 뜻이다
E. 왼쪽 인셋 리듬 (모바일)
오버플로 검사는 오른쪽만 본다 — 왼쪽이 붙어 깨지는 결함은 통과한다(실측: 제목 16px·앱바·카드 24px 혼재가 게이트를 통과해 사용자 보고로 나왔다). 모바일 폭(320·390)에서:
- 화면의 모든 보이는 텍스트 시작점 ≥ 12px
- 헤더 텍스트·화면 제목·카드 텍스트가 같은 축(±10px)
- 측정은 전폭 컨테이너의 보더박스가 아니라 텍스트 시작점,
display:none요소(rect=0)는 제외하고
1. 접근성 — 타협 없음
| 항목 | 확인 방법 | 기준 |
|---|---|---|
| 키보드 도달 | Tab 만으로 순회 | 모든 인터랙티브 요소에 도달, 순서가 시각 순서와 일치 |
| 포커스 표시 | Tab 하며 눈으로 | 항상 보인다. outline: none 만 있고 대체가 없으면 실패 |
| 대비 | 측정 도구 (아래 주의) | 본문 4.5:1, 큰 글자·UI 3:1 |
| 이미지 대체텍스트 | 소스 확인 | 의미 있는 이미지에 alt, 장식은 alt="" |
| 폼 레이블 | 소스 확인 | 모든 입력에 연결된 <label>. placeholder 는 레이블이 아니다 |
| 제목 구조 | 개요 확인 | h1 하나, 건너뛰지 않음 |
| 모션 감소 | prefers-reduced-motion 켜고 확인 |
전부 끄는 게 정답이 아니다 — 위치 이동·시차·자동재생을 죽이고, 페이드·상태 변화는 남긴다 |
| 자동재생 | 확인 | 5초 이상 반복되는 애니메이션에는 정지 수단이 있다 |
| 캔버스/WebGL 실패 | JS 끄고 확인 | 콘텐츠가 여전히 보인다 |
| 네이티브 요소 | 소스 확인 | 이동은 <a href>, 액션은 <button>, 상태 없는 클릭 영역에 <div onClick>을 쓰지 않는다. 근거·예외는 accessibility.md [SKILL-BETTER-A11Y] |
| 아이콘 버튼 이름 · Label in Name | 소스 확인 | 텍스트 라벨 없는 버튼·링크는 aria-label 또는 숨김 텍스트 필수, 장식 아이콘은 aria-hidden="true". 보이는 라벨이 있으면 접근 가능한 이름이 그 텍스트를 포함한다 [WCAG-LABEL-NAME] [SKILL-WEB-A11Y] |
| 포커스 가림 | Tab 순회, 스티키 헤더·CTA 바 확인 | 포커스된 요소가 고정 바에 완전히 가려지지 않는다. scroll-margin-top을 헤더 높이 토큰에 연결 [WCAG-FOCUS-OBSCURED] |
| forced-colors | Windows 고대비 모드로 확인 | 강제 색상 모드에서도 컨트롤 경계·상태가 구분된다(Baseline: 2022-09~ 전 주요 브라우저 [WEB-BASELINE]). forced-color-adjust: none은 검증된 곳에서만 [SKILL-BETTER-A11Y] |
| 스킵 링크 · 랜드마크 | 첫 Tab, 소스 확인 | 반복 내비를 건너뛰는 링크가 첫 포커스 요소, 보이는 <main> 랜드마크 하나. 세부는 accessibility.md [SKILL-WEB-A11Y] [SKILL-BETTER-A11Y] |
| 키보드 위젯 패턴 | 실제 키보드 조작 | 탭·메뉴버튼·콤보박스·리스트박스·다이얼로그는 WAI-ARIA APG 패턴을 따른다. 세부는 accessibility.md [ARIA-APG] |
| 폼 — autocomplete·오류 | 소스·조작 확인 | autocomplete 값이 필드 의미와 맞고(무표시는 하드 게이트), 오류는 필드 옆에서 수정법을 말한다. 세부는 accessibility.md [WCAG-INPUT-PURPOSE] [SKILL-BETTER-A11Y] |
| [프로젝트 계약] 폼 — 제출 버튼 | 소스·조작 확인 | 제출 버튼은 요청 시작 전까지 비활성화하지 않으며, disabled와 aria-disabled를 구분해 쓴다. 세부는 accessibility.md [SKILL-BETTER-A11Y] |
| 상태 메시지 | 조작 후 확인 | 포커스 이동 없이 전달되는 상태 변화도 role·속성으로 보조기술에 전달된다. 라이브 리전 선택 기준은 accessibility.md [WCAG-STATUS] [SKILL-BETTER-A11Y] |
| 깜빡임 | 초당 프레임 확인 | 1초에 3회를 넘게 번쩍이거나 일반·적색 섬광 한계를 넘는 콘텐츠가 없다 [WCAG-FLASH] |
| 호버 콘텐츠 | 마우스오버 확인 | 호버·포커스로 나타나는 콘텐츠는 해제 가능·호버 가능·계속 보임 세 조건을 만족한다 [WCAG-HOVER] |
| 드래그 대안 | 조작 확인 | 드래그로만 되는 기능은 단일 포인터 조작(탭 등)으로도 된다. 예외는 필수 드래그·UA 기본 스크롤 [WCAG-DRAG] |
| 잘린 텍스트 도달 수단 | 소스·렌더 확인 | text-overflow: ellipsis 등으로 시각적으로 잘린 텍스트·표 셀·태그에는 title·툴팁·상세보기 같은 전체 값 도달 수단이 있다 [SKILL-BETTER-INTERFACE] |
| [프로젝트 계약] 비활성 · placeholder 대비 | 렌더 확인 | 비활성 컨트롤은 WCAG 대비 예외 대상이지만, 활성처럼 보여 사용자를 속이지 않을 만큼은 구분한다. placeholder는 라벨이 아니며 지나치게 옅어 읽을 수 없게 두지 않는다 [SKILL-BETTER-COLORS] |
이 표에 새로 더한 행은 비활성/placeholder 대비(별도 표시한 프로젝트 계약)를 빼면 모두 하드 게이트다. forced-colors 도 하드 게이트다 — 판정 근거는 accessibility.md §12. 대비가 실패로 나오면 수정 절차(색상환 고정·명도부터 조정)는 color.md를 따른다.
대비를 스크립트로 잴 때 — 반투명 배경을 불투명으로 계산하지 마라.
getComputedStyle(el).backgroundColor로 조상을 거슬러 올라가며 "투명이 아닌 첫 값"을 배경으로 쓰면,rgb(255 255 255 / 0.085)같은 유리 틴트를 순백으로 취급한다. 흰 글자가 1.15:1 로 나온다. 알파가 1 미만인 층은 계속 쌓고, 아래에서 위로 합성한 뒤에 재라:// 알파 < 1 이면 멈추지 말고 계속 쌓는다 const stack = []; let e = el; while (e && e !== document.documentElement) { const p = parse(getComputedStyle(e).backgroundColor); if (p && p[3] > 0) { stack.push(p); if (p[3] >= 1) break; } e = e.parentElement; } let [r, g, b] = rootBg; for (let i = stack.length - 1; i >= 0; i--) { const [sr, sg, sb, sa] = stack[i]; r = sr*sa + r*(1-sa); g = sg*sa + g*(1-sa); b = sb*sa + b*(1-sa); }유리·오버레이·틴트를 쓰는 페이지에서는 이 차이가 통과와 실패를 뒤집는다. 검사 도구가 틀리면 통과도 실패도 의미가 없다. 실패가 나오면 값을 고치기 전에 측정을 먼저 의심해라.
스크린리더를 실제로 켜볼 수 없다면 최소한 소스의 읽기 순서를 확인해라. order·position: absolute 로 시각 순서를 바꿨다면 읽기 순서가 어긋난다.
2. 성능 — 3단계에서 정한 예산과 대조
예산 값은 tokens.md §5 를 보라. 여기서 다시 적지 않는다 — 두 곳에 적으면 갈라진다.
이 문서가 하는 일은 실측을 채우는 것이다.
| 항목 | 실측 | 판정 |
|---|---|---|
| 히어로까지 JS (gzip) | ||
| WebGL/3D 추가분 | ||
| 총 전송량 (첫 화면) | ||
| 첫 인터랙션 (모바일 4G) | ||
| LCP | ||
| CLS | ||
| 폰트 파일 수 |
측정하지 않았으면 통과가 아니다. 예산을 넘겼다면 둘 중 하나다: 이펙트를 빼거나, 예산을 올린 이유를 명시하거나.
폰트 (typography.md §8 이 전체 목록)
- 웹폰트를 쓰면 실제 교체 시점의 레이아웃을 측정하고, 폴백 메트릭·
font-display전략을 선택했다. 특정 전략만으로 CLS 유무를 단정하지 않는다 - 폰트를 preload했다면 첫 화면에서 실제로 쓰이고 요청에 맞는
crossorigin이 있다 - 수치 비교가 필요한 곳의 숫자 정렬을 확인했다.
tabular-nums는 해당 서체의 지원과 과업에 맞춰 선택한다 - 한글 글꼴과 시스템 폴백을 실제로 확인했다. 웹폰트를 전송하는 경우 서브셋·전송량·글리프 범위를 검토했다
- 웹폰트를 임베딩하면 라이선스를 확인해
design.md에 적었다 - 웹폰트를 쓰면 폰트를 못 받은 상태로 열어봤다. 그 상태로도 읽힌다
자주 걸리는 것
- 전송하는 폰트의 크기·글리프 범위 미측정. 한글 웹폰트는 필요한 범위와 라이선스에 맞춰 서브셋을 검토한다
- 첫 화면 밖 이미지에
loading="lazy"누락 - 3D/WebGL을 초기 번들에 포함 (뷰포트 진입 시 동적 import 해야 한다)
- 애니메이션이
top/left/width를 건드림 →transform·opacity로 가능한지 먼저 검토하고, 유지한다면 비용·CLS·입력 간섭·감소 모션을 측정해 예산과 대조한다 will-change남발 → 레이어가 늘어 오히려 느려진다
3. 반응형
- 프로젝트가 채택한 회귀 매트릭스에서 가로 스크롤 없음. 이 저장소의 기본 매트릭스는 320·390·768·1440·1920·2560px이며, 지원 기기·브리프가 다르면 그 계약을 바꾸고 이유를 기록한다
- 변경 영향에 따라 프로젝트가 채택한 뷰의 너비×높이, 짧은 화면, 긴 세로 흐름, 뷰포트 종횡비·피사체 보존·실제 clipping, 글자 확대를 추가로 검사한다. 크롬·모달·긴 폼·고정 CTA는 짧은 화면의 가시 영역과 scroll owner를, 목록·본문·이미지는 긴 세로 흐름과 피사체 보존을, 글꼴·카피·컨트롤은 지원 확대 상태를 잰다. 모션 상태와 clipping의 상세 계약은 렌더 측정 계약을 따른다
- 크롬(탑바·앱바·툴바)에 컨트롤을 더했다면 그 줄의 최소폭 합을 가장 좁은 폭에서 다시 잰다 — 버튼 하나가 320px를 뚫는 사고가 반복된다(실측: 인쇄 버튼 1개로 +18px). 줄이 넘으면 감싸기(2행 랩)가 기본 수습이다
- 프로젝트 회귀 매트릭스의 각 폭에서 실제 브라우저 렌더를 잰다. 기본 매트릭스(320·390·768·1440·1920·2560px)는 저장소의 회귀 범위이며 WCAG의 보편 폭 기준은 아니다. 최소 폭의 오버플로와 wide 화면의 카피 측정폭·제목 칼럼을 함께 확인한다
- WCAG 200% 확대 또는 운영체제의 실제 글꼴 확대가 지원 범위라면 실제 브라우저·기기에서 별도 검증한다. gate의 font-scale 행렬은 회귀 신호이며 px 고정 폰트의 OS 확대를 대체하지 않는다
- 1920px 이상에서는 본문 측정폭을 유지하고, 표·도면·작업대처럼 정보 밀도가 필요한 표면만 별도의
--container-wide로 넓힌다. 같은max-width를 전부 풀어 넓은 화면을 빈 종이로 만들지 않는다 - 분할 히어로는 1920·2560에서
hero / copy / media / 다음 정보 레일rect를 기록했다. 사진의 최대 폭과 카피의 최소 폭을 페이지 토큰으로 정하고, 단지 viewport를 반으로 나눈1fr 1fr가 사진을 무제한 키우지 않는지 확인한다 - hero 검증만으로 text-media 분할 검증을 끝내지 않는다. 과정·추천·가맹처럼 DOM/여백 규칙이 다른 모든 분할 표면에서 rail·copy·media·제목의 실제 rect와 줄 수를 기록한다. wide override가 있다면 기존
padding-left/right: calc(100vw …)를 양쪽 모두 재설정했는지, 상위max-width의 선택자 우선순위가 named stage를 다시 줄이지 않는지 확인한다 - 중간 뷰포트(768~1024px)에서 레이아웃이 깨지지 않음 — 가장 자주 빠뜨리는 구간
- 터치 타깃: 버튼·아이콘·카드 등 독립 컨트롤은 44×44px 이상(Apple/Google 권고)
- 터치 타깃: 본문 안 인라인 텍스트 링크는 24×24px 이상 — 이 스킬의 프로젝트 계약(
inlineTargetMin24px)이다. WCAG 2.5.8은 문장 속 인라인 링크를 예외로 둔다. 여기에 44 를 요구하면 정상적인 내비 링크가 오탐된다 - 컨트롤의 내용 여백: 버튼 라벨·입력값·select 표시·표 셀의 실제 렌더 글자가 테두리에 닿지 않는다. 이 저장소의 실렌더 기본값은 좌우 8 CSS px 이상이다. 이는 WCAG 적합성 수치가 아니라 검증 가능한 시각 품질 기본값이며, 아이콘 전용·체크박스·의도적인 데이터 정렬은 별도 근거를 적는다
- 폼 기하: 연결된 label/name/autocomplete를 확인한 뒤 실제 렌더 rect로 입력끼리 겹치지 않는지 잰다. 좁은 폭에서는 필드를 세로로 쌓고, label·입력·오류 문장이 서로의 클릭/읽기 영역을 침범하지 않게 한다
- 표와 표처럼 보이는 flex/grid: 데이터 관계에는
th/td와scope를 쓰고, 모든 가시 셀에 좌우 읽기 여백을 둔다. 좁은 폭에서 스크롤·카드화로 형식이 바뀌어도 헤더-값 관계가 남아야 한다 - 호버로만 접근되는 기능 없음
- 긴 단어/URL이 넘치지 않음 (
overflow-wrap: anywhere) - 가로 모드에서 첫 화면이 잠기지 않음
근거: W3C WCAG 2.5.8 Target Size (최소 24 CSS px/간격 예외), Apple HIG Layout (읽기 폭·음의 공간·다양한 화면 크기), Apple HIG Text Fields (일관된 필드 폭·간격·세로 배치), W3C Tables Tutorial (반응형에서도 데이터 관계 보존), NN/g Form White Space (인접 요소의 간격이 관계를 전달함). 조사일 2026-08-30.
4. 콘텐츠
- 히어로가 무엇인지 말한다. 형용사만 있고 명사가 없으면 실패
- 로렘입숨이 남아 있지 않다
- 실제 콘텐츠 길이로 테스트했다 (짧은 제목만으로 맞춘 레이아웃은 긴 제목에서 깨진다)
- 빈 상태·오류 상태·로딩 상태가 있다
- 링크가 어디로 가는지 텍스트만 보고 알 수 있다 ("여기를 클릭" 금지)
- 이미지가 없거나 실패했을 때 레이아웃이 무너지지 않는다(
aspect-ratio지정)
4-1. 상태 완결성 — 동작하는 화면의 빈틈
정적 마케팅 페이지에는 없는 검사다. 입력·파괴·열림이 있는 화면(폼·콘솔·앱)은 네 가지를 갖춰야 프로덕션이다. 실제로 조작해 본다 — 눈으로 봐서는 안 보인다(실측: 범위 밖 101점이 조용히 평균에 반영되고 있었다).
- 수치 입력에는 범위가 있다 — 범위 밖 값은 인라인 오류로 이유를 말하고 제출을 막는다(
aria-invalid). 스트랩 검증만 믿지 마라:type="number"의min/max는 직접 입력을 막지 못한다 - 판정은 순수 함수다 — 가능/불가+사유의 판정 로직은 UI 핸들러에 두지 않고
calc.js같은 모듈로 추출해 단위 테스트(L1)가 같은 판정을 공유하게 한다. UI 는 판정 결과를 문장으로 번역만 한다. 실행취소의 재심사도 같은 함수를 쓴다 - 파괴적 행동에는 되돌림이 있다 — 삭제·취소는 실행취소 또는 확인. 되돌리기가 확인보다 낫다(흐름이 끊기지 않는다). 재신청·복원은 원래 판정 함수로 다시 심사한다 — 사이에 끼어든 다른 변화가 있으면 정당하게 막혀야 한다
- 열리는 것은 Esc 로 닫힌다 — 모달만이 아니다. 드롭다운·팝오버·알림 메뉴도. 닫힐 때 포커스는 연 요소로 돌아간다
- native
<dialog>또는 동등 모달은 전역 reset 뒤에도position: fixed; inset: 0; margin: auto와 viewport 상한/내부 scroll owner를 가진다. 390·1440·2560에서 중심점, 화면 안 rect, 배경 scroll lock을 실제로 단언한다. W3C의 modal dialog 키보드·포커스·닫기 계약을 따른다: WAI-ARIA APG, MDN dialog - [프로젝트 계약] 모달 액션 행은 스크롤 영역과 분리된 스티키 푸터에 둔다 — 콘텐츠가 스크롤되어도 확인·취소 같은 핵심 액션은 항상 보인다. 리사이즈 가능한 패널 바닥이나 고정 높이 모달의 폴드 아래처럼 잘릴 수 있는 자리에 크리티컬 액션을 두지 않는다 [SKILL-BETTER-LAYOUT]
- 로딩 상태는 실제 비동기에만 — 동기 인라인 데이터에 스켈레톤을 붙이는 건 저장을 흉내내는 것이다. 없는 지연을 만들지 마라
- [프로젝트 계약] 변형 상태 매트릭스 — 새 컴포넌트·variant는 hover·focus·active·disabled·loading·selected 여섯 상태를 갖추었는지 표로 확인한다. 일부 상태만 구현하고 넘어가는 것이 가장 흔한 누락이다 [SKILL-INTERFACE-REVIEW]
- [프로젝트 계약] 오류·빈 상태 문구는 "존재"만으로 충분하지 않다 — 무엇이 잘못됐는지·어떻게 고치는지를 비난하지 않는 톤으로 말하는 내용 기준은 product-copy.md를 따른다 [SKILL-BETTER-WRITING]
- [하드 게이트] 낙관적 업데이트는 실패하면 되돌린다 — 즉시 반응이 필요한 저위험 토글(좋아요·북마크 등)에 낙관적 업데이트를 쓸 때는 실패 시 같은 판정 함수로 원상 롤백하고, 실패를 토스트·인라인 오류로 알린다. "판정은 순수 함수다"(위) 원칙과 연결된다 [SKILL-INTERACTION-DESIGN](근거: SKILL.md 하드 게이트 5 — 실패를 성공으로 남기지 않는다)
- [프로젝트 계약] 제스처·모션은 실제로 조작해 QA한다 — 커스텀 컨트롤의 제스처 QA는 interaction-feel.md §11, 모션 QA(배속 재생·프레임 단위 점검)는 motion.md §5를 따른다 [SKILL-EMIL-DESIGN-ENG] [SKILL-IMPECCABLE]
4-2. 진실 완결성 — 가상·예시·AI·규제 화면
가상 브랜드·예시 데이터·AI 분석·규제 주제를 실제 서비스처럼 보이게 만든 화면에만 돈다. 전역 데모 띠 하나로 끝내지 않는다. 상세 설계는 trustworthy-showcases.md.
- 모든 숫자·주소·상태·추천이 사실 / 예시 / 추론 / 미정 중 하나이고
USER_SELF_REPORT / VERIFIED_SOURCE / SYSTEM_STATE / SYNTHETIC_FIXTURE출처 계층이 추적된다. 자기보고 값 자체를 검증 사실로 승격하지 않았다 예시 가격,거래 불가,실제 접수 아님,연출 이미지라벨이 오해가 생기는 범위 가까이에 있다. 같은 상태·출처·행동 가능성을 공유하는 자식은 가장 가까운 공통 부모가 한 번 소유하고, 다른 자식만 예외 라벨을 가진다- 검증하지 않은 수익·가맹비·매장 수·등록번호·연락처를 만들지 않았다. 모르면
미정이다 - AI 결과에 입력 조건·출처가 붙은 입력/검증 사실·추론·불확실/누락·수정·사람 검토가 있고, 입력을 바꾸면 결과와 근거가 함께 바뀐다. 모델 출력 내용을
SYSTEM_STATE사실로 두지 않았다 - 진단·개인화 추천·예약·전송·거래·게시·내보내기 등 실제 규제 행동은 행동별 필수 검증이 없을 때 실패 폐쇄형이며, 미등록 행동은 기본 거절되고 막힌 이유가 화면에 보인다
- 민감 입력과 파생값의 영속 저장·쿠키·분석 이벤트 포함·네트워크 전송 경계를 E2E로 검증했다
- 공개 화면은 사용자 해석·제한·다음 행동을, 관리자는 내부 원장·검증 이벤트·채널 판정·감사 로그를 소유한다. 사용자 행동에 영향을 주는 제한을 관리자에만 숨기지 않았다
- 지도·차트·도식의 같은 정보가 DOM 목록·표·설명으로도 제공되고 데이터 원천이 하나다
- 생성 이미지는 가격·주소·점수의 증거로 쓰이지 않으며, 프로젝트가 채택한 모바일 뷰와 종횡비에서 핵심 피사체가 첫 화면의 의도와 맞는다
- URL별 390·1440 기본 화면과 핵심 입력/오류/모달 상태 캡처를 실제로 열어 보고 시각 PASS/RED를 따로 기록했다
4-3. 썸네일·OG 캡처 — 움직이는 화면을 대표하지 않는다
썸네일은 '페이지가 열렸다'는 증거가 아니라 사람들이 처음 보는 정지된 브랜드 표면이다. 로딩 중인 폰트, 이미지 디코드 전 프레임, 입장 모션 중간, 다음 WebGL 프레임을 파일로 남기면 정상 사이트도 카드에서 망가져 보인다.
file://즉시 캡처 대신 실제 배포와 같은 상대 URL을 해석하는 로컬 HTTP 서버에서 고정 viewport로 연다. 로컬 4xx, runtime error,naturalWidth === 0이미지는 캡처 성공이 아니라 실패다document.fonts.ready와 모든 가시 이미지의decode()를 기다린 뒤, 페이지별로 정한 bounded settle 시간을 지난다.document.fonts.ready는 사용 중인 폰트의 로드와 레이아웃 작업이 끝날 때 이행한다- 캡처 환경은
prefers-reduced-motion: reduce를 에뮬레이션하고, 영상·오디오는 정지하며 CSS/WAAPI 애니메이션과 rAF 기반 canvas를 정착한 한 프레임에 멈춘다.animation: none으로 초기 상태를 되돌려 빈 화면을 만들지 말고, 실제로 완성된 프레임을 pause/finish 한다 - 기본 컷·모달/결과 컷·OG 모두 같은 계약으로 찍고, 파일의 규격·0바이트·해시 중복을 검사한 뒤 적어도 움직임이 있던 대표 컷을 눈으로 연다. 생성 이미지가 있으면 기존 진실 라벨 계약도 그대로 보존한다
근거: MDN
Document.fonts(ready는 사용 중인 폰트의 로드와 레이아웃 완료 뒤 이행), MDNHTMLImageElement.decode(), MDNprefers-reduced-motion(불필요한 모션을 줄이거나 대체하는 사용자 선호). 조사일 2026-08-30.
5. 디자인 자체
기계로 못 잡는 부분이다. 정직하게 답해라.
첫인상·실제 과업 행동·접근성 적합성·전문가 시각 검토가 필요한 경우, design foundations의 평가 절차를 읽고 각 결과를 분리해 기록한다.
- 이 사이트를 다른 회사의 것으로 바꿔도 그대로 쓸 수 있는가? → 그렇다면 브리프에 맞춘 것이 없다
- 2단계에서 정한 한 문장 컨셉이 화면에서 보이는가? → 안 보이면 컨셉이 문서에만 있는 것이다
- 감수하기로 한 리스크가 실제로 들어갔는가? → 구현 중에 안전한 쪽으로 후퇴하지 않았는지
- 사용한 레퍼런스의 원칙이 브리프와 렌더 결과에 맞게 번역됐는가? → 슬롯 수나 업종 차이 자체로 판단하지 않는다
- 강조색·radius·정렬·반복이 프로젝트 토큰과 과업에 맞는가?
- 여백이 의도적인가, 남은 것인가?
- 감수하기로 한 리스크는 몇 개이고, 하나로 압축할 수 있는가? → 여러 개를 동시에 감수했다면 서로 상쇄해 사실상 아무 것도 감수하지 않은 것과 같다 [SKILL-FRONTEND-DESIGN]
반사실 제네릭 점검("이 선택이 다른 업종의 브리프에도 그대로 나왔을 것인가")은 2단계(방향 결정)에서 먼저 하고 design.md에 기록한다. 여기서는 그 결정이 구현 중 안전한 쪽으로 후퇴하지 않았는지만 다시 본다.
6. 최종 게이트
전부 통과해야 끝난다.
- 0장 기계 검사 4종 통과
- 접근성 표 전 항목 통과
- 성능 예산 내 (또는 초과 이유 명시)
- 반응형 체크리스트 통과
- 콘텐츠 체크리스트 통과
- 상태 완결성(§4-1) — 입력 검증·되돌림·Esc 를 실제 조작으로 확인
- 해당하면 진실 완결성(§4-2) — 예시·AI·규제·생성 이미지의 오해 경로를 실제 상태로 확인
- 정적 CSS/JS의 stable URL을 바꿨다면 HTML 링크와
@import의 버전을 함께 올렸고, 공개 CDN에서 실제 내려온 stylesheet URL과 새 토큰/규칙을 확인했다. HTML만 cache-bust하고 CSS가 이전 버전이면 배포 성공이 아니다 - 기능·접근성 자동 검사의 결과와 시각 평가(위계·브랜드·타입·구도·이미지·리듬)의 결과를 별도로 기록했다. 한쪽 PASS를 다른 쪽 PASS로 바꾸어 말하지 않았다
- 5장 여섯 질문과
antipatterns.md검토를 프로젝트 계약·실제 렌더 근거로 기록했다
하나라도 실패하면 출시가 아니라 4단계 복귀다.
근거: research/references/04-ai-slop-signatures.md, research/motion/01-principles.md, research/three/04-performance.md (조사일 2026-08-20)