
처음 aria-label이라는 속성을 알았을 때 반응이 "이게 뭐 대수냐"였다. 그냥 텍스트 하나 더 붙이는 거잖아. 그런데 현장에서 스크린 리더 테스트를 직접 해보고 나서 생각이 완전히 뒤집혔다. 화면을 보지 않고 소리만으로 웹페이지를 탐색하는 경험은 충격적이었다. "버튼, 버튼, 버튼" 이렇게만 읽히는 화면에서 사용자가 느끼는 답답함은 마치 불 꺼진 지하 주차장에서 내 차를 찾는 것과 다르지 않았다. 그날 이후로 아이콘 버튼을 만들 때마다 aria-label을 먼저 생각하게 됐다.
부끄러운 고백이지만, 나도 한동안 aria-label을 선택이 아닌 장식 정도로 여겼다. 스크린 리더를 실제로 켜본 적이 없었기 때문이다. 직접 켜서 내가 만든 페이지를 탐색해보기 전까지는 무엇이 문제인지 피부로 느낄 수 없었다. 이 경험이 없는 개발자가 접근성을 진지하게 다루기 어렵다는 것이 내가 내린 결론이다. 도구는 한 번이라도 직접 써봐야 한다.
ARIA가 뭔지, WAI-ARIA부터 이해하자
ARIA는 Accessible Rich Internet Applications의 약자다. WAI-ARIA라고 하면 Web Accessibility Initiative에서 만든 스펙을 말한다. HTML 요소에 의미와 역할, 상태 정보를 추가로 달아주는 속성 묶음이다. HTML만으로는 전달하기 어려운 맥락 정보를 스크린 리더나 보조 기술에 전달하는 다리 역할을 한다.
가장 많이 쓰는 ARIA 속성은 aria-label, aria-labelledby, aria-describedby 세 가지다. 이 중 aria-label이 가장 직접적이고 자주 사용된다. 요소에 사람이 읽을 수 있는 이름을 직접 붙여주는 방식이다.
aria-label이 없으면 생기는 현실적인 문제
아이콘 버튼을 생각해보자. 검색 버튼, 좋아요 버튼, 공유 버튼. 화면에는 아이콘만 보인다. 마우스를 쓰는 사람은 아이콘 모양으로 기능을 유추한다. 그런데 스크린 리더 사용자에게는 그냥 "버튼"이다. 무슨 버튼인지 알 수 없다. 더 심한 경우는 이미지로 만든 버튼인데 alt 텍스트조차 없는 경우다. 스크린 리더가 파일명을 그대로 읽어버린다. "icon-search-v2-final-수정.png 버튼" 이런 식으로.
나는 이 문제를 처음에 이론으로만 이해했다. 그런데 실제로 스크린 리더로 내가 만든 페이지를 탐색하면서 직접 들었을 때 충격이 달랐다. 내가 만든 버튼들이 죄다 "버튼"으로만 읽혔다. 검색 버튼인지 제출 버튼인지 닫기 버튼인지 구분이 없었다. 그 경험 이후로 아이콘 버튼에 aria-label을 달지 않고 넘기는 일이 없어졌다.
네비게이션 영역에서 aria-label을 쓰는 방법
한 페이지에 nav 태그가 여러 개 있을 때가 문제다. 헤더 네비게이션, 사이드바 네비게이션, 푸터 네비게이션. 스크린 리더는 이것들을 구분하지 못하고 그냥 "내비게이션"이라고만 읽는다. 마치 건물 안내판에 "화장실", "화장실", "화장실"만 써있고 어느 층 어느 방향인지 없는 것과 같다. aria-label로 각 네비게이션의 역할을 명확히 해줘야 한다. "주요 메뉴", "카테고리", "사이트 하단 링크" 같은 식으로 각각 구분해주면 스크린 리더 사용자도 원하는 내비게이션을 빠르게 찾을 수 있다.
이 처리를 하는 데 추가 시간이 얼마나 드냐고 물으면, 솔직히 별로 안 든다. 기껏해야 속성 하나 붙이는 일이다. 그런데 효과는 크다. 개발에서 이런 비율이 압도적으로 좋은 작업을 게을리할 이유가 없다.
폼 요소와 aria-label: 레이블 없는 입력 필드의 함정
폼 설계 작업을 하다 보면 디자인상 이유로 label 태그를 숨기고 placeholder만 사용하는 경우가 많다. placeholder는 사용자가 입력을 시작하면 사라진다. 스크린 리더 사용자는 입력 중에 이 필드가 무엇인지 다시 확인할 방법이 없다. 이럴 때 aria-label이 구원투수가 된다.
가장 이상적인 방법은 label 태그를 직접 연결하는 것이다. 구글 크롤러도 label-input 연결 구조를 명확한 시맨틱 신호로 인식한다. aria-label은 label 사용이 어려운 상황에서의 차선책이지, 기본값이 아니다. 이 우선순위를 헷갈리면 aria-label을 달았는데도 오히려 접근성이 더 나빠지는 역설이 생긴다. label이 가능하면 label을 써야 한다.
aria-labelledby: 기존 텍스트를 레이블로 재활용하는 방법
페이지에 이미 존재하는 텍스트를 레이블로 쓰고 싶을 때 aria-labelledby가 더 적합하다. aria-label은 새 텍스트를 직접 지정하고, aria-labelledby는 이미 페이지에 있는 요소의 텍스트를 참조한다. 예를 들어 섹션의 제목으로 이미 h2가 있다면, 그 h2의 id를 aria-labelledby로 참조하면 된다. 여러 id를 공백으로 연결하면 두 텍스트가 합쳐서 읽힌다. 이를 이용하면 모달 제목과 부제목을 함께 레이블로 만들 수 있다.
구글이 시맨틱 구조를 왜 좋아하는가
구글의 검색 알고리즘은 페이지의 콘텐츠를 이해하고 분류하려 한다. 이 과정에서 구조적 신호가 결정적인 역할을 한다. nav 태그 안에 있는 링크들은 메인 콘텐츠 링크와 다르게 취급된다. aside 안의 내용은 주요 콘텐츠와 구분된다. aria 속성들은 이 구조적 의미를 더욱 명확하게 만들어준다. aria-label로 구조화된 페이지는 구글 Search Console에서 구조화 데이터 관련 경고가 줄어드는 경향이 있다. 접근성 점수가 높은 페이지는 Core Web Vitals 평가에서도 유리하다. 모두 연결된 고리다.
현장에서 느낀 주의사항: 과잉 사용의 역설
aria-label을 처음 도입할 때 가장 많이 했던 실수는 과잉 사용이었다. 모든 요소에 aria-label을 붙이면 오히려 스크린 리더가 중복 정보로 혼란스러워진다. 이미 텍스트가 있는 버튼에 aria-label을 따로 달면 텍스트와 aria-label이 따로따로 읽히는 경우가 생긴다. ARIA 사용의 첫 번째 원칙은 "HTML이 충분하면 ARIA를 추가하지 마라"다. 텍스트가 명확하게 있는 버튼에는 aria-label이 불필요하다. aria-label이 꼭 필요한 경우는 텍스트 없이 아이콘만 있을 때다.
이 과잉 사용의 문제는 처음 ARIA를 배우는 개발자들이 거의 예외 없이 겪는다. 좋은 도구를 발견했을 때 모든 곳에 적용하고 싶은 마음은 이해하지만, 도구는 필요한 곳에 써야 한다. 접근성을 개선하려다가 오히려 접근성을 해치는 역설을 경험하고 나서야 이 원칙이 진짜로 이해됐다.
마무리: aria-label은 배려가 아니라 커뮤니케이션이다
개발 일을 오래 하다 보면 코드가 결국 사람과 사람 사이의 소통이라는 걸 느끼게 된다. 내가 만드는 코드는 기계만 읽는 게 아니라, 그 기계를 통해 사람이 정보를 얻는다. 스크린 리더 사용자, 키보드 사용자, 저시력 사용자. 이들이 내 페이지에서 길을 잃지 않도록 하는 것이 aria-label이 하는 일이다. 이걸 배려라고 표현하면 마치 특별한 선물처럼 들리지만, 사실은 커뮤니케이션의 기본이다. 식당 메뉴판에 글씨를 읽을 수 있게 쓰는 것처럼, 당연히 해야 하는 일이다.
구글 SEO 관점에서도 효과는 분명했다. aria-label과 시맨틱 구조를 정리한 이후 Search Console에서 크롤링 오류가 줄었고, 구조화 데이터 경고도 감소했다. 페이지 이해도가 높아지면 구글이 더 정확하게 페이지를 분류하고, 그 결과로 관련 검색어에서 순위가 오른다. 접근성과 SEO는 같은 목표를 향한 두 개의 길이 아니라, 원래부터 하나의 길이었다. aria-label을 처음 배우는 분들께 한 가지만 당부하자면, 과잉 사용을 경계하라는 것이다. 의미 있는 HTML 구조가 먼저고, ARIA는 HTML이 부족할 때 보완하는 도구다. 이 우선순위를 헷갈리지 않으면 aria-label은 정말 강력한 도구가 된다.