메뉴 건너뛰기

A11Y

접근성 가이드: 사용자 입력 폼(Forms)에서 “논리 순서”와 레이블 연결

1. 목적

시각적으로 완벽하게 배치된 입력 폼이라도, 스크린리더/키보드 사용자에게는 무의미한 “편집창, 편집창, 버튼…” 나열로 들릴 수 있다.

이 가이드는 폼에서 논리 순서(탐색 순서)레이블(이름) 제공을 올바르게 설계/구현하여, 스크린리더가 “무슨 입력칸인지” 정확히 읽도록 만드는 방법을 정의한다.

2. 문제 정의: 시각적 배치 ≠ 접근성 의미

많은 접근성 API(AT-SPI, UIA, AX API 등) 및 스크린리더는 폼 컨트롤의 정보를 얻을 때, 단순히 화면 좌표로 “가까운 레이블”을 추측하지 않는다. 대신 보통은 다음을 기반으로 이름을 계산한다.

  1. 명시적 연결(권장): <label for> / aria-labelledby
  2. 구조적 연결: 컨트롤을 감싼 <label>
  3. 대체 메커니즘: aria-label, title
  4. (일부 환경) DOM/생성 순서(논리 순서) 기반 추론

따라서 화면상으로 레이블이 “옆에” 있어도, DOM/생성 순서가 어긋나면 스크린리더는 레이블을 못 읽거나 엉뚱한 레이블을 붙일 수 있다.

3. 핵심 원칙(필수)

원칙 A. 키보드 탐색은 “논리적 흐름”을 따라야 한다

  • 사용자는 Tab으로 위에서 아래로, 좌에서 우로 자연스럽게 이동하는 경험을 기대한다.
  • 폼 요소가 복잡한 레이아웃(그리드, 카드, 2열 배치 등)일수록 DOM 순서를 시각적 순서와 맞추는 것이 중요하다.

필수 기준

  • 폼 필드(레이블 → 입력 → 도움말/오류 → 다음 필드)가 자연스러운 순서로 탐색되어야 한다.
  • 레이아웃을 위해 CSS로 위치만 바꾸고 DOM 순서를 뒤섞지 않는다(가능하면).

원칙 B. 모든 입력 컨트롤은 “이름(Name)”을 가져야 한다

스크린리더가 “편집창”이 아니라 “이름, 편집창”처럼 읽어야 한다.

필수 기준

  • 텍스트 입력, 콤보박스, 체크박스, 라디오, 스위치, 날짜 선택, 파일 업로드 등 모든 폼 컨트롤은 접근 가능한 이름을 제공해야 한다.
  • placeholder는 레이블 대체가 아니다(입력 시 사라지고, 보조기술에서 충분하지 않음).

4. 구현 규칙(우선순위)

4.1 1순위: 네이티브 <label for> 사용(가장 권장)

가장 안정적이고 도구/브라우저/스크린리더 호환성이 좋다.

예시
<label for="user_name">이름</label>
<input id="user_name" name="user_name" type="text">
  • label[for] 값과 input#id가 반드시 일치해야 한다.
  • 레이블을 클릭하면 입력 포커스가 이동하는 부가 UX도 얻는다.

4.2 2순위: 컨트롤을 <label>로 감싸기

예시
<label>
  이름
  <input name="user_name" type="text">
</label>
  • 간단한 UI에서 유용
  • 다만 복잡한 레이아웃/스타일링에서 구조가 불편할 수 있음

4.3 DOM에서 레이블이 떨어져 있으면: aria-labelledby 사용(필수 대안)

시각 디자인 또는 컴포넌트 구조 때문에 레이블과 입력이 DOM에서 멀어질 수 있다. 이 경우 명시적으로 레이블 요소의 id를 참조한다.

예시
<span id="lbl_user_name">이름</span>
<input type="text" aria-labelledby="lbl_user_name">
  • aria-labelledby는 “이 입력의 이름은 이 요소(들)의 텍스트를 합친 것”이라는 뜻
  • 여러 개를 지정하면 공백으로 구분해 순서대로 결합한다.
여러 레이블 조합 예시
<span id="lbl">배송지</span>
<span id="required">(필수)</span>
<input aria-labelledby="lbl required">

4.4 추가 설명(도움말/오류)은 aria-describedby로 연결

레이블은 “이름(Name)”, 설명은 “설명(Description)”이다.

도움말 연결 예시
<label for="email">이메일</label>
<input id="email" type="email" aria-describedby="email_help">
<p id="email_help">예: user@example.com</p>
  • 스크린리더는 보통 “이메일, 편집창, 예: user@example.com” 형태로 읽을 수 있다.
  • 오류 메시지에도 동일하게 적용 가능
오류 메시지 연결 예시
<input id="email" aria-describedby="email_help email_error">
<p id="email_error">이메일 형식이 올바르지 않습니다.</p>

4.5 정말 불가피할 때만: aria-label

화면에 레이블 텍스트가 없고(아이콘-only) 시각적으로도 별도의 텍스트를 둘 수 없을 때만 사용한다.

예시
<input type="search" aria-label="사이트 검색">

가능하면 시각적으로도 레이블을 제공하거나, 최소한 aria-labelledby로 “실제 텍스트”를 참조하는 편이 유지보수에 좋다.

5. 논리 순서 설계 가이드(디자인/개발 공통)

5.1 “레이블 → 컨트롤 → 도움말/에러”의 묶음을 유지

한 필드를 구성하는 요소들은 DOM에서도 가능한 한 가까이 둔다.

권장 DOM 구조 예
<div class="field">
  <label for="user_name">이름</label>
  <input id="user_name" type="text" aria-describedby="user_name_hint">
  <div id="user_name_hint">한글 2~20자</div>
</div>

5.2 시각적 2열 배치에서도 DOM은 위→아래 흐름 유지

  • CSS Grid/Flex로 “보이는 위치”만 바꾸되, DOM 자체는 자연스러운 순서를 유지한다.
  • tabindex로 순서를 억지로 맞추는 방식(특히 양수 tabindex)은 지양한다.

6. 체크리스트(릴리스 전 점검)

레이블/이름

  • 모든 입력 요소에 접근 가능한 이름이 있다(읽었을 때 “무엇을 입력하는지” 명확).
  • placeholder만 있는 필드는 없다.
  • 레이블이 DOM에서 멀리 떨어져 있으면 aria-labelledby로 연결했다.

설명/오류

  • 입력 규칙, 단위, 예시, 오류 메시지는 aria-describedby로 연결되어 있다.
  • 오류 상태 변화 시(검증 실패) 오류 메시지가 화면과 스크린리더에 모두 전달된다(필요 시 라이브 영역 검토).

키보드/논리 순서

  • TAB 이동이 시각적/업무 흐름과 일치한다.
  • 포커스가 갑자기 점프하거나, 읽기 순서가 섞이지 않는다.
  • 불필요한 tabindex(특히 1,2,3…)를 사용하지 않는다.
예시 코드
<div class="grid">
  <div class="label-col">
    <span id="name_label">이름</span>
  </div>
  <div class="input-col">
    <input type="text" aria-labelledby="name_label" aria-describedby="name_help">
    <div id="name_help">실명 기준으로 입력</div>
  </div>

  <div class="label-col">
    <span id="gender_label">성별</span>
  </div>
  <div class="input-col">
    <select aria-labelledby="gender_label">
      <option value="m">남성</option>
      <option value="f">여성</option>
    </select>
  </div>
</div>
  • 레이블과 컨트롤이 DOM에서 꼭 붙어있지 않아도, aria-labelledby로 논리적 인접성을 “명시”한다.
  • 결과적으로 스크린리더는 “이름, 편집창 … / 성별, 콤보상자 …”처럼 읽을 수 있다.

8. 금지/주의 패턴

  • 레이블 없이 placeholder로만 대체: 입력 중 사라지고 의미 전달이 불완전
  • 시각적 위치만 믿기: 레이블이 옆에 있어도 스크린리더가 못 읽을 수 있음
  • 양수 tabindex로 TAB 순서 설계: 유지보수 비용 증가, 예외 케이스 발생
  • 중복 id / 잘못된 참조: aria-labelledby="없는ID" 같은 오류는 즉시 품질 저하

9. 결론

폼 접근성의 핵심은 “예쁜 배치”가 아니라, 보조기술이 이해할 수 있는 논리 순서와 명시적 연결이다.

가능하면 네이티브 <label>을 우선 사용하고, 구조상 떨어질 수밖에 없다면 aria-labelledby/aria-describedby로 관계를 선언해 스크린리더가 정확히 읽도록 보장한다.

번호 제목 날짜 조회 수
45 About: MSAA, Microsoft Active Accessibility 2024.09.05 1253
44 센스리더에서 지원하는 SSML 2024.09.05 1758
43 About: Microsoft Windows IUIAutomation Interface 2024.09.06 1160
42 윈도우 접근성 기술: MSAA와 UIAutomation 비교 2024.09.09 1142
41 시각장애인 접근성 향상을 위한 응용프로그램 조작 인터페이스 2024.09.11 1277
40 접근성 역할에서 "link"와 "button"의 차이 2024.09.24 1807
39 시각장애인을 위한 음성 접근성 정보 제공 방법 2024.09.25 1363
38 시각장애인 접근성 음성 정보의 맹점 2024.10.02 1183
37 시각장애인을 위한 소리 정보 제공 시 기본 파형 사용 주의사항 2024.10.02 1253
36 센스리더의 "기능 검색" 기능에 대하여 2024.10.08 1765
35 센스리더의 브라우저 탭키 환경과 가상커서 탭키 환경 2024.10.11 1669
34 시각장애인과의 협업을 위한 특수문자 발음의 이해 2024.10.18 1292
33 여러 단계로 이루어진 서비스 제공시 시각장애인 접근성 개선 방안 2024.10.22 1210
32 [세미나] 시각장애 개발자와 함께 하는 아이디어 마이닝 #1. 목적 2024.11.11 1482
31 시각장애 개발자와 함께하는 아이디어 마이닝 #2. 텍스트와 오디오 2024.11.12 1600
30 시각장애 개발자와 함께하는 아이디어 마이닝 #3. 이미지 2024.11.13 1388
29 시각장애 개발자와 함께하는 아이디어 마이닝 #4. 의사 코드 2024.11.14 1307
28 시각장애 개발자와 함께하는 아이디어 마이닝 #5. HTML 2024.11.18 1537
27 시각장애 개발자와 함께하는 아이디어 마이닝 #6. 스크립트 언어 2024.11.19 1585
26 시각장애 개발자와 함께하는 아이디어 마이닝 #7. 스크립트 예시, CMD 2024.11.20 1457