Frontend

드롭다운의 정체를 밝혀라 — Combobox, Multiselect, Listbox 완전 해부

Combobox, Multiselect, Listbox, Dual Listbox의 차이점과 접근성 요구사항, 선택 기준을 ARIA 패턴 기반으로 정리한다.

10 min read
UI컴포넌트접근성ARIAComboboxListbox
드롭다운의 정체를 밝혀라 — Combobox, Multiselect, Listbox 완전 해부

드롭다운이 필요하다. 검색도 되어야 하고, 여러 개를 동시에 선택할 수도 있어야 한다. "Combobox? Multiselect? 아니면 그냥 Listbox?" — 세 단어가 머릿속에서 뒤엉킨다. 셋 다 "목록에서 뭔가를 고르는" 컴포넌트인데, 용도와 접근성 요구사항이 완전히 다르다. 여기서 갈림길을 잘못 타면 키보드 사용자 경험이 통째로 무너진다.


네 가지 컴포넌트, 각자의 영역

Combobox — 검색창과 드롭다운의 결합

텍스트 입력 필드 아래로 목록이 열리고, 타이핑하면 필터링된다. 선택은 하나만 가능하다. 검색엔진의 자동완성 바를 떠올리면 정확하다. 입력 → 필터링 → 선택이라는 흐름이 명쾌하다.

combobox-basic.html
<label for="country-select">국가 선택</label>
<div role="combobox" aria-expanded="false" aria-haspopup="listbox">
  <input
    type="text"
    id="country-select"
    aria-autocomplete="list"
    aria-controls="country-listbox"
  />
</div>
<ul id="country-listbox" role="listbox" aria-label="국가 목록">
  <li role="option" id="kr">대한민국</li>
  <li role="option" id="us">미국</li>
  <li role="option" id="jp">일본</li>
</ul>

[💡 잠깐! 이 용어는?] role="combobox": WAI-ARIA에서 정의한 역할(role)로, 텍스트 입력과 팝업 목록을 결합한 복합 위젯을 나타낸다. 스크린 리더는 이 역할을 통해 "검색 가능한 선택 목록"이라는 맥락을 전달한다.

Multiselect — 태그가 쌓이는 선택창

Combobox와 구조가 비슷하지만 여러 항목을 선택할 수 있다. 선택된 항목은 입력 필드 위에 태그(칩)로 쌓인다. 이메일 작성 시 수신자를 추가하는 필드가 대표적인 예다.

multiselect-basic.html
<label for="tag-input">기술 스택</label>
<div class="multiselect" role="combobox" aria-expanded="false" aria-haspopup="listbox">
  <div class="selected-tags" aria-live="polite">
    <span class="tag" role="option" aria-selected="true">React</span>
    <span class="tag" role="option" aria-selected="true">TypeScript</span>
  </div>
  <input
    type="text"
    id="tag-input"
    aria-autocomplete="list"
    aria-controls="tech-listbox"
  />
</div>
<ul id="tech-listbox" role="listbox" aria-multiselectable="true" aria-label="기술 스택 목록">
  <li role="option" aria-selected="false">Vue</li>
  <li role="option" aria-selected="false">Svelte</li>
  <li role="option" aria-selected="false">Angular</li>
</ul>

Listbox — 전체 선택지가 벽에 걸린 메뉴판

드롭다운 없이 모든 옵션이 처음부터 펼쳐져 있다. 스크롤로 탐색하며, 단일 또는 복수 선택이 가능하다. 서랍 속에 넣어둔 것이 아니라 벽에 걸어놓은 메뉴판이다. 한눈에 모든 선택지를 비교할 수 있어서, 사용자가 전체 옵션을 파악해야 할 때 힘을 발휘한다.

listbox-basic.html
<label id="font-label">폰트 선택</label>
<ul role="listbox" aria-labelledby="font-label" tabindex="0">
  <li role="option" aria-selected="false">Pretendard</li>
  <li role="option" aria-selected="true">Noto Sans KR</li>
  <li role="option" aria-selected="false">IBM Plex Sans KR</li>
  <li role="option" aria-selected="false">Spoqa Han Sans Neo</li>
</ul>

Dual Listbox — 좌우 이동의 미학

두 개의 Listbox가 나란히 놓여 있고, 항목을 왼쪽에서 오른쪽으로(또는 반대로) 이동시키는 패턴이다. "사용 가능"과 "선택됨"을 시각적으로 분리해서 보여준다.

dual-listbox.html
<div class="dual-listbox">
  <div>
    <label id="available-label">사용 가능</label>
    <ul role="listbox" aria-labelledby="available-label" aria-multiselectable="true">
      <li role="option">권한 A</li>
      <li role="option">권한 B</li>
      <li role="option">권한 C</li>
    </ul>
  </div>
  <div class="controls">
    <button aria-label="선택 항목 추가">&rarr;</button>
    <button aria-label="선택 항목 제거">&larr;</button>
  </div>
  <div>
    <label id="selected-label">선택됨</label>
    <ul role="listbox" aria-labelledby="selected-label" aria-multiselectable="true">
      <li role="option">권한 D</li>
    </ul>
  </div>
</div>

[💡 잠깐! 이 용어는?] aria-multiselectable: Listbox에서 복수 선택 가능 여부를 스크린 리더에 알리는 ARIA 속성. true로 설정하면 사용자에게 "여러 항목을 선택할 수 있다"는 맥락이 전달된다.


키보드 내비게이션 — 같은 키, 다른 동작

접근성의 핵심은 마우스 없이 키보드만으로 모든 조작이 가능해야 한다는 것이다. 네 컴포넌트가 같은 키에 대해 서로 다르게 반응한다.

ComboboxMultiselectListboxDual Listbox
/ 목록 탐색목록 탐색목록 탐색목록 탐색
Enter선택 후 닫기선택 (닫지 않음)선택해당 없음
Space텍스트 입력텍스트 입력선택 토글선택 토글
Escape팝업 닫기팝업 닫기해당 없음해당 없음
Shift + ↓해당 없음범위 선택범위 선택범위 선택
Tab다음 요소로 이동다음 요소로 이동다음 요소로 이동반대쪽 Listbox로 이동
문자 입력필터링필터링해당 문자로 이동해당 문자로 이동

핵심 차이: Combobox와 Multiselect에서 Space는 텍스트 입력에 쓰이지만, Listbox에서는 선택 토글에 쓰인다. 이 하나를 놓치면 키보드 사용자 경험이 완전히 깨진다.


선택 의사결정 가이드

기준은 두 가지다. 옵션의 수선택 방식.

조건추천 컴포넌트
옵션 5개 미만라디오 버튼 또는 체크박스
옵션 5~20개, 단일 선택Combobox 또는 <select>
옵션 5~20개, 복수 선택Listbox (aria-multiselectable)
옵션 20개 이상, 단일 선택Combobox (검색 필터 필수)
옵션 20개 이상, 복수 선택Multiselect (검색 + 태그)
선택/미선택 상태를 명확히 분리Dual Listbox
옵션 순서 재배열 필요Dual Listbox (드래그앤드롭 대체)

옵션이 5개도 안 되는데 드롭다운을 쓰는 건, 3층짜리 건물에 엘리베이터를 설치하는 것과 같다. 계단이 더 빠르다. 라디오 버튼이나 체크박스가 클릭 한 번으로 선택을 끝내므로 훨씬 효율적이다.

[💡 잠깐! 이 용어는?] Dual Listbox: 두 개의 Listbox를 나란히 배치해 항목을 이동시키는 UI 패턴. 드래그앤드롭보다 접근성이 뛰어나고, 키보드만으로 조작 가능하며, 현재 선택 상태를 시각적으로 명확히 구분할 수 있다.


자주 저지르는 실수 세 가지

1. <select multiple> 남용

네이티브 <select multiple>은 대부분의 사용자가 조작법을 모른다. Ctrl/Cmd를 누른 채 클릭해야 복수 선택이 된다는 사실을 직관적으로 알기 어렵다. Listbox나 Multiselect로 대체하는 것이 맞다.

2. 드래그앤드롭으로 순서 변경

드래그앤드롭은 시각적으로 직관적이지만, 키보드 사용자와 스크린 리더 사용자에게 접근성 문제를 일으킨다. 순서 변경이 필요하다면 Dual Listbox에 "위로/아래로" 버튼을 조합하는 것이 더 접근 가능하다.

3. 포커스 관리 누락

Combobox에서 항목을 선택하면 포커스가 입력 필드로 돌아와야 한다. Multiselect에서 태그를 삭제하면 이전 태그 또는 입력 필드로 포커스가 이동해야 한다. aria-activedescendant로 시각적 포커스와 실제 DOM 포커스를 분리하는 것이 핵심이다.

focus-management.css
[role="listbox"]:focus [aria-selected="true"] {
  outline: 2px solid #4a90d9;
  outline-offset: -2px;
}
 
[role="option"]:hover {
  background-color: #f0f0f0;
}
 
[role="option"][aria-selected="true"] {
  background-color: #e0e7ff;
  font-weight: 600;
}

마무리

Combobox, Multiselect, Listbox는 모두 "목록에서 고르기"라는 같은 문제를 풀지만, 옵션 수, 선택 방식, 표시 형태가 전부 다르다. 원칙은 단순하다 — 옵션이 적으면 단순한 UI를, 많으면 검색 가능한 UI를 쓴다. 어떤 컴포넌트를 선택하든 키보드 내비게이션과 ARIA 속성은 옵션이 아니라 필수다. 라이브러리를 가져다 쓰더라도 키보드로 한 번쯤 직접 조작해보는 습관이 접근성 문제를 예방하는 가장 확실한 방법이다.


참고: