designpaca/packages/skill/references/preflight.md
Yun Chan 9648d1d82a 소개 페이지를 스킬 전체 경로로 다시 만들고, 배운 것을 스킬에 반영
방향을 글래스로 바꿀 때 2단계 재결정을 하고도 전체 경로로 올리지 않았다.
레퍼런스 없이 재질만 갈아끼운 결과가 스위스 미니멀 뼈대에 유리를 바른
페이지였고, design.md 는 초판 결정을 그대로 담고 있었다. 0단계부터 다시 돌았다.

1단계 — 레퍼런스 3개를 computed style 까지 실측
  R1 zed.dev      컨테이너 1120px 과 전체폭이 교대 · radius 2px 621회
  R2 lusion.co    3D 는 액자 안, 텍스트는 액자 밖 · 배경 흰색 · h1 36px
  R3 Codrops      DOM 이 구조를 소유하고 WebGL 은 uniform 만 만진다

2단계 — 프리셋 swiss-minimal → dark-instrument, 컨셉 "검사대 위의 물체"
        유리는 액자에만 남긴다(헤더 · 검사대 · 명령창)

4단계 — 히어로 재구성. 캔버스를 배경에서 빼 액자 안으로, 텍스트는 밖으로
        판독기가 통과한 게이트를 표시한다(값이 바뀔 때만 DOM 을 쓴다)
        파이프라인을 2열로 열어 625px → 1113px

5단계에서 실제로 걸린 것
  게이트 3  radius 4종 → 2종 (3px / 14px, pill 제거)
  게이트 1  base.css 토큰 밖 rgb() 7곳 → 토큰
  게이트 7  헤더 English 2.59:1 → ink 로 상향
  카운트    히어로 h1 4줄 → 2줄
  셰이더    판이 정면이라 프레넬이 구조적으로 0. 법선을 굽히고 UV 로 테두리
  셰이더    gl_FragCoord 를 렌더 타겟 크기로 나눠 UV 가 1 을 넘고 있었다
  수치      페이지가 실은 "타입 단계 5단계"가 실측 9종이었다. lang 속성이
            스케일을 재정의해 링크 하나가 16px 로 새고 있었다
  측정      대비 스크립트가 반투명 배경을 불투명으로 계산했다. 알파 합성으로 교정

스킬 반영
  three.md    §0-A 배치 원리(3D 는 액자 안) · 프레넬 0 함정 · gl_FragCoord 함정
  preflight.md 대비 측정 시 알파 합성. 검사 도구가 틀리면 통과도 의미가 없다

최종: 하드 게이트 12/12, 대비 실패 0, 320px 오버플로 0, 테스트 22개 통과
2026-08-20 13:33:28 +09:00

169 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# preflight — 출시 전 감사
5단계에서 읽는다. **자기 결과물을 남의 것처럼 본다.** 통과 못 한 항목은 4단계로 돌아가 고친다.
슬롭 지문 검출과 자가 채점표는 `references/antipatterns.md` 에 있다. 이 문서는 **그 외 전부**를 다룬다.
---
## 0. 먼저 기계로 검사한다
**무엇에 돌리는가부터 정해라.**
- 정적 HTML/CSS 프로젝트 → 소스 그대로
- **React·Vue·Astro 등 프레임워크 프로젝트 → 프로덕션 빌드 결과에 돌린다.** 소스만 보면 렌더된 DOM 이 없어 대비·가로 스크롤·LCP 를 잴 수 없다. `pnpm build && pnpm preview` 로 띄우고 그 URL 을 검사해라
- **소스만 보고 "측정 불가"로 남기지 마라.** 미측정은 통과가 아니다
grep 검사는 **주석과 문자열을 제외**해라. "100vh 금지"라고 쓴 주석이 게이트 #9 에 걸리는 오탐이 실제로 나왔다.
사람 눈보다 정확하고 빠르다. 셋 다 돌려라.
### A. 이펙트 전부 끄기
```css
/* 임시로 주입해서 확인한다 */
*, *::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, 전체 대문자 헤드라인, 번호 매긴 1·2·3 단계)부터.
### C. 카피 경쟁사 치환
제품명을 경쟁사 이름으로 바꿔 읽는다. **문장이 그대로 성립하면 그 카피는 아무것도 말하지 않았다.** 히어로 문구부터 검사한다.
---
## 1. 접근성 — 타협 없음
| 항목 | 확인 방법 | 기준 |
|---|---|---|
| 키보드 도달 | Tab 만으로 순회 | 모든 인터랙티브 요소에 도달, 순서가 시각 순서와 일치 |
| 포커스 표시 | Tab 하며 눈으로 | 항상 보인다. `outline: none` 만 있고 대체가 없으면 실패 |
| 대비 | 측정 도구 (아래 주의) | 본문 4.5:1, 큰 글자·UI 3:1 |
| 이미지 대체텍스트 | 소스 확인 | 의미 있는 이미지에 alt, 장식은 `alt=""` |
| 폼 레이블 | 소스 확인 | 모든 입력에 연결된 `<label>`. placeholder 는 레이블이 아니다 |
| 제목 구조 | 개요 확인 | h1 하나, 건너뛰지 않음 |
| 모션 감소 | `prefers-reduced-motion` 켜고 확인 | **전부 끄는 게 정답이 아니다** — 위치 이동·시차·자동재생을 죽이고, 페이드·상태 변화는 남긴다 |
| 자동재생 | 확인 | 5초 이상 반복되는 애니메이션에는 정지 수단이 있다 |
| 캔버스/WebGL 실패 | JS 끄고 확인 | 콘텐츠가 여전히 보인다 |
> **대비를 스크립트로 잴 때 — 반투명 배경을 불투명으로 계산하지 마라.**
> `getComputedStyle(el).backgroundColor` 로 조상을 거슬러 올라가며 "투명이 아닌 첫 값"을 배경으로 쓰면,
> `rgb(255 255 255 / 0.085)` 같은 유리 틴트를 **순백**으로 취급한다. 흰 글자가 1.15:1 로 나온다.
> 알파가 1 미만인 층은 계속 쌓고, **아래에서 위로 합성**한 뒤에 재라:
>
> ```js
> // 알파 < 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: optional` 을 골랐다.** 둘 다 안 했으면 폰트가 교체되는 순간 레이아웃이 튄다
- [ ] preload 한 파일이 첫 화면에 실제로 쓰인다. `crossorigin` 이 있다
- [ ] 수치를 나열하는 곳에 `tabular-nums` 가 있다
- [ ] 한글 폰트를 명시했고 서브셋을 쓴다
- [ ] 웹폰트 임베딩 라이선스를 확인해 `design.md` 에 적었다
- [ ] **폰트를 못 받은 상태로 열어봤다.** 그 상태로도 읽힌다
### 자주 걸리는 것
- 폰트 서브셋 안 함 (한글 전체 폰트는 수 MB)
- 첫 화면 밖 이미지에 `loading="lazy"` 누락
- 3D/WebGL을 초기 번들에 포함 (뷰포트 진입 시 동적 import 해야 한다)
- 애니메이션이 `top`/`left`/`width` 를 건드림 → `transform` 으로 바꿔라
- `will-change` 남발 → 레이어가 늘어 오히려 느려진다
---
## 3. 반응형
- [ ] **320px** 폭에서 가로 스크롤 없음 (하드 게이트 #5 는 320~1920px 전 구간을 요구한다. 375px 만 보면 그 아래가 뚫린다)
- [ ] 1920px 이상에서 콘텐츠가 늘어지지 않음(최대 폭 제한)
- [ ] 중간 뷰포트(768~1024px)에서 레이아웃이 깨지지 않음 — **가장 자주 빠뜨리는 구간**
- [ ] 터치 타깃: **버튼·아이콘·카드 등 독립 컨트롤은 44×44px 이상**(Apple/Google 권고)
- [ ] 터치 타깃: **본문 안 인라인 텍스트 링크는 24×24px 이상**(WCAG 2.5.8 AA). 여기에 44 를 요구하면 정상적인 내비 링크가 오탐된다
- [ ] 호버로만 접근되는 기능 없음
- [ ] 긴 단어/URL이 넘치지 않음 (`overflow-wrap: anywhere`)
- [ ] 가로 모드에서 첫 화면이 잠기지 않음
---
## 4. 콘텐츠
- [ ] 히어로가 **무엇인지** 말한다. 형용사만 있고 명사가 없으면 실패
- [ ] 로렘입숨이 남아 있지 않다
- [ ] 실제 콘텐츠 길이로 테스트했다 (짧은 제목만으로 맞춘 레이아웃은 긴 제목에서 깨진다)
- [ ] 빈 상태·오류 상태·로딩 상태가 있다
- [ ] 링크가 어디로 가는지 텍스트만 보고 알 수 있다 ("여기를 클릭" 금지)
- [ ] 이미지가 없거나 실패했을 때 레이아웃이 무너지지 않는다(`aspect-ratio` 지정)
---
## 5. 디자인 자체
기계로 못 잡는 부분이다. **정직하게 답해라.**
1. **이 사이트를 다른 회사의 것으로 바꿔도 그대로 쓸 수 있는가?** → 그렇다면 브리프에 맞춘 것이 없다
2. **2단계에서 정한 한 문장 컨셉이 화면에서 보이는가?** → 안 보이면 컨셉이 문서에만 있는 것이다
3. **감수하기로 한 리스크가 실제로 들어갔는가?** → 구현 중에 안전한 쪽으로 후퇴하지 않았는지
4. **1단계 레퍼런스 R2(다른 업종의 톤)의 흔적이 있는가?** → 없으면 결국 R1을 베낀 것이다
5. **강조색이 하나인가?**
6. **여백이 의도적인가, 남은 것인가?**
---
## 6. 최종 게이트
전부 통과해야 끝난다.
- [ ] 0장 기계 검사 3종 통과
- [ ] 접근성 표 전 항목 통과
- [ ] 성능 예산 내 (또는 초과 이유 명시)
- [ ] 반응형 체크리스트 통과
- [ ] 콘텐츠 체크리스트 통과
- [ ] 5장 여섯 질문에 정직하게 답했고, 실패 항목을 고쳤다
- [ ] `antipatterns.md` 자가 채점표 통과
**하나라도 실패하면 출시가 아니라 4단계 복귀다.**
> 근거: research/references/04-ai-slop-signatures.md, research/motion/01-principles.md, research/three/04-performance.md (조사일 2026-08-20)