웹 기초 ·
입력칸의 이름표를 연결해야 누구나 폼을 쓸 수 있다
먼저 답부터
입력칸의 이름은 옆에 글자를 놓는 것만으로 연결되지 않습니다. HTML의 label은 입력칸의 id와 같은 for 값을 가져야 하고, 형식 안내는 별도 문장으로 연결해야 합니다. 이렇게 하면 이름을 눌러 입력칸으로 이동할 수 있고 화면 읽기 도구도 무엇을 입력할지 알려 줄 수 있습니다.
회원가입 화면에서 빈 칸 위에 ‘이메일’이라고 적혀 있어도, 그 글자와 입력칸이 코드에서는 따로 떨어져 있을 수 있습니다. 눈으로 보면 둘이 가까워서 짐작할 수 있지만, 화면 읽기 도구로 칸을 하나씩 이동하는 사람에게는 무엇을 입력해야 하는지 빠질 수 있습니다.
가게의 보관함에 이름표를 옆 선반에 놓는 것과 해당 서랍에 묶어 두는 것은 다릅니다. 웹 폼도 마찬가지입니다. 폼은 사용자가 내용을 입력하고 보내는 화면이며, 입력칸의 이름표를 해당 칸에 실제로 연결해야 누구나 같은 목적을 알 수 있습니다.
글자가 가까이 있어도 이름표가 연결된 것은 아니다
입력칸 위에 굵은 글씨로 ‘이메일 주소’라고 쓰고 바로 아래 빈 칸을 두면 사람은 둘을 짝으로 봅니다. 그러나 HTML에서는 단지 글자의 위치만 가까울 수 있습니다. HTML은 웹페이지 내용과 역할을 적는 언어인데, 위치와 역할은 서로 다른 정보입니다.
W3C의 폼 안내는 글을 보여 주는 데서 멈추지 않고 이름표와 입력칸을 명시적으로 연결하도록 권합니다. 이 연결은 화면 읽기 도구가 칸의 목적을 말해 주는 데 쓰이며, 마우스나 손가락으로 이름표를 눌렀을 때 해당 칸으로 이동하는 데도 도움이 됩니다. 보이는 모양을 맞추는 CSS만 고쳐서는 이 관계가 만들어지지 않습니다.
label과 id는 같은 이름을 가리키게 한다
label은 입력칸에 붙이는 이름표 요소입니다. id는 페이지 안에서 특정 요소를 가리키는 고유 이름이고, for는 이름표가 어떤 입력칸을 가리키는지 적는 값입니다. 두 값이 정확히 같아야 아래 예시의 ‘이메일 주소’가 빈 칸과 연결됩니다.
<label for="contact-email">이메일 주소</label>
<input id="contact-email" type="email" name="email">
이 코드를 브라우저에 놓으면 이름표와 입력칸이 보입니다. 이름표 글자를 누르면 입력칸에 커서가 이동합니다. 같은 페이지의 다른 입력칸에 contact-email이라는 id를 다시 쓰면 목적지를 구분하기 어려워지므로 고유하게 정합니다. MDN 문서도 for와 id의 명시적 연결을 설명합니다.
이름표는 무엇을 입력할지 알려 준다
‘여기에 입력’ 같은 이름표는 칸의 목적을 설명하지 못합니다. ‘이메일 주소’, ‘배송받을 사람 이름’처럼 어떤 정보를 받는지 적어야 합니다. 필수라면 그 사실도 글자로 알려 줍니다. 색이나 별표 모양만으로 필수 여부를 전달하면 뜻을 놓칠 수 있습니다.
입력칸 안에 흐리게 보이는 예시 글자인 placeholder는 이름표를 대신하지 않습니다. 값을 쓰기 시작하면 사라지기 때문에 입력 중 형식을 다시 확인하기 어렵고, 화면 읽기 도구가 이를 이름표로 일관되게 취급한다고 기대할 수도 없습니다. W3C는 예시 문구와 별개로 실제 이름표를 제공하라고 안내합니다.
추가 안내는 이름표와 다른 역할로 둔다
‘이메일 주소’는 칸의 이름이고, ‘예시 주소를 사용하세요’는 입력을 돕는 안내입니다. 안내 문구를 길게 이름표에 모두 넣기보다, 필요한 경우 화면에 보이는 별도 문장으로 두고 연결할 수 있습니다. aria-describedby는 입력칸이 읽힐 때 추가 설명을 함께 전달하도록 설명 문장의 id를 가리키는 속성입니다.
<label for="practice-email">이메일 주소</label>
<input id="practice-email" type="email" aria-describedby="email-help">
<p id="email-help">연습에서는 example.com 주소만 사용하세요.</p>
이 예시에서 이름은 label이 담당하고, 한 줄 도움말은 email-help가 담당합니다. aria-describedby만 쓰고 보이는 이름표를 없애는 방법으로 이해하면 안 됩니다. 실제 화면에서도 안내 문구가 입력칸 가까이에 보이는지 확인합니다.
체크박스와 버튼도 목적을 분명히 한다
동의 체크박스는 작은 네모만 보여서는 무엇에 동의하는지 알 수 없습니다. 짧고 구체적인 문장을 이름표로 붙이고, 자세한 약관 링크는 별도 위치에서 읽을 수 있게 둡니다. MDN은 이름표 안에 링크나 다른 버튼을 넣으면 입력칸을 누르는 동작과 충돌할 수 있다고 설명합니다.
여러 선택지가 한 질문에 답하는 구조라면 각 선택지의 이름과 질문 전체의 이름을 구분합니다. fieldset은 관련 선택지를 묶는 상자이고 legend는 그 묶음의 질문 제목입니다. 버튼에는 ‘제출’처럼 막연한 말보다 ‘연습 답변 확인’처럼 실제 다음 행동을 알려 주는 글자를 쓰는 편이 낫습니다. 이 글의 작은 실습에서는 아무 자료도 보내지 않으므로 버튼을 만들 필요가 없습니다.
눈과 키보드로 연결 결과를 확인한다
코드에서 같은 글자를 맞췄다고 끝난 것은 아닙니다. 브라우저에서 이름표를 눌러 입력칸으로 이동하는지, Tab 키로 이동했을 때 어느 칸에 있는지 보이는지, 작은 화면에서 이름표와 칸이 멀리 떨어지지 않았는지를 함께 봅니다. 화면 읽기 도구를 쓸 수 있다면 칸의 이름과 추가 안내가 읽히는지도 확인합니다.
입력 값이 잘못됐을 때 무엇을 고칠지 알려 주는 오류 문장은 9강 ‘입력 폼과 오류를 확인하는 법’에서 이어서 다룹니다. 여기서는 먼저 평소 상태의 칸마다 이름과 추가 설명이 정확히 붙어 있는지에 집중합니다. 화면의 한 곳에서 통과했다고 모든 브라우저와 보조 도구에서 같다고 단정하지 않고, 실제 사용하는 환경에서도 확인합니다.
오늘 바로 해볼 작은 실습
실제 회원 정보나 결제 화면을 건드리지 않고, 10분 동안 빈 연습 페이지나 종이에 입력칸 하나의 연결을 점검합니다.
- ‘이메일 주소’라는 보이는 이름표와 빈 입력칸 하나를 그립니다.
- 이름표의
for에 쓸 고유한 값을practice-email로 적습니다. - 입력칸의
id에도 같은 값을 적고 다른 칸과 중복되는지 봅니다. - 입력 형식 안내가 필요하다면 이름표와 별도 문장으로 적습니다.
- 안내 문장의 id를 정하고 입력칸의
aria-describedby와 맞춥니다. - 브라우저에서 연습했다면 이름표를 눌러 커서가 이동하는지 봅니다.
- Tab 키로 칸에 들어갔을 때 현재 위치가 보이는지 확인합니다.
- 값을 쓴 뒤에도 이름표와 안내가 화면에 남는지 확인합니다.
- 실제 이메일, 비밀번호, 카드 번호, API 비밀키는 연습 칸에 넣지 않습니다.
- 제출·결제·삭제 버튼은 누르지 않고 연결 확인만 마칩니다.
모르는 설치 명령이나 외부 스크립트를 복사해 실행할 필요가 없습니다. 기존 서비스의 폼을 바꿀 때는 시험 화면에서 먼저 확인하고, 결제·삭제·계정 변경 화면은 담당자의 승인과 되돌릴 방법을 확인한 뒤 다룹니다. 이름표가 보이는지, 어느 칸에 붙었는지, 추가 안내가 무엇인지 세 가지를 설명할 수 있으면 첫 점검을 마친 것입니다.
확인한 자료
- Labeling Controls — W3C Web Accessibility Initiative
- Form Instructions — W3C Web Accessibility Initiative
- The HTML label element — MDN Web Docs
함께 읽기
- 주소를 입력하면 웹페이지가 열리는 과정을 주문 배달처럼 이해하기
웹 주소를 입력하면 브라우저는 DNS로 서버 주소를 찾고 HTTP 요청을 보냅니다. 서버가 돌려준 HTML, CSS, JavaScript와 이미지를 조합해 화면을 그리며, 404나 500 오류가 보이면 이 요청과 응답 중 실패한 구간을 확인하면 됩니다.
- 프론트엔드와 백엔드와 데이터베이스를 식당 역할로 구분하기
프론트엔드는 사용자가 보고 누르는 화면, 백엔드는 요청과 규칙을 처리하는 보이지 않는 부분, 데이터베이스는 회원과 주문 같은 기록을 보관하는 곳입니다. 식당으로 비유하면 각각 홀, 주방, 장부에 해당하며 세 역할이 연결돼 하나의 기능이 완성됩니다.
- API와 JSON을 메뉴판과 주문서처럼 읽는 첫 연습
API는 다른 서비스에 정해진 방식으로 기능이나 데이터를 요청하는 연결 창구이고, JSON은 그 요청과 답을 이름과 값의 묶음으로 적는 형식입니다. 메뉴판에서 가능한 주문을 확인하고 주문서에 항목을 적는 과정으로 생각하면 두 개념을 함께 이해하기 쉽습니다.