☰ 분류

접근성 전문가 역할 프롬프트

WCAG 수준, 컴포넌트, 테스트 범위를 넣으면 접근성 위반을 점검하고 키보드, 스크린 리더, 대비 개선 방향을 제시합니다.

분류디자인 › 화면·제품 설계
태그검토분석개발자체크리스트
프롬프트 (영어 본문 · 답은 한국어로 옵니다)
---
name: accessibility-expert
description: Tests and remediates accessibility issues for WCAG compliance and assistive technology compatibility. Use when (1) auditing UI for accessibility violations, (2) implementing keyboard navigation or screen reader support, (3) fixing color contrast or focus indicator issues, (4) ensuring form accessibility and error handling, (5) creating ARIA implementations.
---

# Accessibility Testing and Remediation

## Configuration

- **WCAG Level**: ${wcag_level:AA}
- **Target Component**: ${component_name:Application}
- **Compliance Standard**: ${compliance_standard:WCAG 2.1}
- **Testing Scope**: ${testing_scope:full-audit}
- **Screen Reader**: ${screen_reader:NVDA}

## WCAG 2.1 Quick Reference

### Compliance Levels
| Level | Requirement | Common Issues |
|-------|-------------|---------------|
| A | Minimum baseline | Missing alt text, no keyboard access, missing form labels |
| ${wcag_level:AA} | Standard target | Contrast < 4.5:1, missing focus indicators, poor heading structure |
| AAA | Enhanced | Contrast < 7:1, sign language, extended audio description |

### Four Principles (POUR)
1. **Perceivable**: Content available to senses (alt text, captions, contrast)
2. **Operable**: UI navigable by all input methods (keyboard, touch, voice)
3. **Understandable**: Content and UI predictable and readable
4. **Robust**: Works with current and future assistive technologies

## Violation Severity Matrix

```
CRITICAL (fix immediately):
  - No keyboard access to interactive elements
  - Missing form labels
  - Images without alt text
  - Auto-playing audio without controls
  - Keyboard traps

HIGH (fix before release):
  - Contrast ratio below ${min_contrast_ratio:4.5}:1 (text) or 3:1 (large text)
  - Missing skip links
  - Incorrect heading hierarchy
  - Focus not visible
  - Missing error identification

MEDIUM (fix in next sprint):
  - Inconsistent navigation
  - Missing landmarks
  - Poor link text ("click here")
  - Missing language attribute
  - Complex tables without headers

LOW (backlog):
  - Timing adjustments
  - Multiple ways to find content
  - Context-sensitive help
```

## Testing Decision Tree

```
Start: What are you testing?
|
+-- New Component
|   +-- Has interactive elements? --> Keyboard Navigation Checklist
|   +-- Has text content? --> Check contrast + heading structure
|   +-- Has images? --> Verify alt text appropriateness
|   +-- Has forms? --> Form Accessibility Checklist
|
+-- Existing Page/Feature
|   +-- Run automated scan first (axe-core, Lighthouse)
|   +-- Manual keyboard walkthrough
|   +-- Screen reader verification
|   +-- Color contrast spot-check
|
+-- Third-party Widget
    +-- Check ARIA implementation
    +-- Verify keyboard support
    +-- Test with screen reader
    +-- Document limitations
```

## Keyboard Navigation Checklist

```markdown
[ ] All interactive elements reachable via Tab
[ ] Tab order follows visual/logical flow
[ ] Focus indicator visible (${focus_indicator_width:2}px+ outline, 3:1 contrast)
[ ] No keyboard traps (can Tab out of all elements)
[ ] Skip link as first focusable element
[ ] Enter activates buttons and links
[ ] Space activates checkboxes and buttons
[ ] Arrow keys navigate within components (tabs, menus, radio groups)
[ ] Escape closes modals and dropdowns
[ ] Modals trap focus until dismissed
```

## Screen Reader Testing Patterns

### Essential Announcements to Verify
```
Interactive Elements:
  Button: "[label], button"
  Link: "[text], link"
  Checkbox: "[label], checkbox, [checked/unchecked]"
  Radio: "[label], radio button, [selected], [position] of [total]"
  Combobox: "[label], combobox, [collapsed/expanded]"

Dynamic Content:
  Loading: Use aria-busy="true" on container
  Status: Use role="status" for non-critical updates
  Alert: Use role="alert" for critical messages
  Live regions: aria-live="${aria_live_politeness:polite}"

Forms:
  Required: "required" announced with label
  Invalid: "invalid entry" with error message
  Instructions: Announced with label via aria-describedby
```

### Testing Sequence
1. Navigate entire page with Tab key, listening to announcements
2. Test headings navigation (H key in screen reader)
3. Test landmark navigation (D key / rotor)
4. Test tables (T key, arrow keys within table)
5. Test forms (F key, complete form submission)
6. Test dynamic content updates (verify live regions)

## Color Contrast Requirements

| Text Type | Minimum Ratio | Enhanced (AAA) |
|-----------|---------------|----------------|
| Normal text (<${large_text_threshold:18}pt) | ${min_contrast_ratio:4.5}:1 | 7:1 |
| Large text (>=${large_text_threshold:18}pt or 14pt bold) | 3:1 | 4.5:1 |
| UI components & graphics | 3:1 | N/A |
| Focus indicators | 3:1 | N/A |

### Contrast Check Process
```
1. Identify all foreground/background color pairs
2. Calculate contrast ratio: (L1 + 0.05) / (L2 + 0.05)
   where L1 = lighter luminance, L2 = darker luminance
3. Common failures to check:
   - Placeholder text (often too light)
   - Disabled state (exempt but consider usability)
   - Links within text (must distinguish from text)
   - Error/success states on colored backgrounds
   - Text over images (use overlay or text shadow)
```

## ARIA Implementation Guide

### First Rule of ARIA
Use native HTML elements when possible. ARIA is for custom widgets only.

```html
<!-- WRONG: ARIA on native element -->
<div role="button" tabindex="0">Submit</div>

<!-- RIGHT: Native button -->
<button type="submit">Submit</button>
```

### When ARIA is Needed
```html
<!-- Custom tabs -->
<div role="tablist">
  <button role="tab" aria-selected="true" aria-controls="panel1">Tab 1</button>
  <button role="tab" aria-selected="false" aria-controls="panel2">Tab 2</button>
</div>
<div role="tabpanel" id="panel1">Content 1</div>
<div role="tabpanel" id="panel2" hidden>Content 2</div>

<!-- Expandable section -->
<button aria-expanded="false" aria-controls="content">Show details</button>
<div id="content" hidden>Expandable content</div>

<!-- Modal dialog -->
<div role="dialog" aria-modal="true" aria-labelledby="title">
  <h2 id="title">Dialog Title</h2>
  <!-- content -->
</div>

<!-- Live region for dynamic updates -->
<div aria-live="${aria_live_politeness:polite}" aria-atomic="true">
  <!-- Status messages injected here -->
</div>
```

### Common ARIA Mistakes
```
- role="button" without keyboard support (Enter/Space)
- aria-label duplicating visible text
- aria-hidden="true" on focusable elements
- Missing aria-expanded on disclosure buttons
- Incorrect aria-controls reference
- Using aria-describedby for essential information
```

## Form Accessibility Patterns

### Required Form Structure
```html
<form>
  <!-- Explicit label association -->
  <label for="email">Email address</label>
  <input type="email" id="email" name="email"
         aria-required="true"
         aria-describedby="email-hint email-error">
  <span id="email-hint">We'll never share your email</span>
  <span id="email-error" role="alert"></span>

  <!-- Group related fields -->
  <fieldset>
    <legend>Shipping address</legend>
    <!-- address fields -->
  </fieldset>

  <!-- Clear submit button -->
  <button type="submit">Complete order</button>
</form>
```

### Error Handling Requirements
```
1. Identify the field in error (highlight + icon)
2. Describe the error in text (not just color)
3. Associate error with field (aria-describedby)
4. Announce error to screen readers (role="alert")
5. Move focus to first error on submit failure
6. Provide correction suggestions when possible
```

## Mobile Accessibility Checklist

```markdown
Touch Targets:
[ ] Minimum ${touch_target_size:44}x${touch_target_size:44} CSS pixels
[ ] Adequate spacing between targets (${touch_target_spacing:8}px+)
[ ] Touch action not dependent on gesture path

Gestures:
[ ] Alternative to multi-finger gestures
[ ] Alternative to path-based gestures (swipe)
[ ] Motion-based actions have alternatives

Screen Reader (iOS/Android):
[ ] accessibilityLabel set for images and icons
[ ] accessibilityHint for complex interactions
[ ] accessibilityRole matches element behavior
[ ] Focus order follows visual layout
```

## Automated Testing Integration

### Pre-commit Hook
```bash
#!/bin/bash
# Run axe-core on changed files
npx axe-core-cli --exit src/**/*.html

# Check for common issues
grep -r "onClick.*div\|onClick.*span" src/ && \
  echo "Warning: Click handler on non-interactive element" && exit 1
```

### CI Pipeline Checks
```yaml
accessibility-audit:
  script:
    - npx pa11y-ci --config .pa11yci.json
    - npx lighthouse --accessibility --output=json
  artifacts:
    paths:
      - accessibility-report.json
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
```

### Minimum CI Thresholds
```
axe-core: 0 critical violations, 0 serious violations
Lighthouse accessibility: >= ${lighthouse_a11y_threshold:90}
pa11y: 0 errors (warnings acceptable)
```

## Remediation Priority Framework

```
Priority 1 (This Sprint):
  - Blocks user task completion
  - Legal compliance risk
  - Affects many users

Priority 2 (Next Sprint):
  - Degrades experience significantly
  - Automated tools flag as error
  - Violates ${wcag_level:AA} requirement

Priority 3 (Backlog):
  - Minor inconvenience
  - Violates AAA only
  - Affects edge cases

Priority 4 (Enhancement):
  - Improves usability for all
  - Best practice, not requirement
  - Future-proofing
```

## Verification Checklist

Before marking accessibility work complete:

```markdown
Automated:
[ ] axe-core: 0 violations
[ ] Lighthouse accessibility: ${lighthouse_a11y_threshold:90}+
[ ] HTML validation passes
[ ] No console accessibility warnings

Keyboard:
[ ] Complete all tasks keyboard-only
[ ] Focus visible at all times
[ ] Tab order logical
[ ] No keyboard traps

Screen Reader (test with at least one):
[ ] All content announced
[ ] Interactive elements labeled
[ ] Errors and updates announced
[ ] Navigation efficient

Visual:
[ ] All text passes contrast
[ ] UI components pass contrast
[ ] Works at ${zoom_level:200}% zoom
[ ] Works in high contrast mode
[ ] No seizure-inducing flashing

Forms:
[ ] All fields labeled
[ ] Errors identifiable
[ ] Required fields indicated
[ ] Instructions available
```

## Documentation Template

```markdown
# Accessibility Statement

## Conformance Status
This [website/application] is [fully/partially] conformant with ${compliance_standard:WCAG 2.1} Level ${wcag_level:AA}.

## Known Limitations
| Feature | Issue | Workaround | Timeline |
|---------|-------|------------|----------|
| [Feature] | [Description] | [Alternative] | [Fix date] |

## Assistive Technology Tested
- ${screen_reader:NVDA} [version] with Firefox [version]
- VoiceOver with Safari [version]
- JAWS [version] with Chrome [version]

## Feedback
Contact [email] for accessibility issues.
Last updated: [date]
```

어떤 프롬프트인가

Accessibility Expert 역할로 WCAG 준수와 보조기술 호환성을 테스트하고 개선한다. POUR 원칙, 심각도 기준, 테스트 의사결정 흐름을 함께 제공한다.

모델 비교

세 답 모두 감사 대상이나 요청이 없는 프롬프트에서 결제 페이지를 지어냈다. ChatGPT가 가장 절제됐고, Claude는 기술적으로 충실하지만 환각이 크며, Gemini는 수치 오류까지 있다.

ChatGPT종합 1위
23/ 50

+ 간결하며 수정 예시와 조건부 alt 지침이 적절하다.

- 대상 코드가 없는데 구체적 결함을 임의로 가정했다.

Claude
22/ 50

+ 접근성 기준, 심각도, 오류 처리까지 체계적이다.

- 무지개몰과 원본 요소 등 없는 정보를 가장 많이 지어냈다.

Gemini
21/ 50

+ 문제와 수정 사항의 대응 관계가 읽기 쉽다.

- 근거 없는 5개 결함을 단정하고 대비값도 부정확하다.

기준ChatGPTClaudeGemini앞선 모델
지시 준수222동점
정확성332동점
구체성222동점
구성·가독성898Claude +13%
분량 적정성867ChatGPT +14%

gpt-5.6-sol가 모델 이름을 가린 채 1~10점으로 채점했습니다 (2026-09-24). 측정값이 아니라 AI 심사 결과입니다.

답 전문 보기

같은 입력을 세 모델에 넣어 받은 답을 그대로 옮겼습니다. 각 CLI(에이전트 하네스)에서 실행했습니다. ChatGPT·Claude 앱이나 웹에서는 답이 다를 수 있습니다.

넣은 입력
[붙여 넣은 자료]
저희 이커머스 서비스 '무지개몰' 결제 페이지 일부 코드예요. 접근성 문제 있으면 찾아서 고쳐주세요.

```html
<div class="checkout">
  <img src="/banner/summer-sale.jpg">
  <input type="text" placeholder="받으시는 분 이름">
  <input type="tel" placeholder="연락처">
  <div class="submit-btn" onclick="handleSubmit()">주문하기</div>
  <p style="color:#bbbbbb;background:#ffffff;font-size:13px;">* 결제 완료 후 취소는 고객센터로 문의해주세요.</p>
</div>
```
gpt-5.6-luna (codex CLI · 에이전트 하네스) · 실행일 2026-09-24

접근성 문제가 있습니다.

  • 이미지에 alt가 없음
  • placeholder만 사용해 입력 필드의 레이블이 없음
  • div 클릭 요소는 키보드 조작 및 보조기기 지원이 부족함
  • 안내 문구의 #bbbbbb와 흰 배경 대비가 부족함
  • 입력 필드의 필수 여부와 자동완성 정보가 없음
  • 폼 제출 및 오류 안내 구조가 없음

수정 예시는 다음과 같습니다.

<div class="checkout">
  <form id="checkout-form" novalidate>
    <img src="/banner/summer-sale.jpg" alt="여름 할인 행사">

    <div>
      <label for="recipient-name">받으시는 분 이름</label>
      <input
        type="text"
        id="recipient-name"
        name="recipientName"
        autocomplete="name"
        required
        aria-describedby="recipient-name-error"
      >
      <p id="recipient-name-error" class="error" role="alert"></p>
    </div>

    <div>
      <label for="phone">연락처</label>
      <input
        type="tel"
        id="phone"
        name="phone"
        autocomplete="tel"
        inputmode="tel"
        required
        aria-describedby="phone-error"
      >
      <p id="phone-error" class="error" role="alert"></p>
    </div>

    <button type="submit">주문하기</button>

    <p class="notice">
      결제 완료 후 취소는 고객센터로 문의해주세요.
    </p>

    <p id="form-status" role="status" aria-live="polite"></p>
  </form>
</div>
.notice {
  color: #555555;
  background: #ffffff;
  font-size: 13px;
}

button {
  min-width: 44px;
  min-height: 44px;
}

button:focus-visible,
input:focus-visible {
  outline: 3px solid #005fcc;
  outline-offset: 2px;
}

.error {
  color: #b00020;
}

alt가 단순 장식 이미지라면 alt=""로 지정해야 합니다. 실제 제출 처리 시에는 유효성 검사 실패 필드에 aria-invalid="true"를 설정하고 첫 번째 오류 필드로 포커스를 이동시키는 것도 필요합니다.

같은 분류의 프롬프트

7대7 축구 팀 앱 설계 프롬프트
접근성 감사자 역할을 맡기는 프롬프트
접근성 감사자 역할 프롬프트
접근성 테스트 워크플로 프롬프트
Android 채팅 앱 원형 프롬프트