Preflight logoPreflight

접근성 점검 샘플 리포트

가상의 노트·이미지 공유 SaaS 시나리오로 만든 예시입니다. 실제 리포트는 인터뷰 답변과 검사 결과에 맞춰 이런 형태로 생성됩니다.

샘플 리포트의 가상 앱 맥락

사용 환경
모바일 우선
핵심 task
콘텐츠 읽기·검색글쓰기·편집파일 업로드
한국어 비중
거의 전부
이전 점검
자동 도구만 써봤음
단계
출시 직전

예시 데이터입니다. 한국어 비중이 “거의 전부”라 각 항목에 KWCAG ID도 함께 표시됩니다.

지금 막아야 할 것(2)

이미지 업로드 버튼이 키보드로 활성화되지 않습니다

axe rule: button-name · WCAG 2.1.1 · KWCAG 5.3.1

`input[type="file"]`을 시각적으로 숨기고 styled `label`만 노출했지만 `label`에 `role="button"`이 없고 `Enter`·`Space` 키 핸들러도 없습니다. 키보드 사용자와 스크린리더 사용자는 이미지 첨부 자체가 불가능합니다. `파일 업로드`가 핵심 task로 지정돼 있어 BLOCK입니다.

위치 (selector)
label.upload-btn > input[type="file"]
수정 방향
`label`에 `role="button"`과 `tabindex="0"`을 추가하고 `Enter`·`Space` 키 핸들러로 `input` 클릭을 트리거하세요. 또는 `input`을 `sr-only`로 두고 자연스럽게 키보드 포커스를 받도록 처리하세요.
노트 작성 영역이 스크린리더에 라벨 없이 노출됩니다

axe rule: aria-input-field-name · WCAG 4.1.2 · KWCAG 7.1.1

`contenteditable` div에 `aria-label`이나 연결된 `label`이 없어 NVDA·VoiceOver가 "편집 영역"으로만 읽습니다. 무엇을 입력하는 자리인지 알 수 없어 스크린리더 사용자는 글쓰기를 시작조차 할 수 없습니다. `글쓰기·편집`이 핵심 task로 지정돼 있어 BLOCK입니다.

위치 (selector)
div[contenteditable="true"].note-editor
수정 방향
`contenteditable` 요소에 `aria-label="노트 본문"` 또는 `aria-labelledby`로 외부 헤딩과 연결하세요. 동시에 `role="textbox"` + `aria-multiline="true"`를 추가해 의미를 명확히 하세요.

출시 전 수정(3)

검색·태그 입력의 라벨이 placeholder로만 표현됩니다
4

axe rule: label · WCAG 3.3.2 · KWCAG 7.3.4

`placeholder`는 입력이 시작되면 사라지고, 일부 스크린리더 설정에서는 라벨로 인식되지 않습니다. 입력 중 사용자가 무엇을 적고 있었는지 잊어도 다시 확인할 단서가 없습니다.

위치 (selector)
input.search-input, input.tag-input
수정 방향
`<label htmlFor>` 또는 `aria-label`을 추가하세요. 시각적으로 placeholder만 노출하고 싶다면 label은 `sr-only` 클래스로 숨겨도 접근성 정보는 유지됩니다.

같은 패턴이 4에서 반복됩니다. 한 컴포넌트만 고치면 한 번에 해결될 가능성이 큽니다.

버튼·링크의 포커스 표시가 디자인 변경으로 사라졌습니다
12

axe rule: focus-visible · WCAG 2.4.7 · KWCAG 5.4.7

키보드 사용자는 지금 어디에 포커스가 있는지 시각적으로 확인할 수 없습니다. `Tab`으로 이동하다 길을 잃기 쉽고, 잘못된 버튼을 활성화할 위험이 있습니다.

위치 (selector)
button.btn-primary, a.nav-link
수정 방향
전역 CSS에 `:focus-visible { outline: 2px solid; outline-offset: 2px; }`를 적용하세요. Tailwind면 `focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-ring`으로 같은 효과를 얻습니다.

같은 패턴이 12에서 반복됩니다. 한 컴포넌트만 고치면 한 번에 해결될 가능성이 큽니다.

노트 카드 메타 정보의 `<dt>`·`<dd>`가 부모 `<dl>` 없이 떠있습니다
24

axe rule: dlitem · WCAG 1.3.1 · KWCAG 5.3.1

정의 목록(definition list)의 `<dt>`(term)·`<dd>`(description)는 `<dl>` 부모 안에서만 의미를 가집니다. 부모 없이 떠있으면 스크린리더가 "태그·작성일·작성자"의 짝 관계를 인식하지 못해 의미 손실이 발생합니다.

위치 (selector)
article.note-card > dt, article.note-card > dd
수정 방향
메타 정보를 `<dl>` 한 쌍으로 감싸세요. 노트 카드 컴포넌트 한 곳만 수정하면 모든 카드에서 한 번에 해결됩니다.

같은 패턴이 24에서 반복됩니다. 한 컴포넌트만 고치면 한 번에 해결될 가능성이 큽니다.

전문가·보조기술 시험 권장(2)

에러 메시지의 인지 접근성 검토가 필요합니다
8

axe rule: aria-valid-attr-value

`role="alert"` 속성 자체는 자동 검출로 확인되지만, 메시지 *내용*이 사용자에게 이해되는지는 자동 검출 범위 밖입니다. 현재 메시지가 "Network request failed", "Validation error: invalid_input" 같은 기술 용어로 노출돼 일반 사용자·인지 접근성 측면에서 별 검토가 필요합니다.

위치 (selector)
div[role="alert"]
수정 방향
각 에러 메시지를 "무엇이 일어났는지 / 사용자가 다음에 할 수 있는 것" 두 줄로 다시 쓰세요. 예: "이미지 저장에 실패했어요. 잠시 후 다시 시도해 주세요." 콘텐츠 디자이너와 함께 검토 권장.

같은 패턴이 8에서 반복됩니다. 한 컴포넌트만 고치면 한 번에 해결될 가능성이 큽니다.

노트 무한 스크롤의 스크린리더 실사용 시험을 권장합니다

axe rule: aria-busy

`aria-busy` 속성은 자동 검출로 문법 검증이 되지만 실제 사용감은 보지 못합니다. 무한 스크롤은 스크린리더 사용자에게 끝없이 새 항목이 추가되는 흐름이라 "리스트 끝에 도달했다"는 신호가 없으면 사용자가 갇힐 수 있습니다.

위치 (selector)
main[aria-busy] > article.note-card
수정 방향
NVDA(Windows) 또는 VoiceOver(macOS)로 직접 노트 피드를 탐색해 보세요. 페이지네이션이나 "더 보기" 버튼을 옵션으로 제공하는 것도 검토할 만합니다. 보조기술 사용자 1~2명 인터뷰 권장.

이미 결정한 trade-off(2)

보조 텍스트(`text-muted-foreground`)의 명암비가 AA-Large만 통과합니다
18

axe rule: color-contrast

(이미 결정한 trade-off) 본문·핵심 정보엔 사용하지 않고 메타·시간·라벨에만 한정. 인터랙션 컨트롤에는 사용 금지.

DESIGN.md §1.1

text-muted-foreground는 약 3.44:1 — AA-Large(3:1)만 통과. shadcn/ui 디폴트 토큰이고 우리도 그 판단을 유지한다. 본문·핵심 정보엔 사용하지 않는다.

"확인됨" 배지의 명암비는 의도한 hierarchy로 낮게 유지합니다
3

axe rule: color-contrast

(이미 결정한 trade-off) Solid destructive 변형(흰 글자)은 액션 버튼에만 사용. 상태 배지는 약한 톤 유지로 hierarchy 분리.

DESIGN.md §2.17

카드 안의 "확인됨" 배지는 destructive variant — Solid 섹션 pill과 weight 차이로 hierarchy를 만든다. primary action이 아니므로 약한 톤 의도.

접근성 점검은 Lighthouse 한 번과 인터뷰 1분.

내 앱의 접근성 점검 시작하기보안 점검 샘플도 보기