446 lines
35 KiB
Markdown
446 lines
35 KiB
Markdown
# antipatterns.md — 점검 후보
|
||
|
||
AI가 만든 티는 **못 만들어서** 나는 게 아니라 결정을 설명·검증하지 않을 때 난다.
|
||
보라 그라디언트, Inter, 3열 아이콘 카드, `rounded-2xl shadow-lg`, "Get Started"는 반복될 수 있는 출발점이다. 존재만으로 미결정이라고 단정하지 않고, 브리프·프로젝트 계약·실제 렌더로 판단한다.
|
||
|
||
프리플라이트에서 이 문서를 훑어 후보를 찾는다. 검출은 실패가 아니다. 브리프·프로젝트 계약·실제 렌더를 대조해 유지·수정·제거를 결정하고 그 근거를 남긴다.
|
||
|
||
---
|
||
|
||
## 0. 먼저 보는 반복 후보
|
||
|
||
원자료와 재현 가능한 표본이 없는 빈도 수치는 규칙의 근거가 될 수 없다. 아래 항목은 흔한 기본값을 찾는 검색 후보이며, 색·대문자·번호가 존재한다는 사실만으로 실패가 아니다.
|
||
|
||
| 후보 | 확인할 질문 |
|
||
|---|---|
|
||
| 보라·인디고 CTA | 브랜드 팔레트·상태 구분·대비·목표 행동을 설명하는가? |
|
||
| 전체 대문자 라벨 | 언어·가독성·정보 위계에 맞는가? |
|
||
| 번호 매긴 단계 | 사용자가 실제 순서로 수행하는 과업인가? |
|
||
|
||
---
|
||
|
||
## 1. 컬러
|
||
|
||
다크·그라디언트·강한 색은 그 자체로 실패가 아니다. 화면 역할, 브랜드, 대비, 실제 기기 렌더에서 이유를 설명할 수 있는지 점검한다.
|
||
|
||
| 지문 | 왜 문제 | 대신 |
|
||
|---|---|---|
|
||
| **다크 모드를 브리프 근거 없이 기본값으로** (`bg-slate-900`, `#0B0B0F`) | 대상 환경·브랜드·콘텐츠에 맞는지 설명하지 못하면 선택이 기본값처럼 보일 수 있다 | 라이트·다크의 역할 토큰, 실제 기기 대비, 사용자 설정·테마 전환 필요성을 비교한다 |
|
||
| **보라→파랑 그라디언트 히어로** (`from-purple-600 to-blue-500`, `#6366f1→#a855f7`) | 제품·브랜드·정보 역할과 무관하면 배경 장식만 남을 수 있다 | 단색·동일 hue 변화·다중 hue를 같은 콘텐츠에서 비교하고, 텍스트 대비와 행동 위계를 확인한다 |
|
||
| **라벤더 퍼플이 어디에나** (`#a78bfa`, `#c4b5fd`) | 맥락 없는 반복은 기본값처럼 보일 수 있음 | 브랜드·접근성·표면 역할을 설명하고 실제 렌더에서 위계를 확인 |
|
||
| **네온 온 다크** — 시안(`#22d3ee`)·바이올렛이 검정 위에서 발광 | 색의 의미·대비·주변광에서의 읽기 비용을 확인해야 한다 | 상태·행동·콘텐츠 역할과 연결하고, 저채도/고채도·명도 대비를 실제 기기에서 비교한다 |
|
||
| **컬러 글로우** (`box-shadow: 0 0 80px rgba(139,92,246,.5)`) | 깊이·계층·상태를 글로우만으로 표현하면 의미가 모호해질 수 있다 | 그림자·경계·여백·글로우 후보 중 실제 계층과 성능을 가장 잘 드러내는 것을 선택한다 |
|
||
| **히어로 뒤 방사형 그라디언트 오브·헤일로** | 메시지·제품 증거·구도보다 장식이 먼저 읽히는지 점검한다 | 배경·제품 화면·타입 중심 구도를 같은 콘텐츠로 비교한다 |
|
||
| **순백 `#ffffff` / 순흑 `#000000`** 을 배경·텍스트로 | 극단값이 브랜드·매체·환경에 맞는지 점검한다 | 대상 기기·주변광·텍스트 대비와 실제 렌더의 눈부심을 확인한다. 색 자체를 실패로 취급하지 않는다. 출처: [WCAG 2.2 Contrast](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html)와 프로젝트 브리프 |
|
||
| **Tailwind 기본 토큰 그대로** (`slate-900`, `gray-500`, `emerald-500`) | 역할·브랜드·상태가 토큰 이름과 값에서 드러나는지 점검한다 | 기본 토큰을 유지·확장·교체할 수 있다. 의미 역할과 실제 렌더 근거를 기록한다 |
|
||
| **코드에서 색 이름을 직접 호출** (`purple-500`) | 색이 역할을 못 가짐 | 의미 토큰: `--color-action-primary`, `--color-surface-elevated`, `--color-text-secondary` |
|
||
| **그라디언트 텍스트** (`background-clip: text`) | 작은 크기·이미지 배경·공유 이미지에서 읽기와 fallback을 점검한다 | 단색·그라디언트·다른 위계 수단을 비교하고, 실제 export와 대비를 확인한다 |
|
||
| **크림/베이지(`#FDF8F3`)를 "고급"의 기본값으로** | 보라를 대체한 신종 슬롭 | 크림을 쓸 거면 왜 크림인지 브리프와 연결하고 텍스트·액센트를 그에 맞춰 재설계 |
|
||
| **여러 hue가 경쟁함** | 행동·상태·정보의 우선순위가 색 때문에 흐려질 수 있다 | 색 역할과 화면 면적을 실제 상태에서 비교한다. hue 수·60/30/10은 출발 가설일 뿐 통과 기준이 아니다 |
|
||
| **다크에서 본문 대비 미달** | 적용 WCAG 성공 기준을 실제 배경 합성값으로 충족하는지 점검한다 | `#0f172a` 위 `#94a3b8`의 WCAG 대비는 약 **6.96:1**이므로 미달 사례가 아니다. WCAG 2.2 AA 본문 판정에는 contrast ratio를 사용하며 APCA는 이를 대체하지 않는다. 반투명·이미지 배경은 실제 렌더에서 계산한다. 출처: [WCAG 2.2 Contrast](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html) |
|
||
|
||
---
|
||
|
||
## 2. 타이포그래피
|
||
|
||
| 지문 | 왜 문제 | 대신 |
|
||
|---|---|---|
|
||
| **Inter 선택** (특히 중앙 정렬 히어로) | 서체가 언어·정보 밀도·브랜드 톤에 맞는지 점검한다 | 후보 서체와 숫자·한글·긴 제목을 같은 viewport에서 비교하고, 라이선스·fallback metric을 기록한다. Inter 자체를 실패로 취급하지 않는다. 출처: `references/typography.md`와 프로젝트 브리프 |
|
||
| **Space Grotesk + Instrument Serif + Geist 조합** | 조합이 실제 위계와 브랜드 톤을 만드는지 점검한다 | 서체 수가 아니라 역할·fallback·가독성을 실제 렌더에서 비교한다. 조합의 구성원 수만으로 실패시키지 않는다. 출처: `references/typography.md` |
|
||
| **헤드라인 한 단어만 세리프 이탤릭** (`Build <em>better</em> products`) | 강조가 브랜드 언어·문장 의미·읽기 순서를 실제로 돕는지 점검한다 | 이탤릭·줄바꿈·크기·색·여백을 같은 문구에서 비교하고 선택 이유를 기록한다 |
|
||
| **페이지 전체에 폰트 패밀리 1개** | 서체 수와 무관하게 제목·본문·데이터의 위계가 읽히는지 점검한다 | 한 패밀리 또는 여러 패밀리를 같은 콘텐츠·viewport·확대 상태에서 비교하고, 역할과 fallback을 기록한다. 출처: `references/typography.md` |
|
||
| **타입 스케일이 평평해 보임** | 최대/본문 배율이 아니라 실제 과업의 위계·읽기 폭·언어 적합성을 점검한다 | 제목·본문·보조 정보의 역할과 렌더된 우선순위를 비교한다. 배율·단계 수는 관찰값으로 기록하되 최대/본문 4배나 특정 비율을 보편 통과 조건으로 쓰지 않는다. 출처: `references/design-foundations.md`, `references/typography.md` |
|
||
| **타입 스케일 단계가 많음** | 같은 역할에 여러 크기가 섞이면 읽기 순서가 흐려질 수 있다 | 각 단계에 역할을 이름 붙이고, 대표 폭·확대 상태에서 실제 위계를 확인한다. 단계 수 자체로 실패시키지 않는다 |
|
||
| **히어로 = pill 배지 + 거대 헤드라인** (`✨ Now in beta` + H1) | 배지가 실제 상태·시간성·제약을 설명하는지 점검한다 | 배지·문장 안 상태·내비 상태·생략을 비교하고, 첫 행동에 필요한 경우만 남긴다 |
|
||
| **`_01_ _02_ _03_` 장식 번호 라벨** | 에디토리얼 흉내인데 구조는 없음 | 번호가 순서를 의미할 때만 |
|
||
| **본문/헤드라인 자간이 읽기를 방해함** | 글꼴·언어·크기·폭에 따라 글리프 충돌, 단어 인식, 줄바꿈이 달라진다 | 0, 양수, 음수 자간을 대표 문구·지원 viewport·200% 확대에서 비교한다. 단일 `em` 수치를 보편 기준으로 쓰지 않는다 |
|
||
| **본문 크기·행간이 과업에 맞지 않음** | 작은 글자나 촘촘한 행간은 읽기·확대·오류 복구 비용을 높일 수 있다 | 글꼴·언어·콘텐츠 밀도별 후보를 실제 기기·200% 확대·긴 문단에서 검증한다. 16px이나 고정 line-height를 보편 하한으로 선언하지 않는다 |
|
||
| **모노스페이스를 장식으로 사용** | 코드·데이터 외 용도에서도 의미·가독성·브랜드 톤을 돕는지 점검한다 | 대상 언어·크기·대비·긴 문자열을 실제 렌더에서 비교한다. 모노스페이스 자체나 용도만으로 실패시키지 않는다. 출처: `references/typography.md` |
|
||
|
||
---
|
||
|
||
## 3. 레이아웃 · 구조
|
||
|
||
| 지문 | 왜 문제 | 대신 |
|
||
|---|---|---|
|
||
| **표준 골격**: 히어로 → 3열 피처 → 로고월 → 요금제 → FAQ → 푸터 | shadcn/ui 예제·Tailwind UI·Vercel 템플릿의 순서 그대로 | 섹션 순서를 브리프의 설득 논리로 재배열. 예: 문제 제시 → 실제 사용 화면 → 반론 처리 → 가격 |
|
||
| **중앙 정렬 히어로** (텍스트 가운데 + CTA 2개 + 아래 스크린샷) | 목표 행동·읽기 폭·브랜드의 구도를 돕는지 점검한다 | 중앙·비대칭·좌측 정렬 후보를 같은 콘텐츠와 viewport에서 비교하고, 선택 근거를 기록한다. 중앙 정렬 자체를 실패로 취급하지 않는다. 출처: `references/design-foundations.md`, 프로젝트 브리프 |
|
||
| **균등 카드 grid** | 항목 중요도·비교 과업·작은 폭 재배치가 균등 구조와 맞는지 점검한다 | 3열/비대칭/목록을 콘텐츠와 대표 과업에서 비교한다 |
|
||
| **아이콘 중심 피처 카드** | 아이콘이 실제 기능 이해를 돕는지, 이미지·수치·UI 증거가 더 나은지 점검한다 | 아이콘 위치·라벨·실제 제품 조각을 비교하고, 전체 카드 hitbox와 접근 가능한 이름을 확인한다 |
|
||
| **컬러 스트립·중첩 카드** | 경계와 깊이가 실제 정보 묶음을 나타내는지 점검한다 | 여백·선·표면·중첩을 비교한다. 중첩 횟수와 border 폭은 통과 기준이 아니다 |
|
||
| **근거 없는 지표 배너** (`10,000+ users · 99.9% uptime · 4.9★`) | 검증할 수 없는 수치는 사실처럼 제시하면 안 된다 | 출처·측정 조건·기간이 있는 수치만 쓰고, 수가 여러 개여도 목적에 맞는 묶음과 출처를 제시한다 |
|
||
| **여백 리듬이 정보 관계를 가림** | 같은/다른 간격이 관련성과 우선순위를 드러내지 못할 수 있다 | 토큰 수·비율을 고정하지 말고, 실제 콘텐츠와 회색조 렌더에서 그룹·섹션 관계를 확인한다 |
|
||
| **벤토 그리드를 기본 선택지로** | 타일 크기 차이가 정보 위계나 과업을 설명하지 못할 수 있다 | 벤토·단순 목록·비교 grid를 콘텐츠와 작은 폭 재배치에서 비교한다. 연도별 트렌드 주장은 근거가 아니다 |
|
||
| **콘텐츠 여백·본문 폭이 읽기를 방해함** | viewport·글꼴·언어·확대에 따라 줄 길이와 행동 영역이 달라진다 | gutter와 measure 후보를 320px·200% 확대·넓은 폭에서 렌더해 검증한다. 고정 px·ch 범위는 출발값일 뿐이다 |
|
||
| **푸터가 링크 4열 + 소셜 아이콘 + 카피라이트뿐** | AI가 가장 성의 없이 만드는 곳 | 실제 정보(연락처, 주소, 사업자 정보)를 넣어라. 링크가 4개뿐이면 4열로 만들지 마라 |
|
||
|
||
---
|
||
|
||
## 4. 컴포넌트
|
||
|
||
| 지문 | 왜 문제 | 대신 |
|
||
|---|---|---|
|
||
| **기본 radius·shadow·padding 조합을 그대로 사용** | 컴포넌트 역할·밀도·브랜드 표면이 토큰과 맞는지 점검한다 | radius·선·그림자·여백 후보를 실제 상태에서 비교하고, 역할 토큰으로 기록한다 |
|
||
| **여러 깊이 표현을 겹침** | 경계·그림자·표면 차이가 같은 계층을 중복 설명하는지 점검한다 | 하나 또는 여러 단서를 쓸 수 있다. 포커스·상태·인접 표면에서 계층이 읽히는지 검증한다 |
|
||
| **글래스모피즘 전면 사용** (`backdrop-blur` 카드 다수) | backdrop filter의 성능·대비·reduced-transparency 대안이 필요할 수 있다 | 대상 기기의 performance, fallback 표면, 텍스트 대비를 측정하고 역할이 있을 때만 채택한다 |
|
||
| **이모지를 아이콘 대신** (🚀 ⚡ 🎯 ✨) | 의미·locale·플랫폼 렌더링·접근 가능한 이름이 역할을 돕는지 점검한다 | 이모지·아이콘 세트·텍스트를 실제 대상과 보조기술에서 비교한다 |
|
||
| **여러 CTA가 같은 무게로 경쟁함** | 사용자가 다음 행동을 선택하기 어려울 수 있다 | 행동 우선순위·위험·되돌림에 맞춰 주/보조 CTA와 배치를 정하고 과업 테스트한다 |
|
||
| **로고월·후기·FAQ·요금제 템플릿** | 사실·질문·가격 구조가 현재 제품의 증거인지 점검한다 | 검증 가능한 출처와 실제 고객 질문·요금 조건을 사용한다. 개수·열 수·배지 존재로 실패시키지 않는다 |
|
||
| **펄스 애니메이션 상태 점** (초록 원 깜빡임 + "All systems operational") | 정적 정보에 장식 애니메이션 | 상태가 실제로 바뀔 때만 |
|
||
| **자동 스크롤 마퀴** (로고·후기·태그가 끝없이 흐름) | 읽기·움직임 민감도·입력과 충돌할 수 있음 | 목적·정지 수단·감소 모션·성능을 검증하고, 정적 그리드 또는 페이지네이션과 비교 |
|
||
| **hover 상태가 과업을 돕지 않음** | 포인터 반응이 행동 가능성·현재 상태·위험을 설명하지 못할 수 있다 | 링크·카드·버튼의 상태를 역할별로 설계하고, touch/keyboard에서도 같은 핵심 단서를 제공한다 |
|
||
| **편집 불가 히어로 카피 뒤 깜빡이는 커서 `|`** | 타이핑 흉내. 정보 없음 | 삭제 |
|
||
|
||
---
|
||
|
||
## 5. 모션
|
||
|
||
| 지문 | 왜 문제 | 대신 |
|
||
|---|---|---|
|
||
| **같은 모션을 모든 요소에 적용** | 모션이 상태·관계·우선순위를 설명하지 못하고 읽기를 방해할 수 있다 | 중요한 변화에만 모션을 연결하고, duration/easing은 과업·거리·reduced-motion에서 검증한다. 고정 ms 범위는 출발값이다 |
|
||
| **bounce·elastic·scale·rotate 모션** | 장면의 물성·피드백 의미·멀미·성능과 맞는지 점검한다 | 이징과 속성은 실제 상호작용·reduced-motion·저사양 기기에서 비교한다 |
|
||
| **스크롤 reveal 실패 시 콘텐츠가 `opacity: 0`으로 남음** | JS 실패 시 빈 페이지가 됨 | 기본을 visible로 두고 JS가 숨긴 뒤 보여주는 방식. 또는 CSS scroll-driven animation |
|
||
| **`prefers-reduced-motion` 미대응** | 사용자 모션 선호를 무시하면 중요한 상태를 이용하기 어려울 수 있다 | `prefers-reduced-motion`에서 비동작 대체 신호와 핵심 과업을 실제로 검증한다 (`evidence-ledger.md`의 `W3C-REDUCED`) |
|
||
| **전 섹션 패럴랙스·3D/Spline 씬** | 콘텐츠보다 연출이 우선되거나 저사양·느린 망에서 핵심 경로를 막을 수 있다 | 목적·성능 예산·정적 fallback·정지 제어를 정하고 local proxy와 field data를 구분해 측정한다 |
|
||
| **로딩할 게 없는데 프리로더 카운터** | 없는 대기를 만듦 | 삭제 |
|
||
|
||
---
|
||
|
||
## 6. 카피 — 경쟁사 치환 테스트
|
||
|
||
**AI 티는 시각보다 문장에서 먼저 난다.**
|
||
|
||
### 테스트
|
||
카피에서 제품·회사 이름을 **경쟁사 이름으로 바꿔 읽는다.**
|
||
**여전히 자연스러우면 그 카피는 아무것도 말하지 않은 것이다. 다시 써라.**
|
||
|
||
### 작법 — 금지 목록만으로는 못 잡는다
|
||
|
||
위의 지문 목록은 **나쁜 문장**을 걸러낸다. 그런데 지문에 하나도 안 걸리면서
|
||
**아무것도 전달하지 않는 문장**이 있다. 대개 대구가 예뻐서 통과된다.
|
||
|
||
> 실측 사례: `"표면은 CSS 가 정하고, 공간은 GPU 가 맡는다"`
|
||
> 치환 테스트 통과(다른 제품엔 안 맞는다), 금칙어 없음, 리듬도 좋다.
|
||
> 그런데 **독자가 얻는 것이 없다.** 구현 이야기를 대구로 포장한 것뿐이다.
|
||
|
||
**세 가지로 거른다.**
|
||
|
||
**1. `so you can…` 테스트** — 문장 뒤에 이어 붙여 완성해봐라.
|
||
|
||
```
|
||
"feTurbulence 로 노이즈를 만든다" so you can → 200KB 텍스처를 300바이트로 줄인다 ✅
|
||
"표면은 CSS 가 정하고 공간은 GPU 가 맡는다" so you can → ??? ❌
|
||
```
|
||
|
||
완성되지 않으면 기능만 쓴 것이다. **완성된 뒷부분을 헤드라인으로 올려라.**
|
||
|
||
**2. 6~12단어** — 2초 안에 훑히면서 가치를 전달하는 폭이다.
|
||
한국어는 어절 기준으로 6~12, 글자 수로는 12~28자.
|
||
|
||
**3. 헤딩에 검증 가능한 것을 넣어라** — 숫자·조건·비교 대상 중 하나.
|
||
|
||
| 고치기 전 | 고친 뒤 | 무엇이 달라졌나 |
|
||
|---|---|---|
|
||
| 표면은 CSS 가 정하고, 공간은 GPU 가 맡는다 | **텍스처 200KB 를 300바이트가 대신한다** | 구현 → 이득. 수치가 검증 가능 |
|
||
| Powerful Features | 엑셀 없이 정산이 끝난다 | 명사구 → 주장 |
|
||
| 빠르고 안정적인 배포 | 실제 배포·롤백 결과와 조건 | 형용사 → 측정치. 예: 검증된 `p95 롤백 시간`, 기간, 환경 |
|
||
|
||
### 데모가 주장을 증명하는지 재라
|
||
|
||
주장을 화면으로 보여주는 섹션이라면, **그 화면이 정말 다른지 숫자로 확인해라.**
|
||
"차이는 이 한 줄뿐이다"라고 써놓고 두 쪽이 똑같으면, 그건 증명이 아니라 주장의 반증이다.
|
||
|
||
> 실측 사례: `word-break: break-all` 과 `keep-all` 을 나란히 두고
|
||
> "차이는 한 줄뿐"이라고 적었다. 재보니 **줄 수 3, 높이 87px 로 완전히 동일**했다.
|
||
> 어절이 짧아 두 쪽이 같은 자리에서 끊긴 것이다. 반년을 그대로 뒀어도 몰랐을 것이다.
|
||
|
||
```js
|
||
// 비교 데모는 이렇게 검증한다
|
||
const m = sel => { const e = document.querySelector(sel), r = e.getBoundingClientRect();
|
||
return { h: Math.round(r.height), lines: Math.round(r.height / parseFloat(getComputedStyle(e).lineHeight)) }; };
|
||
// m('.bad') 와 m('.good') 이 같으면 그 데모는 아무것도 보여주지 않는다
|
||
```
|
||
|
||
**차이가 안 나면 조건을 극단으로 밀어라** — 폭을 좁히고, 잘리기 쉬운 긴 어절을 넣고,
|
||
값 차이를 벌린다. 그래도 안 나면 그 비교는 애초에 보여줄 것이 없는 것이다.
|
||
|
||
그리고 **설명 문장이 화면과 일치하는지 확인해라.** "A 가 갈린다"고 썼는데 실제로 갈린 건
|
||
B 라면, 반응형에서 매번 바뀌는 것을 지목한 것이다. 지목하지 말고 현상만 말해라.
|
||
|
||
**대구·대조·리듬은 마지막에 얹는 것이다.** 먼저 말할 내용을 정하고,
|
||
그것이 정해진 뒤에도 대구가 성립하면 그때 써라. 대구부터 잡으면 내용이 비어도 모른다.
|
||
|
||
### 구문 지문
|
||
|
||
| 지문 | 왜 문제 | 대신 |
|
||
|---|---|---|
|
||
| **`It's not X, it's Y` / `단순한 X가 아니라 Y입니다`** | 대조가 실제 차이·조건을 설명하지 못하면 문장이 비어 보일 수 있다 | Y를 직접 말하거나, 필요할 때 비교 대상과 검증 조건을 명시한다 |
|
||
| **스타카토 3연타** (`No fluff. No filler. No BS.` / `빠르게. 정확하게. 간단하게.`) | 리듬으로 내용 없음을 감춤 | 한 문장으로 구체적으로 |
|
||
| **em-dash(—) 한 문단에 2회 이상** | AI 문장 리듬의 대표 지문 | 마침표로 끊거나 쉼표로. 한국어에서 특히 부자연스럽다 |
|
||
| **`In today's fast-paced digital landscape...`** 도입 | 아무 말도 하지 않는 문단 | 첫 문장부터 본론. 도입 문단 삭제 |
|
||
|
||
### 어휘 지문
|
||
|
||
| 지문 | 왜 문제 | 대신 |
|
||
|---|---|---|
|
||
| `Streamline / Empower / Supercharge / Unlock / Leverage / Seamless / Elevate` | 아무 제품에나 붙는 동사. 정보량 0 | 제품이 실제로 하는 동작 동사 (`정산한다`, `병합한다`, `4일을 6시간으로 줄인다`) |
|
||
| `world-class / cutting-edge / enterprise-grade / best-in-class` | 자기 평가 형용사는 증거가 아니다 | 인증명, 벤치마크 수치, 고객사 실명 |
|
||
| `Build the future of X` / `Your all-in-one platform` / `Scale without limits` | 경쟁사 이름으로 바꿔도 성립 | 치환 테스트를 통과하는 문장 (예: "Financial infrastructure for the internet") |
|
||
| 헤지 표현 (`may help you`, `~할 수 있습니다`) | 불확실성의 범위가 숨겨지면 독자가 주장 강도를 판단하기 어렵다 | 검증된 내용은 명확히 쓰고, 불확실하면 조건·근거·한계를 명시한다 |
|
||
| CTA가 `Get Started` / `Learn More` / `시작하기` | 무엇이 시작되는지 알 수 없음 | 결과를 말하는 CTA (`무료로 30일 써보기`, `가격표 보기`) |
|
||
| 출처·조건 없는 숫자 (`10,000+`, `99.9%`, `50% faster`) | 사실처럼 보이는 주장의 검증 경로가 없다 | 정확/범위 수치 모두 출처·측정 조건·기간을 붙인다. 조건 없는 수치는 제거하거나 예시임을 라벨링한다 |
|
||
| 모든 헤딩이 명사구 (`Powerful Features`, `Simple Pricing`) | 헤딩이 정보를 전달하지 않음 | 헤딩에 주장을 담아라 (`엑셀 없이 정산이 끝난다`) |
|
||
| 레이블·서브레이블·헬퍼가 같은 말 3번 (`이메일` / `이메일 주소` / `이메일 주소를 입력하세요`) | 화면 소음 | 하나만 남긴다 |
|
||
| 이모지로 시작하는 불릿 (`✅ 빠른 속도`) | 정보 위계를 이모지로 대체 | 일반 불릿 또는 문장으로 |
|
||
|
||
---
|
||
|
||
## 7. 이미지
|
||
|
||
| 지문 | 왜 문제 | 대신 |
|
||
|---|---|---|
|
||
| **스톡 사진·추상 3D·AI 일러스트·일반 SVG 그래픽** | 이미지가 제품 증거·브랜드·정보 이해 대신 빈 자리를 메우는지 점검한다 | 실제 사진·제품 UI·데이터·일러스트·여백 중 과업을 가장 잘 설명하는 것을 선택하고, 출처·라이선스·alt·크롭을 검증한다 |
|
||
| **아이콘 세트가 섞임** (라인·필·이모지 혼재) | 시스템이 없다는 증거 | 세트 하나 고정. 굵기·크기·광학 정렬 통일 |
|
||
| **`src`가 비었거나 깨진 이미지 태그** | 검증 없이 배포된 흔적 | 배포 전 이미지 로드 전수 확인 |
|
||
| **모든 이미지가 같은 비율의 둥근 사각형** | 그리드를 이미지에 강제 | 콘텐츠에 맞는 비율. 풀블리드 1장을 섞으면 리듬이 생긴다 |
|
||
|
||
---
|
||
|
||
## 8. 한글 조판 (한국어 프로젝트 필수)
|
||
|
||
한국어는 글꼴·줄바꿈·fallback·문장 리듬을 실제 콘텐츠와 지원 기기에서 별도로 검증한다. 영문 출발값을 그대로 복사하지 않는다.
|
||
|
||
| 규칙 | 값 | 이유 |
|
||
|---|---|---|
|
||
| **한글 글꼴과 fallback 미확인** | 한국어 glyph coverage·줄바꿈·숫자·운영체제 fallback이 과업에 맞는지 점검한다 | 시스템 한글 폰트를 포함해 실제 지원 기기에서 긴 제목·본문·숫자를 렌더하고, 선택·라이선스·fallback metric을 기록한다. 시스템 폰트 사용만으로 완성도 미달로 취급하지 않는다. 출처: `references/typography.md`, 프로젝트 브리프 |
|
||
| **한글 line-height 후보** | 글꼴·크기·문단 길이·화면 폭에 따라 읽기 리듬이 달라진다 | 1.6–1.8을 포함한 후보를 실제 본문·확대 상태에서 비교한다. 특정 값이 보편 기준은 아니다 |
|
||
| **한글 음수 자간** | 글리프 충돌·단어 인식·확대 상태에서의 읽기성을 점검한다 | 본문·대형 제목·지원 viewport·200% 확대에서 실제 렌더를 비교한다. 음수 자간의 존재만으로 실패시키지 않고, 충돌이나 읽기 저하가 확인되면 조정한다. 출처: `references/typography.md`, 프로젝트 렌더 검증 |
|
||
| **줄바꿈·measure·fallback 순서** | 단어 단위 줄바꿈, 라틴/한글 숫자 렌더, 폭은 글꼴과 콘텐츠에 따라 달라진다 | `word-break`, `overflow-wrap`, measure, fallback 순서를 대표 문단·긴 단어·숫자·지원 기기에서 비교한다. 고정 글자 수나 순서를 규범으로 쓰지 않는다 |
|
||
| **번역투 가능성** | 문맥·대상 독자와 맞지 않는 직역은 의미를 흐릴 수 있다 | 실제 독자와 용어 체계에 맞춰 문장을 다듬고, 제시 표현을 기계적 치환 규칙으로 쓰지 않는다 |
|
||
|
||
**한글 폰트 후보**
|
||
- Pretendard, 마루 부리, Spoqa Han Sans Neo, 본고딕/Noto Sans KR 등은 목적·glyph coverage·라이선스·fallback·전송량을 비교할 후보다.
|
||
- 캠페인 display 폰트도 업종 자체로 배제하지 않는다. 실제 문구·브랜드·작은 크기·지원 기기에서 읽기와 인상을 검증한다.
|
||
|
||
---
|
||
|
||
## 9. grep 코드 지문 (프리플라이트 자동 검사)
|
||
|
||
```
|
||
# 색
|
||
indigo-|violet-|purple-|fuchsia-
|
||
#6366f1|#818cf8|#a855f7|#8b5cf6|#c4b5fd|#a78bfa|#22d3ee
|
||
from-purple|to-blue-|from-violet|via-purple
|
||
bg-slate-900|bg-gray-900|text-gray-400
|
||
#ffffff|#000000
|
||
|
||
# 컴포넌트 기본값
|
||
rounded-2xl|rounded-3xl
|
||
shadow-lg|shadow-xl|shadow-2xl
|
||
border-l-4|border-t-4
|
||
backdrop-blur
|
||
|
||
# 타이포
|
||
font-family:.*Inter
|
||
(Space Grotesk.*Instrument Serif)|(Instrument Serif.*Geist)|(Space Grotesk.*Geist)
|
||
uppercase tracking-wide
|
||
|
||
# 카피
|
||
Get Started|Learn More|Empower|Streamline|Supercharge|Seamless
|
||
world-class|cutting-edge|enterprise-grade|best-in-class
|
||
It's not .* it's
|
||
|
||
# 이모지 아이콘 (텍스트 노드)
|
||
🚀|⚡|✨|🎯|🔥|💡|✅
|
||
```
|
||
|
||
**한글 프로젝트 추가 검사**
|
||
|
||
```
|
||
# 확인 후보 — 프로젝트 계약과 실제 렌더로 평가
|
||
word-break:\s*keep-all
|
||
Pretendard|Noto Sans KR|본고딕|마루부리
|
||
|
||
# 세밀하게 확인할 후보 — 프로젝트 계약과 실제 렌더로 평가
|
||
letter-spacing:\s*-0\.0[3-9] (한글 본문)
|
||
~를 통해|~에 대한|에 있어서
|
||
```
|
||
|
||
---
|
||
|
||
## 9-b. 재는 도구가 거짓말하는 세 가지 방식
|
||
|
||
측정으로 판정하라고 해놓고, 그 측정 자체가 틀리면 잘못된 확신만 남는다.
|
||
실측에서 걸린 세 가지다.
|
||
|
||
**① 등장 애니메이션이 끝나기 전에 재면 간격이 틀리게 나온다.**
|
||
`.reveal { transform: translateY(16px) }` 이 걸린 요소는 화면 밖에 있는 동안 계속
|
||
16px 아래에 있다. 화면 최상단에서 아래쪽 섹션의 간격을 재면 그 16px 이 여백으로 잡힌다.
|
||
한 섹션만 24px 이 아니라 38px 로 나와 한참 원인을 찾았는데, 원인은 CSS 가 아니라
|
||
**측정 시점**이었다. 제목과 본문이 나란히 애니메이션되면 같이 움직여 상쇄되지만,
|
||
한쪽만 `.reveal` 이면 상쇄되지 않는다.
|
||
|
||
```js
|
||
await page.evaluate(() => el.scrollIntoView({ block: 'center' }));
|
||
await page.waitForTimeout(1600); // 프로젝트의 모션 종료 조건을 확인한 뒤 잰다
|
||
```
|
||
|
||
**② `sharp(...).extract(...).stats()` 사용 결과가 의도한 crop 통계를 반영하는지 확인한다.**
|
||
영역을 여섯 군데 잘라 밝기를 쟀는데 여섯 개가 **소수점까지 똑같이** 나왔다.
|
||
전부 원본 전체 평균이었기 때문이다. 값이 수상하게 균일하면 도구를 먼저 의심해라.
|
||
|
||
```js
|
||
const buf = await sharp(f).extract(box).png().toBuffer();
|
||
const s = await sharp(buf).stats(); // 잘라낸 버퍼를 다시 물려야 한다
|
||
```
|
||
|
||
**③ Playwright 의 `animations: 'disabled'` 는 애니메이션을 끝 상태로 보낸다.**
|
||
움직이는 데모를 중간 프레임에서 재려고 `animation-play-state: paused` 로 세워 뒀는데,
|
||
스크린샷 옵션이 그걸 무시하고 100% 지점을 찍었다. 그 프레임에서는 두 도형이 이미
|
||
겹쳐 있어서 "필터가 안 붙는다" 는 잘못된 결론이 나왔다. 멈춘 프레임을 그대로
|
||
찍으려면 그 옵션을 **빼야** 한다.
|
||
|
||
> 움직임이 핵심 주장을 전달한다면 정지 상태의 대체 증거와 함께 검증한다. 지나가는 프레임은 캡처 시점에 따라 달라질 수 있으므로, before/after 정지 캡처가 비교에 적합한 경우가 많다.
|
||
|
||
**④ 개별 요소의 높이로는 "여러 줄에 걸친 것" 을 못 잡는다.**
|
||
"컨트롤 행이 지원 폭에서 읽거나 조작할 수 없게 되는가"를 이렇게 쟀다.
|
||
|
||
```js
|
||
// 틀렸다 — 이 검사는 "접힘 0" 이라고 답한다
|
||
[...document.querySelectorAll('.nav a')]
|
||
.filter(e => e.getBoundingClientRect().height > lineHeight * 1.8)
|
||
```
|
||
|
||
각 링크는 한 줄짜리라 높이가 정상이었다. **줄바꿈된 것은 링크가 아니라 컨테이너였다** —
|
||
링크들이 두 행(top 46 / 77)에 나뉘어 놓여 있었다. 게이트를 통과했다고 보고했고,
|
||
사용자가 화면을 보고 잡아냈다.
|
||
|
||
```js
|
||
// 맞다 — 행이 몇 개인지는 top 값의 종류로 센다
|
||
new Set([...document.querySelectorAll('.nav a')]
|
||
.map(e => Math.round(e.getBoundingClientRect().top))).size
|
||
```
|
||
|
||
같은 함정이 갤러리·태그 목록·버튼 그룹 어디에나 있다.
|
||
**"몇 줄인가"를 물을 때는 컨테이너의 위치 분포와 요소 높이를 함께 본다.**
|
||
|
||
**⑤ 눈으로 의심한 것이 실측에서 뒤집힐 수 있다.**
|
||
WebGL 판이 본문 뒤를 지나가는 화면을 보고 "대비가 죽었다" 고 판단해 캔버스를
|
||
어둡게 만들려 했다. 스크린샷에서 글자 사이 빈 띠의 배경 휘도를 재보니
|
||
최악 지점이 **9.83:1** — AAA(7:1)를 넘었다. 고칠 필요가 없었다.
|
||
밝은 것과 대비가 낮은 것은 다르다. 화려한 배경 위 텍스트는 실제 배경 합성 상태의 contrast ratio와 읽기 관찰을 함께 확인한다.
|
||
|
||
> 캔버스 접근 가능성은 렌더링 구성에 따라 다르다. 스크린샷 기반 측정은 한 방법이며, 텍스트와 배경의 실제 합성 상태를 대표하는 표본을 골라 계산한다.
|
||
|
||
---
|
||
|
||
### 여백이 필요하면 여백을 만들어라 — 문장으로 채우지 마라
|
||
|
||
sticky 캔버스가 끝까지 돌려면 목록 뒤에 스크롤 구간이 필요했다.
|
||
빈 요소를 두기가 뭐해서 마무리 문장을 한 줄 놓았다.
|
||
|
||
> "여섯 단계 끝에 남는 것은 페이지 하나와 design.md 하나다."
|
||
|
||
문장 자체는 틀리지 않았다. 다만 **읽는 사람이 그 자리에서 기대하는 말이 아니다.**
|
||
사용자가 처음 한 말이 "이건 왜 있는 거예요" 였다.
|
||
|
||
레이아웃을 위해 추가한 문장이 콘텐츠 역할을 하지 않으면 겉돌 수 있다. 여백과 문장 중 어느 것이 목적을 더 잘 충족하는지 검토한다.
|
||
|
||
> 자가 진단: 이 문장을 지우면 **레이아웃이 깨지는가, 뜻이 빠지는가?**
|
||
> 레이아웃만 깨진다면 그 문장은 여백의 대역이고, 여백으로 바꿔야 한다.
|
||
|
||
### 지적받은 자리만 고치면 전체가 무너진다
|
||
|
||
한 페이지를 만들며 사용자 지적이 올 때마다 그 섹션을 손봤다.
|
||
각각은 옳은 수정이었는데 합계는 이렇게 됐다.
|
||
|
||
| 섹션 | 분량 | 역할 |
|
||
|---|---|---|
|
||
| 히어로 | 0.7 화면 | 이게 뭔가 |
|
||
| 파이프라인 | 2.4 | 어떻게 작동하나 |
|
||
| 기능 예시 A | **3.1** | 곁가지 |
|
||
| 기능 예시 B | 1.8 | 곁가지 |
|
||
| 증거 ①②③④ | 5.5 | 같은 말 네 번 |
|
||
|
||
**곁가지 하나가 본론의 1.3 배, 첫인상이 가장 짧다.** 분량 배분이 중요도와 정반대다.
|
||
사용자 표현으로는 "정신이 없어 보인다".
|
||
|
||
부분 수정이 누적되면 전체 비율·읽기 순서·핵심 과업을 다시 측정한다.
|
||
|
||
```js
|
||
// 섹션별 화면 수 — 배분이 우선순위와 맞는지 한 번에 보인다
|
||
[...document.querySelectorAll('main > section')].map(s => ({
|
||
제목: s.querySelector('h2')?.textContent?.trim().slice(0, 24),
|
||
화면: +(s.getBoundingClientRect().height / innerHeight).toFixed(1),
|
||
}))
|
||
```
|
||
|
||
읽는 순서도 같이 본다. **같은 성격끼리 붙어 있어야 한다** — 기능·증거·기능·증거로
|
||
번갈아 나오면 독자는 지금 무슨 이야기를 듣고 있는지 놓친다.
|
||
소개 페이지의 기본 묶음은 `무엇인가 → 무엇을 아는가 → 정말 그런가 → 행동` 이다.
|
||
|
||
---
|
||
|
||
### 데모를 만들기 전에 카피부터 쓰지 마라
|
||
|
||
실측 사례. 필터 데모 넷을 만들면서 각 데모의 결론 문장을 먼저 썼다 —
|
||
"대비 2.1:1 → 12.4:1", "하나로 이어진다", "배경을 휜다".
|
||
나중에 재보니 **넷 중 셋이 거짓이었다.**
|
||
|
||
| 화면에 쓴 말 | 실제 측정 |
|
||
|---|---|
|
||
| 대비 2.1:1 → 12.4:1 | 1.70:1 → **3.12:1** (AA 미달) |
|
||
| 하나로 이어진다 | 필터를 켠 쪽도 **덩어리 3개** |
|
||
| 배경을 휜다 | 평균 채널차 **1.66** (거의 변화 없음) |
|
||
|
||
숫자를 지어낸 것이 아니라 **"이 정도 나오겠지" 를 적고 확인하지 않은 것**이다.
|
||
결과는 같다 — 페이지에 거짓이 실렸다.
|
||
|
||
순서를 뒤집어라.
|
||
|
||
1. 데모를 만든다
|
||
2. **잰다** (before/after 를 각각 캡처해 픽셀로)
|
||
3. 잰 값으로 문장을 쓴다
|
||
4. 값이 주장을 뒷받침하지 못하면 **문장이 아니라 데모를 고친다**
|
||
|
||
4번을 지키면 카피가 저절로 구체적이 된다. 위 셋은 고친 뒤 이렇게 됐다 —
|
||
"흰 글자 대비 1.70:1 → 4.79:1", "가로로 세어 덩어리 3개 → 1개",
|
||
그리고 세 번째는 끝내 작동하지 않아 **섹션에서 뺐다.**
|
||
|
||
> 작동하지 않는 데모를 남기고 문장만 다듬는 선택지는 없다.
|
||
|
||
---
|
||
|
||
## 10. 자가 채점표
|
||
|
||
| 카테고리 | 걸린 항목 | 조치 |
|
||
|---|---|---|
|
||
| 0 최우선 3종 | | |
|
||
| 1 컬러 | | |
|
||
| 2 타이포 | | |
|
||
| 3 레이아웃 | | |
|
||
| 4 컴포넌트 | | |
|
||
| 5 모션 | | |
|
||
| 6 카피 | | |
|
||
| 7 이미지 | | |
|
||
| 8 한글 조판 | | |
|
||
|
||
**검토 조건 — 근거와 결과를 남긴다**
|
||
- [ ] 반복 후보(보라 CTA / 전체 대문자 / 1·2·3 단계)를 발견했으면 프로젝트 계약·브리프·실제 렌더 근거로 유지·수정·제거를 결정했다
|
||
- [ ] grep 검사에서 나온 항목은 자동 실패로 취급하지 않고, 출처·관찰·결정·검증을 기록했다
|
||
- [ ] 카피가 경쟁사 치환 테스트를 통과한다
|
||
- [ ] 모션을 전부 끄고도 페이지가 작동한다
|
||
- [ ] 강조색을 지워도 페이지가 읽힌다
|
||
- [ ] 색을 회색조로 바꿔도 위계 순서가 비즈니스 우선순위와 일치한다
|
||
- [ ] 키보드만으로 전 인터랙션이 가능하고 포커스 링이 보인다
|
||
- [ ] (한국어) 글꼴·fallback·줄바꿈 규칙이 실제 지원 기기와 긴 제목·본문·숫자에서 읽히는지 검증하고, 프로젝트 계약에 선택 근거를 남겼다
|
||
- [ ] 제목→본문 간격이 각 섹션의 정보 관계를 설명하고, 의도하지 않은 0px·겹침·불균형이 없는지 실제 렌더에서 확인했다
|
||
- [ ] 화면에 적은 수치는 **전부 그 화면을 캡처해 잰 값**이다 (추정치·기대치가 섞여 있지 않다)
|
||
- [ ] 이미지의 실제 표시 비율·크롭·해상도가 의도한 콘텐츠 역할과 화면 폭에 맞는지 측정했다. 원본 픽셀과의 일치만으로 `aspect-ratio` 동작을 판정하지 않는다
|
||
- [ ] 내비·버튼 그룹의 **행 수를 `top` 값으로** 셌다 (개별 높이로는 못 잡는다)
|
||
|
||
**판정**
|
||
|
||
후보 수를 점수나 자동 통과 기준으로 쓰지 않는다. 각 후보마다 `프로젝트 계약`, `출처 ID`, `적용 조건`, `실제 렌더 관찰`, `유지·수정·제거 결정`, `검증 결과`를 남긴다. WCAG 성공 기준 또는 실제 기능 실패가 있으면 그 항목은 해결 전 통과로 선언하지 않는다. 그 밖의 스타일 후보는 과업·브랜드·위계·성능의 증거로 판정한다.
|
||
|
||
> 근거와 한계: `references/evidence-ledger.md`, `references/design-foundations.md`, 프로젝트 브리프와 렌더 검증
|