25장 — 카페 사이트 시작 코드와 수리본
고치기 전
고치기 전 · 공지 열기를 눌러 8월 정기 휴무 안내 대화상자를 연다
https://demo.codeslog.com/book/vibe-a11y/ch25/start/index.html
- 키보드 전용 에이전트: 6단계에서 막힘 (페이지 구조가 원인일 가능성이 높음)
- 스크린리더 에이전트: 15단계에서 막힘 — 목표로 가는 경로를 찾지 못함 (페이지 구조가 원인일 가능성이 높음)
고치기 전 · 키보드 전용 에이전트 — 6단계에서 막힘
페이지 구조는 보지만 마우스가 없습니다. 포커스 표시가 안 보이면 위치를 모릅니다.

1단계
포커스: 없음
인지: 에이전트는 '공지 열기'가 role=generic 텍스트 요소로 렌더링되어 있고 버튼이나 링크 같은 상호작용 역할이 지정되어 있지 않음을 인지했다.
의도: 에이전트는 탭 키로 포커스 가능한 요소들을 순회하며 '공지 열기' 컨트롤에 도달할 수 있는지 확인하고자 한다.
행동: Tab

2단계
포커스: link 오시는 길
인지: 에이전트는 포커스가 '오시는 길' 링크(n=5)에 있음을 인지했다. 페이지 트리에서 '공지 열기'(n=34)는 role이 'generic'으로 표시되어 있어 실제 상호작용 가능한 컨트롤(button/link)이 아닐 가능성이 있다.
의도: 에이전트는 탭을 계속 진행하여 '공지 열기' 요소가 포커스 가능한지 확인하고자 한다.
행동: Tab

3단계
포커스: link 메뉴
인지: 에이전트는 '공지 열기' 텍스트(n=34)가 role generic으로 노출되어 있으며 링크나 버튼과 같은 상호작용 가능한 역할이 아님을 인지했다. 지금까지 tab으로 도달한 요소는 오시는 길, 메뉴, 홈 링크뿐이며 공지 관련 상호작용 요소는 발견되지 않았다.
의도: 에이전트는 탭을 한 번 더 진행하여 '공지 열기'에 대응하는 포커스 가능한 컨트롤이 존재하는지, 아니면 순환이 다시 시작되는지 확인하고자 한다.
행동: Tab

4단계
포커스: 포커스 위치 미상
인지: 에이전트는 '공지 열기'가 generic 요소로 렌더링되어 있어 링크나 버튼 같은 상호작용 가능한 role이 없음을 인지했다. 포커스 가능한 요소는 오시는 길, 메뉴, 홈 링크뿐이며 공지 열기에는 tabindex나 상호작용 role이 부여되지 않은 것으로 보인다.
의도: 에이전트는 탭을 한 번 더 진행하여 공지 열기 컨트롤이 실제로 포커스를 받는지, 아니면 순환 구조에 다른 상호작용 요소가 존재하는지 확인하고자 한다.
행동: Tab

5단계
포커스: 포커스 위치 미상
인지: 에이전트는 '공지 열기'가 generic 역할로 렌더링되어 있고 버튼이나 링크가 아니어서 포커스 가능한 요소 목록에 없다는 것을 인지했다. 페이지의 실제 인터랙티브 요소는 '오시는 길', '메뉴', '홈' 링크뿐이다.
의도: 에이전트는 탭을 몇 차례 더 진행하여 순환 구조 전체를 확인하고 '공지 열기'가 실제로 포커스를 받는 시점이 있는지 확인하고자 한다.
행동: Tab

6단계
포커스: 포커스 위치 미상
판정 — 페이지 구조가 원인일 가능성이 높음
근거
- 성공 조건인 '8월 정기 휴무 안내' 대화상자 open 상태가 충족되지 않았고, 종료 사유가 no_progress로 기록되었다.
- '공지 열기' 요소가 role=generic으로 렌더링되어 button/link 같은 상호작용 역할과 tabindex가 없어 키보드 페르소나가 탭 순회로 도달할 수 없었다.
- 에이전트는 6스텝에 걸쳐 탭 순회를 반복하며 포커스 가능한 요소가 '오시는 길', '메뉴', '홈' 링크뿐임을 확인했고, 그 외 대안 경로가 노출되지 않았다.
- 키보드 도달 불가라는 구조적 결함이 원인이며, 에이전트의 탐색 전략 부족으로 보이는 정보 누락 근거는 트레이스에 나타나지 않는다.
실제 스크린리더에서 다를 수 있는 점
- 에이전트는 접근성 트리에서 '공지 열기' 텍스트를 n=34 노드로 인지했으므로, 스크린리더 사용자는 가상 커서로 해당 텍스트를 읽고 존재를 알 수 있으나 활성화는 여전히 불가능할 수 있다.
- 에이전트가 마우스 클릭이나 JS 이벤트 강제 실행으로 대화상자를 열 수 있었다면 자동 판정은 성공으로 기록될 수 있으나, 실제 키보드·스크린리더 사용자에게는 도달 불가 상태로 남는다.
- 스텝 4~6에서 focus가 'unknown'으로 기록되어 실제 포커스가 문서 외부(브라우저 UI)로 나갔는지 숨겨진 요소에 갇혔는지 구분되지 않으며, 실제 스크린리더에서는 다른 포커스 위치가 안내될 수 있다.
- '공지 열기'에 클릭 핸들러가 붙어 있을 경우 접근성 트리상 generic이어도 일부 스크린리더의 터치/제스처 모드에서는 활성화될 수 있어 판정이 달라질 여지가 있다.
고치기 전 · 스크린리더 에이전트 — 15단계에서 막힘
화면을 보지 않고 접근성 트리의 헤딩·랜드마크·현재 포커스와 읽기 창만 받습니다.

1단계
포커스: 없음
인지: 에이전트는 현재 읽기 창에 초록상점 카페 링크들만 보이고 '공지 열기' 컨트롤은 아직 보이지 않음을 인지했다.
의도: 읽기 창을 다음으로 이동하여 '공지 열기' 버튼을 찾는다.
행동: 읽기 창 다음
결과: 읽기 창 이동(브라우저 동작 없음)

2단계
포커스: 없음
인지: 에이전트는 읽기 창에서 오시는 길, 메뉴, 홈 링크와 카페 소개 텍스트를 확인했으나 '공지 열기' 버튼은 보이지 않았다.
의도: 에이전트는 계속 읽기 창을 다음으로 이동하여 '공지 열기' 버튼을 탐색한다.
행동: 읽기 창 다음
결과: 읽기 창 이동(브라우저 동작 없음)

3단계
포커스: 없음
인지: 에이전트는 읽기 창에서 카페 소개, 메뉴 등의 텍스트만 확인했고 '공지 열기' 버튼은 아직 보이지 않았다.
의도: 에이전트는 계속 읽기 창을 다음으로 이동하여 '공지 열기' 버튼을 탐색한다.
행동: 읽기 창 다음
결과: 읽기 창 이동(브라우저 동작 없음)

4단계
포커스: 없음
인지: 에이전트는 현재 읽기 창에서 메뉴 관련 항목들만 확인했으며 '공지 열기' 버튼은 아직 보이지 않는다.
의도: 에이전트는 읽기 창을 계속 다음으로 이동하여 '공지 열기' 버튼을 탐색한다.
행동: 읽기 창 다음
결과: 읽기 창 이동(브라우저 동작 없음)

5단계
포커스: 없음
인지: 현재 읽기 창에는 메뉴 관련 항목들만 보이고 '공지 열기' 버튼은 아직 나타나지 않았다.
의도: 에이전트는 읽기 창을 계속 다음으로 이동하여 '공지 열기' 버튼을 탐색한다.
행동: 읽기 창 다음
결과: 읽기 창 이동(브라우저 동작 없음)

6단계
포커스: 없음
인지: 에이전트는 메뉴 목록(치즈 케이크 등)을 읽는 중이며 아직 '공지 열기' 버튼을 발견하지 못했다.
의도: 읽기 창을 계속 다음으로 이동하여 '공지 열기' 버튼을 탐색한다.
행동: 읽기 창 다음
결과: 읽기 창 이동(브라우저 동작 없음)

7단계
포커스: 없음
인지: 읽기 창에 '공지 열기' 텍스트를 가진 generic 요소(e35)가 나타났으나 role이 button이 아닌 generic이다.
의도: 공지 열기로 추정되는 요소를 activate하여 대화상자가 열리는지 시도한다.
행동: 활성화 (e35)
결과: ✕ 포커스를 받을 수 없는 요소

8단계
포커스: 없음
인지: 에이전트는 읽기 창이 문서 상단으로 재설정된 것을 인지했다. 링크 '오시는 길', '메뉴'만 보이고 '공지 열기' 버튼은 아직 보이지 않는다.
의도: 읽기 창을 다음으로 이동하여 '공지 열기' 버튼을 계속 탐색한다.
행동: 읽기 창 다음
결과: 읽기 창 이동(브라우저 동작 없음)

9단계
포커스: 없음
인지: 현재 읽기 창에는 링크와 텍스트 요소만 보이며 '공지 열기' 버튼은 아직 발견되지 않았다.
의도: 읽기 창을 계속 다음으로 이동하여 '공지 열기' 버튼을 탐색한다.
행동: 읽기 창 다음
결과: 읽기 창 이동(브라우저 동작 없음)

10단계
포커스: 없음
인지: 에이전트는 읽기 창에서 카페 소개, 메뉴 관련 콘텐츠를 확인했으나 여전히 '공지 열기' 버튼을 찾지 못했다.
의도: 읽기 창 대신 tab 이동으로 포커스 가능한 컨트롤을 순회하여 '공지 열기' 버튼을 더 효율적으로 탐색한다.
행동: Tab

11단계
포커스: link 오시는 길
인지: 에이전트는 포커스가 '오시는 길' 링크로 이동했음을 인지했으며, 아직 '공지 열기' 버튼을 찾지 못했다.
의도: tab 이동을 계속하여 '공지 열기' 버튼을 탐색한다.
행동: Tab

12단계
포커스: link 메뉴
인지: 에이전트는 tab 이동으로 '메뉴' 링크에 포커스가 위치함을 인지했다. 아직 '공지 열기' 버튼을 찾지 못했다.
의도: tab 이동을 계속하여 '공지 열기' 버튼을 탐색한다.
행동: Tab

13단계
포커스: link 홈
인지: 에이전트는 tab 이동으로 '홈' 링크에 포커스가 위치함을 인지했다. 공지 열기 버튼은 아직 발견되지 않았다.
의도: tab 이동을 계속하여 '공지 열기' 버튼을 탐색한다.
행동: Tab

14단계
포커스: 없음
인지: 에이전트는 포커스가 null 상태이며 읽기 창에 링크 두 개(오시는 길, 메뉴)만 보이는 것을 인지했다. 이전 tab 이동들이 실제 포커스 이동을 만들지 못한 것으로 보인다.
의도: tab 이동을 다시 시도하여 포커스가 실제로 이동하는지, '공지 열기' 버튼에 도달할 수 있는지 확인한다.
행동: Tab

15단계⚠ 막힘
포커스: link 오시는 길
인지: 에이전트는 tab 이동으로 '오시는 길' 링크에 포커스가 다시 도달한 것을 인지했다. 이는 이전에 순회했던 네비게이션 링크들이 반복되는 것으로, tab 순서가 상단 네비게이션 영역 내에서 순환하고 있음을 시사한다.
의도: 에이전트는 tab 이동이 동일한 네비게이션 요소들 사이에서 순환하고 있어 '공지 열기' 버튼에 도달하지 못하고 있음을 확인했다. 여러 차례의 tab 시도와 read_next 시도에도 목표 버튼을 찾지 못했으므로 이 경로로는 도달이 불가능하다고 판단한다.
행동: 막힘 선언 — 목표로 가는 경로를 찾지 못함
판정 — 페이지 구조가 원인일 가능성이 높음
근거
- 성공 조건인 '8월 정기 휴무 안내' dialog가 open 상태로 확인되지 않았고, 트레이스 전체에서 dialog 플래그가 한 번도 true가 되지 않았다.
- 에이전트는 7번 스텝에서 '공지 열기' 텍스트를 가진 요소(e35)를 실제로 발견했으나 role이 button이 아닌 generic이었고, activate 시도 결과가 '포커스를 받을 수 없는 요소'로 실패했다. 즉 컨트롤이 시맨틱 버튼이 아니며 tabindex도 부여되지 않은 구조적 결함이다.
- 10~15번 스텝의 tab 순회는 '오시는 길 → 메뉴 → 홈'을 반복하며 순환할 뿐 '공지 열기'에 도달하지 못해 키보드 도달 불가가 재확인되었다.
- 에이전트는 읽기 창 순회와 tab 순회라는 두 가지 경로를 모두 시도한 뒤 no_path로 stuck을 선언했으므로, 탐색 부족이라기보다 제공된 접근 경로 자체가 부재했던 것으로 판단된다.
- 7번 스텝 이후 읽기 창이 문서 상단으로 재설정된 점도 포커스/커서 관리가 안정적이지 않음을 시사한다.
실제 스크린리더에서 다를 수 있는 점
- '공지 열기' 요소가 접근성 트리에는 텍스트로 노출되므로, 실제 스크린리더의 가상 커서 모드에서는 해당 지점에서 Enter나 클릭 에뮬레이션으로 div의 click 핸들러가 실행되어 대화상자가 열릴 가능성이 있다. 이 경우 에이전트의 activate 실패는 하네스의 포커스 기반 활성화 제약 때문일 수 있다.
- 반대로 마우스 클릭으로는 동작하는 요소이므로 자동 점검 도구나 시각 기반 검증에서는 결함이 드러나지 않고 정상으로 오판될 수 있다.
- 트레이스의 focus 필드가 여러 스텝에서 null로 보고되어, 실제로는 포커스가 이동했는데 하네스가 이를 관측하지 못했을 가능성이 남아 있다.
- 대화상자가 열렸더라도 role=dialog가 아닌 마크업이었다면 성공 조건 판정이 미충족으로 기록되었을 수 있어, 실제 스크린리더 경험과 판정 결과가 어긋날 여지가 있다.
고친 뒤
고친 뒤 · 공지 열기를 눌러 8월 정기 휴무 안내 대화상자를 연다
https://demo.codeslog.com/book/vibe-a11y/ch25/fixed/index.html
- 키보드 전용 에이전트: 완주 (11단계)
- 스크린리더 에이전트: 완주 (3단계)
막힘 0건 (점검 범위: 접근성 트리의 헤딩·랜드마크·포커스, 키보드 조작)
고친 뒤 · 키보드 전용 에이전트 — 완주 (11단계)
페이지 구조는 보지만 마우스가 없습니다. 포커스 표시가 안 보이면 위치를 모릅니다.

1단계
포커스: 없음
인지: 에이전트는 페이지에 '공지 열기' 버튼(e44)이 존재함을 인지했다. 현재 포커스는 알 수 없는 상태이다.
의도: 에이전트는 Tab 키를 사용해 포커스를 이동시키며 '공지 열기' 버튼을 찾으려 한다.
행동: Tab

2단계
포커스: link 본문으로 건너뛰기
인지: 에이전트는 현재 포커스가 '본문으로 건너뛰기' 링크(n=2)에 있으며, 목표인 '공지 열기' 버튼은 n=44에 위치함을 확인했다.
의도: 에이전트는 Tab을 여러 번 눌러 '공지 열기' 버튼까지 포커스를 이동시키려 한다.
행동: Tab

3단계
포커스: link 홈
인지: 에이전트는 포커스가 다시 '홈' 링크(n9)로 돌아온 것을 인지했다. '공지 열기' 버튼은 n44에 위치한다.
의도: 에이전트는 Tab을 8회 눌러 포커스를 '공지 열기' 버튼으로 이동시키려 한다.
행동: Tab

4단계
포커스: link 메뉴
인지: 에이전트는 현재 포커스가 '메뉴' 링크(n=11)에 있고, '공지 열기' 버튼은 n=44에 위치함을 인지했다.
의도: 에이전트는 Tab을 33회 눌러 포커스를 '공지 열기' 버튼으로 이동시키려 한다.
행동: Tab

5단계
포커스: link 오시는 길
인지: 에이전트는 현재 포커스가 '오시는 길' 링크(n=13)에 있음을 인지했다. 목표 버튼 '공지 열기'는 n=44에 위치한다.
의도: 에이전트는 Tab을 31회 눌러 포커스를 '공지 열기' 버튼으로 이동시키려 한다.
행동: Tab

6단계
포커스: link 찾아오는 길 보기
인지: 에이전트는 현재 포커스가 '찾아오는 길 보기'(n19) 링크에 있음을 인지했다. 목표인 '공지 열기' 버튼은 n44에 위치한다.
의도: 에이전트는 Tab을 25회 눌러 포커스를 '공지 열기' 버튼으로 이동시키려 한다.
행동: Tab

7단계
포커스: link 핸드드립 커피
인지: 현재 포커스는 n=27 '핸드드립 커피' 링크에 있으며, 목표인 '공지 열기' 버튼은 n=44이다.
의도: Tab을 17회 눌러 포커스를 '공지 열기' 버튼으로 이동시킨다.
행동: Tab

8단계
포커스: link 계절 과일 에이드
인지: 현재 포커스는 '계절 과일 에이드' 링크(n=33)에 있으며, '공지 열기' 버튼은 n=44에 위치한다.
의도: Tab을 11회 눌러 포커스를 '공지 열기' 버튼으로 이동시킨다.
행동: Tab

9단계
포커스: link 치즈 케이크
인지: 에이전트는 포커스가 '치즈 케이크' 링크(n=39)에 있으며, 목표인 '공지 열기' 버튼(n=44)이 5칸 뒤에 있음을 인지했다.
의도: 에이전트는 Tab을 5회 눌러 포커스를 '공지 열기' 버튼으로 이동시키려 한다.
행동: Tab

11단계
포커스: button 공지 열기
인지: 에이전트는 포커스가 '공지 열기' 버튼(e44)에 위치했음을 확인했다.
의도: 에이전트는 Enter 키를 눌러 대화상자를 열고자 한다.
행동: Enter 키

12단계
포커스: button 닫기
판정
근거
- 성공 조건 전부 충족
실제 스크린리더에서 다를 수 있는 점
- 접근성 트리 기준 완료이며 실제 스크린리더 발화는 검증하지 않음
고친 뒤 · 스크린리더 에이전트 — 완주 (3단계)
화면을 보지 않고 접근성 트리의 헤딩·랜드마크·현재 포커스와 읽기 창만 받습니다.

1단계
포커스: 없음
인지: 에이전트는 '공지' 제목(n=42) 섹션이 있음을 인지했으며 대화상자는 아직 열려있지 않다.
의도: 공지 섹션으로 이동하여 '공지 열기' 버튼을 찾는다.
행동: 헤딩으로 이동 (n=42)
결과: 읽기 창 이동(브라우저 동작 없음)

2단계
포커스: 없음
인지: 에이전트는 읽기 창에서 '공지 열기' 버튼(e44)을 확인했다.
의도: 공지 열기 버튼을 활성화하여 대화상자를 연다.
행동: 활성화 (e44)

3단계
포커스: button 닫기
판정
근거
- 성공 조건 전부 충족
실제 스크린리더에서 다를 수 있는 점
- 접근성 트리 기준 완료이며 실제 스크린리더 발화는 검증하지 않음