개발

검색 폼의 role="search" 를 요소로 바꾸기 — 크롬·사파리 접근성 트리는 같고, 안에 넣으면 문단이 끊긴다

  • 16th October 2026
  • 3 min read

검색창을 감싸는 <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 안에 formAXLandmarkSearch 안에 AXLandmarkForm
<div role="search"><form>search 안에 formAXLandmarkSearch 안에 AXLandmarkForm
<form role="search">searchAXLandmarkSearch
<form> (role 없음)formAXLandmarkForm
<search aria-label="사이트 검색">search, 이름 "사이트 검색"AXLandmarkSearch, 이름 "사이트 검색"
<search> 안에 입력칸만searchAXLandmarkSearch

<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)172023-09-18
파이어폭스1182023-09-26
크롬 (데스크톱·안드로이드)1182023-10-10
엣지1182023-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 같은 화면 낭독기가 실제로 어떻게 읽는지도 듣지 않았고, 접근성 트리까지만 확인했다.

함께 읽으면 좋은 글