Fix(a11y): Production Lighthouse 기반 전체 페이지 접근성 완성 — A11y 100점#7
Conversation
## 주요 변경사항
### Bug Fix
- TripDetailHeader: 호스트 버튼 직접 접근 시 깜빡임 버그 수정
- 서버 프리페치(null 토큰) → AppShell 토큰 복구 전 hostUserCheck=false 덮어쓰기 문제
- isAuthResolved(!!accessToken || isGuestUser) guard 추가
- isGuestUser 변수 섀도잉 버그 수정 (isGuestUser: isGuestUserStore 별칭)
- useAuth: loginPath redirect 미동작 버그 수정
- localStorage.getItem("loginPath") 읽기 전 removeItem 하던 문제
### Error Handling
- useTripDetail: createMutationOptions 적용 (update/delete mutation)
- useEnrollment: cancelMutation에 createMutationOptions 적용
### Accessibility (WCAG 2.1 AA)
- TripDetailPage: 스켈레톤 UI 추가 (auth 복구 대기 중 animate-pulse)
- TripDetailPage: 스크롤 컨테이너 role="region" + tabIndex=0 (scrollable-region-focusable 해결)
- TripDetailPage: 동행자 행 div→button 전환 + aria-label
- TripDetailPage: 댓글 FAB div→button 전환 + aria-label
- TripDetailHeader: 알림/공유/더보기 div→button 전환 + aria-label
- ApplyListButton: 북마크 버튼 aria-label 추가 (button-name critical 위반 해결)
### E2E / MSW
- tripDetail.spec.ts: 호스트 버튼 + 삭제 + axe 측정 스펙 작성
- enrollment.spec.ts, trip.spec.ts: MSW stateful mock 기반 재작성
- MSW routes 확장 (trip, misc)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
## 변경 내용
### 접근성 (axe WCAG 2 AA)
- globals.css: --color-text-muted #848484(3.67:1) → #6b6b6b(5.24:1), --color-text-muted2 #ababab(2.25:1) → #717171(4.80:1)
- EmailLoginForm: '처음 오셨나요?' inline #848484 → var(--color-text-muted) 클래스로 전환
- InfoText: 기본 색상 #ABABAB 하드코딩 → var(--color-text-muted2) CSS 변수 참조
- auth E2E axe 검사에 .exclude('nextjs-portal') 추가 (dev overlay 뱃지 제외)
### react-hook-form ref 연결 수정
- ValidationInputField: forwardRef 미적용으로 RHF ref가 DOM input에 미연결되어
getValues().email = undefined → zod "Required" 에러 발생하던 구조적 버그 수정
- forwardRef + onBlur prop 추가, ref를 StateInputField → <input> 까지 전달
### E2E 테스트
- fillReactInput 헬퍼: nativeInputValueSetter 우회 → locator.fill() 으로 단순화
- '로그인' 버튼 locator에 exact: true 추가 (소셜 로그인 버튼 strict mode 위반 수정)
- 결과: 33 passed, axe 전 페이지 "위반 없음 ✓"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
## 변경 내용
### RegisterDone 자동 로그인
- 회원가입 완료 시 /login 리다이렉트 → / 홈으로 변경
- /api/users/sign-up 응답에 accessToken이 포함되어 있어 이미 로그인 상태임이 확인됨
(useAuth.registerEmailMutation.onSuccess에서 setLoginData 호출)
- 백엔드 협의 불필요 — MSW 검증으로 확인 완료
### MSW 서버 테스트 격리
- db/store.ts: db.reset() 메서드 추가 (모든 데이터 초기화 + 시드 재등록)
- http.ts: POST /api/test/reset 엔드포인트 추가
- auth.spec.ts: 이메일 회원가입 beforeEach db 리셋 추가
### E2E 테스트 안정화
- auth.spec.ts: test.describe.configure({ mode: 'serial' }) 추가
— fullyParallel: true 환경에서 공유 MSW db 상태 충돌 방지
- goToVerifyEmail/goToRegisterPassword: email 파라미터 추가 (기본값 유지)
- goToRegisterDone: 고유 이메일(reg{timestamp}@test.com) 사용 — new@test.com 중복 방지
- 전체 플로우 E2E 테스트 추가: RegisterEmail → RegisterDone → / 이동 확인
- 결과: 34 passed, 0 failed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
## 변경 내용 ### landmark-one-main (전 페이지 공통) - AppShell.tsx: 내부 콘텐츠 래퍼 <div> → <main> - Layout.tsx: auth route 내부 <div> → <main> - 앱 전체에 <main> 랜드마크가 없던 구조적 문제 해소 ### color-contrast (WCAG 2.1 AA 4.5:1) - globals.css: --color-keycolor #3e8d00(4.11:1) → #2d7a00(5.41:1) - BoxLayoutTag: 하드코딩 rgba(132,132,132,1) → var(--color-text-muted) - Navbar: inactiveColor var(--color-muted3)(1.58:1) → var(--color-text-muted)(5.24:1) - TripListPage: text-[#3e8d00] → text-[var(--color-keycolor)] ### button-name / target-size - ShareIcon: className/ariaLabel prop 추가, inner button에 직접 적용 - TripDetailHeader: 중첩 button wrapper 제거, width: "auto" 고정값 제거 ### label-content-name-mismatch (WCAG 2.5.3) - TripDetailPage: 동행자 버튼 aria-label 제거 (visible text로 충분) ### document-title - /trip/list/page.tsx: metadata 추가 - /trip/apply/[travelNumber]/page.tsx: metadata 추가 ### button-name (기타) - Header: 뒤로가기 버튼 aria-label="뒤로 가기" 추가 - CreateTripButton: AddIcon aria-label + aria-expanded 추가 - TripListPage: AlarmIcon div → button 전환 + aria-label ### 문서화 - phase-6.md: §13 추가 (배경/위반 분석/수정 목록/수치/트러블슈팅/회고) - progress.md: Phase 6 완료 처리, 최종 수치 반영 (A11y 100/100/100) ## 수치 - A11y: / 79→100, /trip/list 72→100, /trip/detail 82→100 - Performance 유지: / 89, /trip/list 76, /trip/detail 89 - FCP 유지: 213ms / 336ms / 213ms Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
코드 리뷰Blocking (머지 전 수정 필요)없음 ✅ Non-blocking (권장 개선)1.
|
Summary
AppShell.tsx,Layout.tsx내부 콘텐츠 래퍼<div>→<main>교체. 앱 전체에<main>랜드마크가 없던 구조적 문제 완전 해소.--color-keycolor다크닝(4.11:1→5.41:1),BoxLayoutTag하드코딩 제거, Navbar 비활성 탭(1.58:1→5.24:1),TripListPagearbitrary value 교체ShareIcon중첩 버튼 구조 해소(className/ariaLabel prop 추가), TripDetailHeader width 고정값 제거/trip/list,/trip/apply/[id]metadata 추가최종 Lighthouse 수치 (Production 빌드)
//trip/list/trip/detail/1변경 파일
src/components/AppShell.tsx<div>→<main>src/components/Layout.tsx<div>→<main>src/app/globals.css--color-keycolor#3e8d00 → #2d7a00src/shared/ui/tag/BoxLayoutTag.tsxvar(--color-text-muted)src/widgets/home/Navbar.tsxinactiveColor→var(--color-text-muted)src/page-views/trip/TripListPage.tsxdiv→buttonsrc/components/icons/ShareIcon.tsxclassName,ariaLabelprop 추가src/page-views/trip/TripDetailHeader.tsxwidth: "auto"src/page-views/trip/TripDetailPage.tsxsrc/shared/ui/layout/Header.tsxsrc/widgets/home/CreateTripButton.tsxsrc/app/trip/list/page.tsxsrc/app/trip/apply/[travelNumber]/page.tsxdocs/refactoring/phase-6.mddocs/progress.mdTest plan
yarn build && yarn start후 Lighthouse로/,/trip/list,/trip/detail/1A11y 100 확인<main>랜드마크 이동(단축키) 동작 확인🤖 Generated with Claude Code