'폰트 관련된 것도 스킬이 좀 잘 해줘야 하는데 그렇지 못한 것 같다'는 지적. 점검해보니 size-adjust, ascent-override, unicode-range, OpenType 기능, FOUT/FOIT, 폰트 라이선스가 스킬 어디에도 없었다. font-display 와 서브셋은 tokens.md 에 한 줄씩뿐이었다. references/typography.md 신설 - 고르는 절차: 개수를 먼저 정하고, 성격을 브리프에서 끌어내고, x-height·대비·웨이트 범위·숫자 형태를 실제로 재서 검증한다 - 가변 폰트: 축, 표준 속성 우선, 가변 축 애니메이션이 왜 게이트 8 위반인지 - 로딩: font-display 값별 선택 기준, preload 조건, unicode-range - 폴백 메트릭: size-adjust 와 override 3종. 재는 코드 포함 - OpenType: tabular-nums 등. font-variant-* 를 font-feature-settings 보다 먼저 - 한글: 동적 서브셋 원리, 웨이트가 라틴과 다르게 보이는 이유, 스택 순서 - 라이선스: 웹 임베딩 허용 여부가 상업 이용 허용과 다르다는 것 그리고 이 페이지가 그 규칙을 어기고 있었다 - 실측: 맑은 고딕이 Pretendard 보다 13.0% 넓다. 교체 순간 줄바꿈이 다시 잡힌다 - fonts.css 신설. OS 별로 폴백을 따로 정의하고 size-adjust 로 맞췄다 - 실측 차이 13.0% -> 0.0% preflight.md 에 폰트 검사 6개를 추가했다. 지금까지 하나도 없었다.
146 lines
7.3 KiB
Markdown
146 lines
7.3 KiB
Markdown
# 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 끄고 확인 | 콘텐츠가 여전히 보인다 |
|
||
|
||
**스크린리더를 실제로 켜볼 수 없다면** 최소한 소스의 읽기 순서를 확인해라. `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)
|