FE Accessibility Audit
$ARGUMENTS 로 전달된 파일의 접근성을 WCAG 2.1 AA 기준으로 검사한다.
검사 절차
-
대상 파일 읽기: 컴포넌트 코드를 분석한다
-
체크리스트 기반 검사: 8개 카테고리에 대해 검사한다
-
리포트 생성: 위반 사항과 수정 코드를 제시한다
검사 체크리스트
- 시맨틱 HTML
-
<div> /<span> 남용 대신 적절한 시맨틱 태그 사용
-
<nav> , <main> , <aside> , <header> , <footer> , <section> , <article>
-
<button> (클릭 가능 요소), <a> (네비게이션)
-
<ul> /<ol> (목록), <table> (표형 데이터)
-
헤딩 계층 순서 (h1 → h2 → h3 , 건너뛰기 금지)
-
<img> , <svg> 에 대체 텍스트
// Bad <div onClick={handleClick}>Submit</div>
// Good <button onClick={handleClick}>Submit</button>
- ARIA 속성
-
인터랙티브 커스텀 위젯에 적절한 role + ARIA 속성
-
aria-label , aria-labelledby — 시각적 레이블이 없는 요소
-
aria-describedby — 추가 설명이 필요한 요소
-
aria-expanded , aria-haspopup — 드롭다운/모달
-
aria-live — 동적 콘텐츠 업데이트 알림
-
aria-hidden="true" — 장식용 요소
// 토스트 알림 <div role="alert" aria-live="polite"> {message} </div>
// 아이콘 버튼 <button aria-label="Close dialog"> <XIcon aria-hidden="true" /> </button>
- 키보드 네비게이션
-
모든 인터랙티브 요소가 Tab으로 접근 가능
-
커스텀 위젯에 키보드 핸들러 (Enter , Space , Escape , 화살표키)
-
포커스 트랩 — 모달/다이얼로그 내 포커스 순환
-
Skip navigation 링크 (메인 콘텐츠로 바로 이동)
-
논리적인 탭 순서 (tabIndex 양수값 사용 금지)
// 모달 포커스 트랩 (shadcn/ui Dialog는 자동 지원) <Dialog> <DialogContent> {/* Tab 키가 이 안에서만 순환 */} </DialogContent> </Dialog>
- 색상 & 대비
-
텍스트 대비율 최소 4.5:1 (일반), 3:1 (큰 텍스트 18px+)
-
색상만으로 정보를 전달하지 않음 (아이콘, 텍스트 병행)
-
다크 모드에서도 대비율 충족
-
포커스 표시 (outline) 제거 금지 — focus-visible 사용
// Bad — 색상만으로 상태 표현 <span className={isError ? "text-red-500" : "text-green-500"}> {status} </span>
// Good — 아이콘 + 텍스트 병행 <span className={isError ? "text-red-500" : "text-green-500"}> {isError ? <AlertIcon aria-hidden="true" /> : <CheckIcon aria-hidden="true" />} {isError ? "Error: " : "Success: "}{status} </span>
- 폼 접근성
- <label>
- htmlFor 로 입력 필드와 연결
-
에러 메시지를 aria-describedby 로 연결
-
필수 필드에 aria-required="true" 또는 required
-
자동완성: autoComplete 속성 적절히 설정
-
유효성 검사 결과를 스크린리더에 전달
// shadcn/ui Form은 자동으로 접근성 처리 <FormField control={form.control} name="email" render={({ field }) => ( <FormItem> <FormLabel>Email</FormLabel> <FormControl> <Input {...field} autoComplete="email" /> </FormControl> <FormDescription>We'll never share your email.</FormDescription> <FormMessage /> {/* aria-describedby 자동 연결 */} </FormItem> )} />
- 이미지 & 미디어
-
정보를 전달하는 이미지: 의미 있는 alt 텍스트
-
장식용 이미지: alt="" 또는 aria-hidden="true"
-
복잡한 이미지 (차트, 그래프): 상세 설명 제공
-
Next.js <Image> 컴포넌트에 alt 필수
// 정보 전달 이미지 <Image src="/chart.png" alt="2024년 매출 추이: 1분기 100억, 2분기 150억" />
// 장식용 이미지 <Image src="/bg-pattern.png" alt="" aria-hidden="true" />
- 동적 콘텐츠
-
로딩 상태: aria-busy="true" , 로딩 안내 텍스트
-
페이지 전환: 포커스를 새 콘텐츠로 이동
-
무한 스크롤: 대안 네비게이션 제공 (페이지네이션)
-
토스트/알림: role="alert" 또는 aria-live="polite"
- shadcn/ui 접근성 패턴
shadcn/ui는 Radix UI 기반으로 대부분의 접근성이 내장되어 있지만, 확인해야 할 사항:
- Dialog : DialogTitle
- DialogDescription 필수
-
DropdownMenu : 트리거 버튼에 명확한 레이블
-
Toast : aria-live 영역 설정
-
Tooltip : 키보드 포커스로 표시 가능
-
Tabs : 화살표 키 네비게이션 동작 확인
-
Sheet : 포커스 트랩 + ESC로 닫기
리포트 형식
Accessibility Audit: [파일명]
요약
- WCAG 2.1 AA 준수율: [N]%
- 위반: N개 (Critical: N, Major: N, Minor: N)
Critical (WCAG A 위반)
[A1] 이슈 제목
- 기준: WCAG [번호] [이름]
- 위치:
파일:라인 - 문제: 설명
- 수정안: 코드
Major (WCAG AA 위반)
...
Minor (개선 권장)
...
통과 항목
- ...
실행 규칙
-
인자가 없으면 사용자에게 검사 대상을 질문한다
-
shadcn/ui 컴포넌트 사용 여부를 확인하고, 내장 접근성 기능을 고려한다
-
수정안에는 항상 구체적인 코드를 포함한다
-
자동 테스트로 잡을 수 없는 수동 검증 항목도 안내한다