Popover API — JavaScript 없이 툴팁을 만들 수 있게 된 이유
popover 속성 하나로 열기/닫기, Esc 처리, 접근성이 자동으로 동작하는 브라우저 네이티브 UI
<button popovertarget="tip-1">ホバー</button>
<div id="tip-1" popover="auto" role="tooltip">
これがネイティブ ツールチップ
</div>
JavaScript 0줄. 이벤트 리스너 없음. 상태 추적 없음. 그런데 Esc로 닫히고, 키보드로 접근 가능하고, 스크린 리더가 제대로 읽는다.
기존 툴팁이 깨지는 방식
"hover하면 뜨고 벗어나면 사라지는" 단순한 요구사항인데, 실제로 배포하면 문제가 쏟아진다.
키보드 사용자가 Tab으로 트리거에 도착해도 툴팁이 안 뜬다. 스크린 리더가 두 번 읽거나 아예 안 읽는다. 마우스를 빠르게 움직이면 깜빡인다. 작은 화면에서 겹친다. Esc로 안 닫힌다. 포커스가 유실된다.
결국 이벤트 리스너가 누적되고, hover/focus 별도 처리, 외부 클릭 특수 케이스, ARIA 속성 수동 동기화까지 코드가 비대해진다. 구현 자체의 문제가 아니라 웹 플랫폼에 "이 요소가 툴팁이다"라는 개념이 없었기 때문이다.
Popover API가 바꾼 것
popover 속성을 붙이면 브라우저가 이 요소의 역할을 이해한다. 3가지가 자동으로 해결된다.
1. JavaScript 없이 열기/닫기
popovertarget="id"로 버튼과 popover를 연결하면 끝. 클릭, 포커스로 열고 닫는 걸 브라우저가 처리한다. popovertargetaction으로 동작을 지정할 수도 있다 — show, hide, toggle(기본값).
2. Esc 키 자동 처리
전역 keydown 핸들러, Esc 전용 정리 로직이 필요 없다. 브라우저가 popover를 해제 가능한 요소로 인식하기 때문에 Esc가 그냥 동작한다.
3. ARIA 상태 자동 동기화
aria-expanded가 popover 열림/닫힘에 맞춰 자동 업데이트된다. 수동 관리 불필요. 오래된 상태가 남을 위험이 없다. Lighthouse가 잘못된 ARIA 상태를 경고하는 일도 사라진다 — 커스텀 ARIA 상태 자체가 없으니까.
auto vs manual
<!-- auto: 바깥 클릭 시 자동 닫힘 -->
<div popover="auto">자동 닫힘</div>
<!-- manual: 명시적으로만 닫힘 -->
<div popover="manual">수동 닫힘</div>
auto는 바깥 클릭, Esc, 다른 auto popover 열기 시 자동으로 닫힌다. 툴팁에 적합.
manual은 명시적으로 닫아야 한다. 포커스 복원도 자동으로 안 된다 — 블러로 닫을 때 트리거로 포커스를 직접 반환해야 한다. 토스트 알림 같은 데 적합.
아직 JavaScript가 필요한 영역
타이밍 제어. 네이티브 popover는 즉시 열리고 닫힌다. 마우스를 빠르게 움직이면 깜빡이는 문제가 여전하다. hover와 열림 사이에 딜레이를 넣으려면 JavaScript가 필요하다.
호버 인텐트. 브라우저는 포인터가 요소 위에 있는 이유를 모른다. 의도적인 호버인지, 지나가는 중인지 판단할 수 없다. 이건 JavaScript로 감지해야 한다.
다만 핵심이 바뀌었다. 이전에는 JavaScript가 상호작용 모델 전체를 소유했다. 이제는 Popover API가 기본 열기/닫기를 처리하고, JavaScript는 그 위에 인텐트 판별만 얹는다.
CSS 쪽에서도 진행 중이다. interest/invoker 관련 명세가 진입/퇴장 딜레이를 CSS로 표현하는 방향으로 발전하고 있다.
라이브러리가 여전히 유효한 경우
복잡한 포지셔닝. 중첩 스크롤 컨테이너 간 충돌 감지, 커스텀 플리핑 로직이 필요하면 Floating UI 같은 라이브러리가 여전히 낫다. CSS anchor positioning이 이 문제를 커버하기 시작했지만 아직 초기 단계.
대규모 디자인 시스템. 여러 팀이 쓰는 디자인 시스템에서는 중앙화된 동작, 문서화된 패턴, 가드레일이 필요하다. 라이브러리가 이 역할을 한다.
접근성 경험이 부족한 팀. Popover API가 좋은 기본값을 제공하지만, role, 레이블, 포커스 관리를 언제 추가할지 아는 건 여전히 필요하다.
근데 대부분의 경우 — 단순 툴팁, 드롭다운 메뉴, 토스트 알림 — Popover API만으로 충분하다. 라이브러리 없이.
핵심 포인트
popover 속성과 popovertarget만으로 열기/닫기, Esc, 키보드 내비게이션이 자동 동작
aria-expanded 자동 동기화로 접근성 버그 범주 자체가 제거된다
auto는 바깥 클릭/Esc로 자동 닫힘, manual은 명시적 제어 — 용도에 맞게 선택
타이밍 제어, 호버 인텐트 같은 영역은 여전히 JavaScript가 필요하지만 핵심 모델은 브라우저 담당