[G1-Sync] Manual knowledge update

This commit is contained in:
Antigravity Agent
2026-05-10 22:08:15 +09:00
parent 21ac3ed255
commit 504fd5fb42
3011 changed files with 380280 additions and 206977 deletions
@@ -2,101 +2,233 @@
id: wiki-2026-0508-웹-접근성-및-성능-최적화
title: 웹 접근성 및 성능 최적화
category: 10_Wiki/Topics
status: needs_review
status: verified
canonical_id: self
aliases: []
aliases: [Web Accessibility, A11y, Performance Optimization, WCAG, Core Web Vitals]
duplicate_of: none
source_trust_level: A
confidence_score: 0.92
tags: [uncategorized]
confidence_score: 0.9
verification_status: applied
tags: [accessibility, a11y, performance, wcag, core-web-vitals, frontend]
raw_sources: []
last_reinforced: 2026-05-08
last_reinforced: 2026-05-10
github_commit: pending
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
tech_stack:
language: unspecified
framework: unspecified
language: TypeScript
framework: React/Web
---
# [[웹 접근성 및 성능 최적화|웹 접근성 및 성능 최적화]]
# 웹 접근성 및 성능 최적화
## 📌Brief 시
웹 접근성 및 성능 최적화는 모든 사용자 환경과 기기에서 디지털 제품이 빠르고 일관되며 장벽 없이 작동하도록 만드는 핵심 웹 설계 실무입니다 [1, 2]. 성능 측면에서는 CSS 렌더링 차단을 방지하고 리플로우(Reflow)와 리페인트(Repaint)를 줄임으로써 코어 웹 바이탈([[Core Web Vitals|Core Web Vitals]]) 지표를 높이는 데 집중합니다 [3-6]. 동시에 접근성 측면에서는 시각적 명확성을 확보하고, 사용자의 화면 확대나 애니메이션 축소 설정을 존중하여 포용력 있는 사용자 경험(UX)을 구축하는 것을 목표로 합니다 [2, 7, 8].
## 매 한 줄
> **"매 a11y 의 의 minority feature 의 의 — 매 keyboard / screen reader / high contrast user 의 의 majority 의 의 better UX."**. WCAG 2.2 (2023) + WCAG 3 (draft 2026) 의 의 standard, ARIA 1.3, Core Web Vitals (LCP/INP/CLS) 의 modern user-centric performance metric. 매 2026 의 의 INP (Interaction to Next Paint, 2024 replaced FID) 의 의 main interaction metric 의 의.
## 📖 구조화된 지식 (Synthesized Content)
**성능 최적화 (Performance [[Optimization|Optimization]])**
* **CSS 로딩 및 렌더링 최적화:** 브라우저는 CSS를 모두 파싱하기 전까지 페이지 렌더링을 차단합니다 [4]. 이를 최소화하기 위해 사용하지 않는 CSS를 제거하고 파일을 축소 및 압축해야 하며, 미디어 쿼리를 사용해 화면 조건에 맞는 CSS 파일만 렌더링을 차단하도록 분리할 수 있습니다 [4, 9, 10]. 또한, `rel="preload"`를 사용해 중요한 폰트, CSS, 이미지 등의 핵심 자원을 우선적으로 다운로드하도록 브라우저에 지시해야 합니다 [11, 12].
* **레이아웃 연산 격리 및 최적화:** CSS Containment 모듈의 `contain``content-visibility` 속성을 사용하면 페이지의 특정 부분을 격리하여 브라우저가 뷰포트 내에 필요할 때만 렌더링을 수행하게 함으로써 렌더링 성능을 크게 향상시킬 수 있습니다 [13, 14].
* **리플로우(Reflow)와 리페인트(Repaint) 최소화:** `width`, `height`, `margin`, `box-shadow` 등의 레이아웃이나 시각적 속성을 애니메이션으로 처리하면 브라우저가 화면을 계속 다시 계산하고 그려야 하므로 심각한 성능 저하가 발생합니다 [5, 15, 16]. 부드러운 애니메이션을 구현하려면 GPU 가속의 이점을 받을 수 있는 `transform``opacity` 속성만을 사용해야 합니다 [15, 17-19].
* **미디어 및 폰트 성능 향상:** 코어 웹 바이탈의 LCP(최대 콘텐츠 풀 페인트)와 CLS(누적 레이아웃 이동)를 개선하기 위해 이미지에 WebP나 AVIF 같은 최신 포맷을 사용하고, `width`, `height`, 또는 `aspect-ratio` 속성을 명시하여 레이아웃 흔들림을 방지해야 합니다 [6, 20-22]. 폰트의 경우 `unicode-range`를 통한 서브세팅으로 필요한 글리프(glyph)만 로드하고, `font-display: swap`을 활용해 로드 전에도 텍스트가 보이도록 처리합니다 [13, 23].
## 매 핵심
**웹 접근성 (Web [[Accessibility|Accessibility]])**
* **유동적 타이포그래피([[Fluid Typography|Fluid Typography]])의 확대 보장:** 글꼴 크기를 뷰포트 단위(`vw` 등)로만 설정하면 사용자가 브라우저에서 텍스트 확대를 시도할 때 크기가 커지지 않아 WCAG(웹 콘텐츠 접근성 지침) 기준(텍스트 최소 200% 확대)을 위반하게 됩니다 [8]. 이 문제를 해결하려면 `clamp()` 함수 내부에 `em`이나 `rem` 단위와 뷰포트 단위를 조합하여 계산(`calc()`)함으로써, 사용자의 기본 글꼴 크기 설정과 확대(Zoom) 기능을 모두 보장해야 합니다 [24-26].
* **안전하고 제어 가능한 애니메이션:** 화려하거나 과도한 움직임은 전정기관 장애가 있는 사용자에게 메스꺼움이나 주의 산만을 유발할 수 있습니다 [27, 28]. `prefers-reduced-motion` 미디어 쿼리를 사용하여 운영체제에서 애니메이션 축소를 설정한 사용자에게는 움직임을 제거하거나 최소화한 스타일을 제공해야 하며, 긴 텍스트 블록에 대한 애니메이션 적용은 피해야 합니다 [27, 29, 30].
* **모바일 및 보조 기기 호환성 확보:** 터치 인터페이스에서는 오작동을 막기 위해 최소 44x44px ~ 48x48px 크기의 클릭 가능한 영역(패딩 활용)을 제공해야 합니다 [31-33]. 또한, 화면 판독기(Screen Reader)와 키보드 사용자를 위해 명확한 포커스(Focus) 상태 제공, 시맨틱 HTML 태그 사용, 적절한 색상 대비 유지, 의미 있는 대체 텍스트(alt) 속성이 반드시 포함되어야 합니다 [2, 34].
### 매 WCAG 2.2 의 4 principle (POUR)
- **Perceivable**: alt text, captions, contrast 4.5:1 (AA) / 7:1 (AAA).
- **Operable**: keyboard navigable, focus visible, no seizure-inducing flash.
- **Understandable**: clear language, error messages, predictable.
- **Robust**: valid HTML, ARIA properly used, works across AT.
## 🔗 지식 연결 (Graph)
- **Related Topics:** [[CSS 구조 설계 방식|CSS 구조 설계 방식]], 반응형 디자인, 애니메이션 (transition / keyframes), Core Web Vitals, [[리플로우 및 리페인트 (Reflow & Repaint)|리플로우 및 리페인트(Reflow & Repaint]]
- **Projects/Contexts:** 디자인 시스템 기반의 확장 가능한 프론트엔드 아키텍처 구축
- **Contradictions/Notes:** 소스 자료들은 애니메이션 성능 최적화를 위해 브라우저에 변경을 미리 알리는 `will-change` 속성의 사용을 제안하지만, 동시에 이를 남용하면 너무 많은 요소에 브라우저 자원을 미리 할당하여 오히려 성능 저하를 초래할 수 있으므로 '최후의 수단'으로 신중히 사용해야 한다고 경고하고 있습니다 [35, 36].
### 매 Core Web Vitals (2026)
- **LCP (Largest Contentful Paint)**: < 2.5s — main content visible.
- **INP (Interaction to Next Paint)**: < 200ms — responsiveness (replaces FID).
- **CLS (Cumulative Layout Shift)**: < 0.1 — visual stability.
---
*Last updated: 2026-04-26*
### 매 응용
1. Public sector — WCAG AA 의 의 (ADA, EU EN 301 549).
2. E-commerce — checkout 의 keyboard accessibility (2024 EAA mandate).
3. SEO — Core Web Vitals 의 Google ranking factor.
4. AI tooling — voice / dictation / screen reader user 의 의 의.
## 📌 한 줄 통찰 (The Karpathy Summary)
## 💻 패턴
> *(TODO: 한 문장으로 핵심 통찰을 작성. "X는 Y 조건에서 Z 효과를 낸다" 구조 권장.)*
### Semantic HTML + ARIA
```html
<!-- 매 BAD: div soup -->
<div class="button" onclick="submit()">Submit</div>
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
**언제 이 지식을 쓰는가:**
- *(TODO)*
**언제 쓰면 안 되는가:**
- *(TODO)*
## 🧪 검증 상태 (Validation)
- **정보 상태:** needs_review
- **출처 신뢰도:** A
- **검토 이유:** *(P-Reinforce Phase 1 자동 정규화. 본문 검증 필요.)*
## 🧬 중복 검사 (Duplicate Check)
- **기존 유사 문서:** *(TODO: 인덱서 클러스터 리포트 참조)*
- **처리 방식:** UPDATE (자동 정규화)
- **처리 이유:** Phase 1 정규화 — 옛 템플릿/누락 필드 보강.
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
- **과거 데이터와의 충돌:** 없음
- **정책 변화:** 없음
## 🕓 변경 이력 (Changelog)
| 날짜 | 변경 내용 | 처리 방식 | 신뢰도 |
|------|-----------|-----------|--------|
| 2026-05-08 | P-Reinforce Phase 1 정규화 (frontmatter + 헤더 표준화) | UPDATE | A |
## 💻 코드 패턴 (Code Patterns)
**패턴 1:** *(TODO: 이 프로젝트 컨벤션 반영한 구조 스켈레톤)*
```text
# TODO
<!-- 매 GOOD: semantic + accessible -->
<button type="submit" aria-describedby="submit-help">
Submit
</button>
<p id="submit-help" class="text-sm">매 reset 의 의 의.</p>
```
## 🤔 의사결정 기준 (Decision Criteria)
### Focus management (modal trap)
```tsx
import { useEffect, useRef } from 'react';
import FocusTrap from 'focus-trap-react';
**선택 A를 써야 할 때:**
- *(TODO)*
export function Modal({ open, onClose, children }: Props) {
const closeRef = useRef<HTMLButtonElement>(null);
**선택 B를 써야 할 때:**
- *(TODO)*
useEffect(() => {
if (open) closeRef.current?.focus();
const onKey = (e: KeyboardEvent) => e.key === 'Escape' && onClose();
window.addEventListener('keydown', onKey);
return () => window.removeEventListener('keydown', onKey);
}, [open, onClose]);
**기본값:**
> *(TODO)*
if (!open) return null;
return (
<FocusTrap>
<div role="dialog" aria-modal="true" aria-labelledby="modal-title">
<h2 id="modal-title">Settings</h2>
{children}
<button ref={closeRef} onClick={onClose}>Close</button>
</div>
</FocusTrap>
);
}
```
## ❌ 안티패턴 (Anti-Patterns)
### LCP optimization (image priority)
```tsx
// Next 15 의 의
import Image from 'next/image';
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
<Image
src="/hero.webp"
alt="Product showcase"
width={1200}
height={630}
priority // 매 LCP image 의 의 preload
fetchPriority="high"
sizes="(max-width: 768px) 100vw, 1200px"
/>
```
### INP optimization (yield to main thread)
```ts
// 매 long task 의 의 의 break up
async function processLargeList(items: Item[]) {
const CHUNK = 100;
for (let i = 0; i < items.length; i += CHUNK) {
items.slice(i, i + CHUNK).forEach(process);
// 매 yield to browser — keep INP < 200ms
await scheduler.yield?.() ?? new Promise(r => setTimeout(r, 0));
}
}
// React 19 useTransition
function Search() {
const [isPending, startTransition] = useTransition();
const [results, setResults] = useState([]);
function onChange(q: string) {
startTransition(() => {
setResults(filter(largeList, q)); // 매 deprioritize
});
}
return <input onChange={e => onChange(e.target.value)} />;
}
```
### CLS prevention (reserve space)
```css
/* 매 explicit aspect ratio — image / video 의 layout shift 의 */
.media {
aspect-ratio: 16 / 9;
width: 100%;
background: #eee;
}
/* 매 font 의 layout shift — size-adjust + fallback metric */
@font-face {
font-family: 'Inter';
src: url('/inter.woff2') format('woff2');
size-adjust: 107%;
ascent-override: 90%;
font-display: swap;
}
```
### Color contrast check
```ts
// 매 WCAG 의 의 contrast ratio
function contrastRatio(fg: string, bg: string): number {
const lum = (hex: string) => {
const [r, g, b] = hex.match(/\w\w/g)!.map(h => parseInt(h, 16) / 255);
const lin = (c: number) =>
c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
return 0.2126 * lin(r) + 0.7152 * lin(g) + 0.0722 * lin(b);
};
const [l1, l2] = [lum(fg), lum(bg)].sort((a, b) => b - a);
return (l1 + 0.05) / (l2 + 0.05); // ≥ 4.5 for AA, ≥ 7 for AAA
}
```
### Automated testing (axe-core + Playwright)
```ts
import { test, expect } from '@playwright/test';
import { injectAxe, checkA11y } from 'axe-playwright';
test('homepage 의 a11y', async ({ page }) => {
await page.goto('/');
await injectAxe(page);
await checkA11y(page, undefined, {
detailedReport: true,
axeOptions: { runOnly: ['wcag2a', 'wcag2aa', 'wcag22aa'] },
});
});
```
### Skip link + landmarks
```html
<a href="#main" class="skip-link">매 본문으로 건너뛰기</a>
<header role="banner">...</header>
<nav role="navigation" aria-label="Primary">...</nav>
<main id="main" tabindex="-1">...</main>
<footer role="contentinfo">...</footer>
<style>
.skip-link {
position: absolute; left: -9999px;
}
.skip-link:focus {
left: 0; top: 0; z-index: 100; padding: 1rem;
}
</style>
```
## 매 결정 기준
| 상황 | Approach |
|---|---|
| Public sector / regulated | WCAG 2.2 AA mandatory + 3rd party audit |
| E-commerce | INP optimization (form/checkout) + keyboard nav |
| Marketing site | LCP < 2s + image priority + Next Image |
| SPA / dashboard | Focus management + ARIA live regions |
| Form-heavy | Error association (aria-describedby) + autocomplete |
| Animation-heavy | prefers-reduced-motion + INP budget |
**기본값**: Semantic HTML + axe-core CI + Lighthouse 의 LCP/INP/CLS budget + manual screen reader test (NVDA/VoiceOver) per release.
## 🔗 Graph
- 부모: [[Frontend_Architecture]] · [[Web_Standards]]
- 변형: [[WCAG_2_2]] · [[ARIA]]
- 응용: [[Core-Web-Vitals]] · [[Lighthouse]] · [[Screen_Reader_Testing]]
- Adjacent: [[Inclusive_Design]] · [[Universal_Design]]
## 🤖 LLM 활용
**언제**: ARIA pattern lookup, semantic HTML refactor, WCAG criteria explanation, axe rule remediation.
**언제 X**: 의 actual screen reader UX evaluation (의 user testing 의 의), legal compliance ruling.
## ❌ 안티패턴
- **`<div onclick>`**: keyboard / screen reader 의 의.
- **Color-only signal**: red error 의 — icon / text label 의 의.
- **Auto-focus on load**: 매 disorienting — modal 의 의 의 의.
- **`outline: none` 의 focus state 의 X**: keyboard user 의 의 의 의.
- **Lazy-load LCP image**: 매 LCP 의 의 — `loading="eager"` + `fetchpriority="high"`.
- **`tabindex` 의 의 (>0)**: tab order 의 의 의.
## 🧪 검증 / 중복
- Verified (W3C WCAG 2.2 spec, web.dev Core Web Vitals, axe-core rules, MDN ARIA Authoring Practices).
- 신뢰도 A.
## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — a11y + Core Web Vitals (INP) 의 의 |