Skip to content

[FIX] 웹접근성 개선#511

Merged
yyoonngg merged 10 commits intodevelopfrom
refactor/#489-improved-accessibility
Feb 25, 2026
Merged

[FIX] 웹접근성 개선#511
yyoonngg merged 10 commits intodevelopfrom
refactor/#489-improved-accessibility

Conversation

@yyoonngg
Copy link
Collaborator

@yyoonngg yyoonngg commented Feb 25, 2026

🚩 연관 이슈

closed #489

⏰ 우선순위(P1,P2,P3)

P1


🔧 작업 내용

WCAG 2.1 AA 기준에 따라 공통 컴포넌트 및 페이지 전반의 웹 접근성을 개선합니다.

공통 컴포넌트

  • TextInput / AmountInput: aria-invalid, aria-describedby로 에러 메시지 연결, role="alert" 추가
  • Dropdown: ESC / Enter / Space / ↑↓ / Tab 완전한 키보드 탐색 지원, aria-invalid 추가
  • InfoTooltip: useId() 고유 ID 생성, role="tooltip", aria-describedby, aria-expanded 추가
  • Loading: role="status", aria-busy="true", .sr-only 스크린리더 전용 텍스트 추가
  • DatePickerPopup: role="dialog", aria-modal, ESC 닫기, 네비게이션 버튼 aria-label 추가
  • Drawer: aria-current="page" 추가 — 스크린리더에 현재 페이지 위치 전달

레이아웃

  • ClientModal: useFocusTrap 포커스 트랩 적용, ESC 닫기, 모달 열기/닫기 시 포커스 복원
  • Toast / ToastProvider: variant별 role="alert"|"status", aria-live="assertive"|"polite" 분리
  • Notification: aria-haspopup="dialog", aria-expanded 추가
  • CalendarDayCell: aria-current="date", aria-expanded, aria-controls, <aside> 시맨틱 태그 적용
  • DataTable: scope="col", aria-sort, 정렬 컬럼 키보드 탐색 지원

페이지

  • Login 페이지: <header>, <main>, <section> 시맨틱 구조 적용
  • Settings / Saving / Forecast 등: 각 컴포넌트 aria-label, aria-hidden 정비

신규 훅

  • useFocusTrap: Tab/Shift+Tab을 컨테이너 내부에서만 순환 (WAI-ARIA Dialog Pattern)

글로벌

  • globals.css: .sr-only 유틸리티 클래스, prefers-reduced-motion 전역 처리 추가

📝 고민내용(선택)

ClientModal 포커스 관리 전략

모달이 닫힐 때 포커스를 복원하는 시점을 shouldRender === false로 감지했습니다.
isClosing 상태(애니메이션 중)에서는 복원하지 않고, 애니메이션이 끝나 실제로 DOM에서 제거된 후 복원하도록 하여 UX 흐름이 자연스럽게 유지됩니다.

dropdown variant는 포커스 트랩 미적용

dropdown variant는 이미 useOutsideClick으로 닫힘을 처리하고, 드롭다운 특성상 포커스가 외부로 이동해도 자연스럽습니다. 포커스 트랩은 overlay variant에만 적용했습니다.

🏞️ 스크린샷

**Lighthouse 접근성 점수 (Frontend Lighthouse CI 기준)

페이지 작업 전 작업 후
대시보드 87 92
달력 88 95
분석 90 96
예측 90 100
저금통 84 95
로그인 91 96

🗣️ 리뷰 요구사항

useFocusTrap 훅을 추가한 이유

WCAG 2.1 SC 2.1.2 No Keyboard Trap 및 WAI-ARIA Dialog Pattern에 따르면, 모달이 열린 동안 키보드 포커스는 반드시 모달 내부에 머물러야 합니다.

기존 ClientModaltabIndex={-1}로 프로그래밍적 포커스만 가능했고, Tab 키를 누르면 포커스가 모달 외부(배경 페이지)로 빠져나가는 문제가 있었습니다. 스크린리더 사용자는 모달이 열린 상태에서 배경 콘텐츠를 탐색하게 되어 문맥을 잃게 됩니다.

useFocusTrap은 Tab / Shift+Tab 이벤트를 가로채 포커스를 컨테이너 내부 첫 번째 ↔ 마지막 요소 사이에서만 순환시킵니다. 모달이 닫히면 리스너가 제거되고, 열기 전에 포커스가 있던 요소로 복원합니다.

@github-actions
Copy link

github-actions bot commented Feb 25, 2026

🧪 Test Report

📊 HTML Report: https://softeerbootcamp-7th.github.io/WEB-Team5-Moong/pr-511/

리포트에서 확인 가능:

  • ✅ 통과/실패한 테스트 목록
  • ⏱️ 각 테스트 실행 시간
  • 📝 에러 로그 및 스택 트레이스

Report generated at: 2026-02-25T14:59:27.740Z

@yyoonngg yyoonngg marked this pull request as draft February 25, 2026 01:35
@yyoonngg yyoonngg marked this pull request as ready for review February 25, 2026 12:49
@yyoonngg yyoonngg force-pushed the refactor/#489-improved-accessibility branch from e1f5832 to 8175a06 Compare February 25, 2026 12:51
@yyoonngg yyoonngg changed the title [REFACTOR] 웹접근성 개선 [FIX] 웹접근성 개선 Feb 25, 2026
@github-actions
Copy link

github-actions bot commented Feb 25, 2026

Lighthouse report ✨

Moong 성능측정

🟢: 90 - 100 / 🟠: 50 - 89 / 🔴: 0 - 49

로그인

/login

Category Score
🟢 Performance 96
🟢 Accessibility 96
🟢 Best Practices 96
🟢 SEO 100
🟢 First Contentful Paint 0.4 s
🟠 Largest Contentful Paint 1.3 s
🟢 Speed Index 0.8 s
🟢 Total Blocking Time 60 ms
🟢 Cumulative Layout Shift 0
온보딩

/onBoarding

Category Score
🟢 Performance 99
🟢 Accessibility 100
🟢 Best Practices 100
🟢 SEO 100
🟢 First Contentful Paint 0.3 s
🟢 Largest Contentful Paint 1.0 s
🟢 Speed Index 0.3 s
🟢 Total Blocking Time 0 ms
🟢 Cumulative Layout Shift 0
대시보드

/dashboard

Category Score
🟢 Performance 97
🟢 Accessibility 92
🟢 Best Practices 100
🟢 SEO 100
🟢 First Contentful Paint 0.3 s
🟠 Largest Contentful Paint 1.2 s
🟢 Speed Index 1.1 s
🟢 Total Blocking Time 20 ms
🟢 Cumulative Layout Shift 0.001
분석

/analysis

Category Score
🟢 Performance 96
🟢 Accessibility 96
🟢 Best Practices 100
🟢 SEO 100
🟢 First Contentful Paint 0.4 s
🟠 Largest Contentful Paint 1.4 s
🟢 Speed Index 0.9 s
🟢 Total Blocking Time 0 ms
🟢 Cumulative Layout Shift 0.005
캘린더

/calendar

Category Score
🟢 Performance 98
🟢 Accessibility 95
🟢 Best Practices 100
🟢 SEO 100
🟢 First Contentful Paint 0.3 s
🟢 Largest Contentful Paint 1.1 s
🟢 Speed Index 0.9 s
🟢 Total Blocking Time 0 ms
🟢 Cumulative Layout Shift 0
저축

/saving

Category Score
🟢 Performance 98
🟢 Accessibility 95
🟠 Best Practices 74
🟢 SEO 100
🟢 First Contentful Paint 0.3 s
🟢 Largest Contentful Paint 1.1 s
🟢 Speed Index 1.0 s
🟢 Total Blocking Time 0 ms
🟢 Cumulative Layout Shift 0.023
예측

/forecast

Category Score
🟢 Performance 97
🟢 Accessibility 100
🟢 Best Practices 100
🟢 SEO 100
🟢 First Contentful Paint 0.3 s
🟠 Largest Contentful Paint 1.2 s
🟢 Speed Index 1.0 s
🟢 Total Blocking Time 0 ms
🟢 Cumulative Layout Shift 0
가족관리

/family

Category Score
🟢 Performance 98
🟢 Accessibility 96
🟢 Best Practices 100
🟢 SEO 100
🟢 First Contentful Paint 0.3 s
🟢 Largest Contentful Paint 1.1 s
🟢 Speed Index 0.7 s
🟢 Total Blocking Time 0 ms
🟢 Cumulative Layout Shift 0
설정

/settings

Category Score
🟢 Performance 98
🟢 Accessibility 100
🟢 Best Practices 100
🟢 SEO 100
🟢 First Contentful Paint 0.3 s
🟢 Largest Contentful Paint 1.0 s
🟢 Speed Index 0.8 s
🟢 Total Blocking Time 0 ms
🟢 Cumulative Layout Shift 0

Copy link
Collaborator

@bonsng bonsng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/noti-fe 끝까지 작은 디테일에 신경 쓰시는 모습이 좋습니다!! Approve 하겠습니다!

const sortEntry = sortConfig?.find((s) => s.sortBy === col.accessor);
const isSorted = sortEntry !== undefined;
const handleClick = () => (isSortable ? onSort?.(col.accessor) : undefined);
const ariaSortValue = isSortable
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2) 이거 매핑 테이블로 분리해도 좋을거 같습니다! 체이닝이 좀 깊은거 같아서..

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 좋습니다! 이후 작업에서.. 진행하겠습니다 ㅎ

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오오 이렇게 모달 안에서 트랩할 수 있는거군요

@yyoonngg yyoonngg merged commit c7a9c67 into develop Feb 25, 2026
7 checks passed
@yyoonngg yyoonngg deleted the refactor/#489-improved-accessibility branch February 25, 2026 15:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[REFACTOR] 프론트엔드 접근성 개선

2 participants