검색창을 감싸는 <div role="search">나 <form role="search">는 이제 <search> 요소 하나로 바꿀 수 있다. 2023년 가을에 크롬·파이어폭스·사파리가 모두 지원했고, webstatus.dev 기준으로 2026년 4월 13일에 Baseline Widely available이 됐다. 크롬과 사파리에서 바꾸기 전후의 접근성 트리를 직접 비교했다. 결과는 똑같았고, 바꿀 때 걸리는 함정이 두 가지 있었다.
바꾸는 법
<!-- 전 -->
<form role="search" action="/search">
<label for="q">사이트 검색</label>
<input type="search" id="q" name="q">
<button>찾기</button>
</form>
<!-- 후 -->
<search>
<form action="/search">
<label for="q">사이트 검색</label>
<input type="search" id="q" name="q">
<button>찾기</button>
</form>
</search>
<search>에는 전용 속성이 없다. 폼을 보내지 않고 자바스크립트로 목록을 거르는 필터라면 <form> 없이 입력칸만 넣어도 된다. 한 페이지에 검색 영역이 둘 이상이면 aria-label로 이름을 붙여 구분한다.
<search aria-label="상품 필터">
<label>이름으로 거르기 <input type="search" id="filter"></label>
</search>
검색 결과는 <search> 안에 넣지 않는다. MDN은 결과를 페이지 본문에 두고, 입력 중에 뜨는 추천어처럼 검색 기능의 일부인 것만 안에 두라고 한다.
접근성 트리는 role="search"와 똑같다
같은 페이지에 여섯 가지 마크업을 두고 크롬은 DevTools 프로토콜의 Accessibility.getPartialAXTree로, 사파리는 macOS 접근성 API의 AXSubrole로 읽었다.
| 마크업 | 크롬 155 | 사파리 27 |
|---|---|---|
<search><form> | search 안에 form | AXLandmarkSearch 안에 AXLandmarkForm |
<div role="search"><form> | search 안에 form | AXLandmarkSearch 안에 AXLandmarkForm |
<form role="search"> | search | AXLandmarkSearch |
<form> (role 없음) | form | AXLandmarkForm |
<search aria-label="사이트 검색"> | search, 이름 "사이트 검색" | AXLandmarkSearch, 이름 "사이트 검색" |
<search> 안에 입력칸만 | search | AXLandmarkSearch |
<search>는 두 브라우저 모두에서 role="search"와 같은 검색 랜드마크로 잡혔다. 접근성 트리가 같으니 화면 낭독기에 넘어가는 정보도 같다. 차이는 하나다. <form role="search">는 랜드마크가 하나지만, <search><form>은 검색 랜드마크 안에 폼 랜드마크가 하나 더 생긴다. 이 구조는 지금까지 흔히 쓰던 <div role="search"><form>과 같다.
자바스크립트 쪽에서도 <search>는 HTMLUnknownElement가 아닌 HTMLElement였고, 기본 display는 block이었다.
함정 1: <p> 안에 넣으면 문단이 끊긴다
<search>는 <div>처럼 열려 있는 <p>를 닫아 버리는 요소다. 문장 중간에 작은 검색칸을 넣으려고 이렇게 쓰면,
<p>원하는 글이 없으면 <search>…</search> 에서 찾아보세요.</p>
크롬과 사파리 모두 아래처럼 파싱했다. 앞 문장은 <p>에 남고, 뒤 문장은 문단 밖으로 빠지며, 원래의 </p>는 빈 문단 하나를 새로 만든다.
<p>원하는 글이 없으면 </p><search>…</search> 에서 찾아보세요.<p></p>
<div role="search">를 <p> 안에 두던 코드도 같은 식으로 깨지므로 새로 생긴 문제는 아니다. 다만 <span role="search">를 쓰던 자리를 <search>로 바꾸면 그때부터 문단이 끊긴다. 문장 안에 검색칸을 둬야 한다면 <p>를 <div>로 바꾼다.
함정 2: [role="search"] 선택자가 더는 맞지 않는다
마크업에서 role="search"를 지우면 그 속성에 기대던 CSS와 자바스크립트가 조용히 빗나간다. 오류는 나지 않고 스타일이나 동작만 빠진다. 바꾸기 전에 코드에서 먼저 찾아 둔다.
grep -rn 'role=.search\|role="search"\]' --include=*.css --include=*.scss --include=*.js .
/* 전 */
[role="search"] { margin-left: auto; }
/* 후: 둘 다 맞게 */
search, [role="search"] { margin-left: auto; }
지원 범위와 옛 브라우저
| 브라우저 | 지원 버전 | 출시 |
|---|---|---|
| 사파리 (macOS·iOS) | 17 | 2023-09-18 |
| 파이어폭스 | 118 | 2023-09-26 |
| 크롬 (데스크톱·안드로이드) | 118 | 2023-10-10 |
| 엣지 | 118 | 2023-10-13 |
출처는 webstatus.dev API이고, Baseline 상태는 widely(Newly available 2023-10-13, Widely available 2026-04-13)다. 같은 API의 크롬 사용량 통계로는 크롬 페이지 로드의 약 0.3%만 <search>를 쓴다.
이보다 오래된 브라우저는 <search>를 모르는 요소로 다룬다. 그래서 인라인 상자로 그려지고 검색 랜드마크도 생기지 않는다. iOS 16 이하 사용자가 많은 서비스라면 한동안 두 가지를 같이 붙여 둔다. W3C 검사기(validator.w3.org/nu)에 <search role="search">를 넣어 보니 경고 없이 통과했다.
<style>search { display: block; }</style>
<search role="search"> … </search>
측정 환경
- 크롬 155 (Chrome for Testing, 헤드리스), 사파리 27.0.1 (macOS 27). 접근성 트리는 크롬 DevTools 프로토콜과 macOS 접근성 API(
AXRole·AXSubrole)로 읽었다. - 파이어폭스는 재지 못했다. VoiceOver·NVDA 같은 화면 낭독기가 실제로 어떻게 읽는지도 듣지 않았고, 접근성 트리까지만 확인했다.