Search

aria 속성

웹을 만들다 보면 생각보다 많은 UI가 보이지 않는 상태에서 동작한다. 버튼처럼 생기지 않은 버튼, 텍스트처럼 보이지만 사실 클릭 가능한 링크, 모달이 열렸는데 포커스가 엉뚱한 곳으로 가는 문제 등은 모두 접근성과 연결된다.

왜 ARIA가 필요할까

스크린 리더(screen reader) 같은 보조기기는 DOM 구조와 역할(role) 을 기반으로 화면을 읽는다.
하지만 요즘 UI는 실제 시멘틱 태그 대신 div와 span을 많이 사용한다. 이때 ARIA 속성은 보조기기에 “이 컴포넌트가 실제로 어떤 역할인지” 힌트를 제공한다.
예를 들어, 다음 두 요소는 시각적으로는 똑같은 버튼처럼 보인다.
<button>저장</button> <div class="button-like">저장</div>
HTML
복사
스크린 리더 입장에서는 완전히 다르게 인식한다.
두 번째는 단순 텍스트로 읽혀 버튼 기능을 알 수 없다.
이때 ARIA 속성을 쓰면 보조기기에도 ‘이건 버튼이다’라고 알려줄 수 있다.
<div role="button" tabindex="0" class="button-like">저장</div>
HTML
복사
이 이유만 알면 ARIA의 전체 목적이 명확해진다.
시각적으로는 충분한데, 기술적으로는 부족한 정보를 ARIA로 보완한다.

ARIA의 원칙

1.
가능하면 ARIA를 쓰지 않는다.
시멘틱 태그(button, nav, header 등)를 먼저 사용한다.
ARIA는 대체재이기 때문에 시멘틱 태그를 쓰면 ARIA를 줄일 수 있다.
2.
의미 없는 div에 자꾸 역할을 부여해야 한다면 컴포넌트 구조를 다시 확인한다.
role이 많아질수록 UI가 복잡해지고 디버깅도 어려워진다.
3.
ARIA는 시각적 스타일링과 관련 없다.
ARIA는 “보이는 UI를 꾸미는 속성”이 아니라 “보이지 않는 정보 전달 도구”다.

실무에서 자주 쓰는 ARIA 속성

role: 요소의 역할 부여

role은 해당 요소가 무엇인지 보조기기에 설명한다.
자주 쓰는 role 목록:
button
textbox
dialog
alert
checkbox
navigation
switch
tab, tablist, tabpanel
예시:
<div role="dialog" aria-modal="true">내용</div>
HTML
복사

aria-label: 눈에 보이지 않지만 읽혀야 하는 텍스트

아이콘 버튼에 가장 많이 쓴다.
<button aria-label="닫기"> <svg>...</svg> </button>
HTML
복사
텍스트가 없으면 스크린 리더가 “버튼”이라고만 읽는다.

aria-labelledby: 여러 요소를 조합해 하나의 레이블로 읽힘

모달 제목과 설명을 함께 읽히게 할 때 유용하다.
<div role="dialog" aria-labelledby="modal-title modal-desc"> <h2 id="modal-title">설정</h2> <p id="modal-desc">알림 옵션을 변경할 수 있다</p> </div>
HTML
복사

aria-hidden: 보조기기에서 숨김

시각적으로는 보이지만, 읽히면 안 되는 경우에 사용한다.
<span aria-hidden="true"></span>
HTML
복사

aria-expanded: 토글 UI 상태 설명

아코디언, 드롭다운 등에서 사용
<button aria-expanded="false">메뉴</button>
HTML
복사
JavaScript로 true/false를 업데이트하면 된다.

aria-controls: 어떤 요소를 조작하는지 설명

expanded와 함께 사용된다.
<button aria-expanded="false" aria-controls="menu">메뉴</button> <ul id="menu"></ul>
HTML
복사

aria-live: 상태 메시지를 자동으로 읽히기

실시간 업데이트 메시지에서 효과적이다.
<div aria-live="polite">저장 완료</div>
HTML
복사

가장 실무에 많이 쓰는 패턴 3가지

1. 아이콘 버튼

텍스트 없이 아이콘만 있는 버튼은 접근성이 가장 나쁘다.
<button aria-label="삭제"> <TrashIcon /> </button>
HTML
복사

2. 커스텀 셀렉트 박스

div로 만든 드롭다운은 role과 상태값을 꼭 지정한다.
<div role="button" aria-haspopup="listbox" aria-expanded="true" tabindex="0" > 선택하기 </div> <ul role="listbox"> <li role="option" aria-selected="true">A</li> <li role="option">B</li> </ul>
HTML
복사

3. 모달(dialog)

모달이 열릴 때 스크린 리더 포커스를 강제로 모달 내부로 넣어야 한다.
<div role="dialog" aria-modal="true" aria-labelledby="modal-title"> <h2 id="modal-title">알림</h2> 내용 </div>
HTML
복사

ARIA를 쓰면 안 되는 경우

1.
button 태그를 div + role="button"으로 바꾸는 경우
-> 불필요한 복잡도를 유발
2.
태그 기본 의미를 무시하는 경우
예: <a> 태그에 role="button"을 넣는 행위
실제로 a는 링크인데 버튼이라고 속이는 셈
3.
aria-hidden으로 중요한 정보를 숨기는 경우
사용자 경험에 치명적일 수 있음

실수 줄이는 간단 체크리스트

기본 HTML 시멘틱 태그를 먼저 쓴다.
div에 role이 계속 붙기 시작하면 컴포넌트를 재검토한다.
상태값(true/false)은 항상 JavaScript로 업데이트한다.
aria-hidden은 꼭 필요한 경우에만 사용한다.
모달, 토글, 드롭다운은 role과 expanded 속성을 반드시 함께 구성한다.
사실 많이 사용되는 ui 라이브러리에서는 이미 웹 접근성에 대해서 잘 처리해놓았기 때문에, 좋은 라이브러리를 선택하는 게 편한 방법일 수도…