HTML5 신규 요소와 API
HTML5 시맨틱·video·audio 요소와 새 입력 타입을 사용하고 브라우저 Web API의 역할을 개괄합니다.
앞 글에서는 시맨틱 HTML과 접근성을 다뤘습니다. 이 글에서는 흔히 HTML5라는 이름으로 묶어 부르는 새 요소와, 브라우저가 자바스크립트에 제공하는 Web API(Application Programming Interface)를 살펴봅니다. HTML은 지금 버전 번호 없이 계속 갱신되는 표준(Living Standard)으로 관리되므로, 아래 기능들이 HTML의 특정 버전 하나로 한꺼번에 생긴 것은 아닙니다. 그래도 이 기능들 덕분에 웹은 정적인 문서에서 애플리케이션을 실행하는 플랫폼으로 넓어졌습니다. 그래픽을 직접 그리는 SVG와 Canvas는 다음 글 SVG와 캔버스 기초에서 다룹니다.
BROWSER CAPABILITIES
HTML 요소와 JavaScript Web API의 책임을 구분합니다
브라우저 플랫폼의 문서·입력·미디어·그래픽·저장·위치 기능은 독립적으로 조합합니다.
문서 구조 · 선언형 HTML
heading · nav · main · link
JS가 없어도 구조와 기본 이동을 제공합니다. DOM 순서와 목적지 연결을 확인합니다.
입력 · HTML 폼
label · input · required · submit
기본 입력과 제약 검증을 활용합니다. 서버 검증·저장·업무 처리는 별도 구현입니다.
미디어 · HTML + 재생 API
audio · video · source · track
controls로 기본 조작을 제공합니다. 코덱·자막·자동 재생 정책과 대체 안내를 확인합니다.
그래픽 · SVG / Canvas
SVG 요소 · Canvas drawing API
SVG는 선언형 도형과 DOM을 사용합니다. Canvas 2D 그리기는 JS API이며 도형 상태·접근성 대안을 설계합니다.
저장소 · JavaScript Web API
localStorage · sessionStorage
HTML 태그가 아닙니다. origin과 수명 범위, 저장 한도·실패·개인 모드 등을 고려합니다.
위치 · JavaScript Web API
navigator.geolocation
HTTPS 등 보안 컨텍스트와 사용자 권한·정책이 필요합니다. 거절·불가 상태의 대안을 제공합니다.
필요한 기능을 조합하고 각 경계를 확인합니다
앞 기능을 통과해야 다음 기능을 쓰는 계층이 아닙니다. HTML의 기본 기능과 JavaScript API를 구분하고, 지원·권한·실패 시 동작을 기능별로 설계합니다.
위 그림은 브라우저의 기능을 HTML 요소로 쓰는 것과 자바스크립트 Web API로 쓰는 것으로 나눠 보여 줍니다. 제목, 폼, 미디어의 기본 조작, SVG 도형, 그림을 그릴 자리인 canvas 요소는 HTML에 속하고, 저장소, Canvas에 그리는 기능, 위치 정보는 자바스크립트 코드로 쓰는 API에 속합니다. 위치 정보는 HTTPS 같은 보안 컨텍스트와 사용자의 권한이 있어야 쓸 수 있습니다.
그림 아래의 설명처럼 두 영역은 차례로 통과하는 단계가 아니라, 한 페이지에서 필요한 만큼 조합하는 기능입니다. HTML의 기본 구조 위에 필요한 API를 더하고, 기능마다 지원 여부와 권한, 실패했을 때의 동작을 따로 정합니다.
시맨틱 요소 다시 보기
앞 글에서 본 <header>, <nav>, <main>, <article>, <section>, <aside>, <footer>는 페이지의 영역에 의미를 부여해 검색 엔진과 보조 기술이 구조를 파악하게 합니다. 여기서는 몇 가지 요소를 더 살펴봅니다.
<figure>와 <figcaption>은 이미지, 코드, 비디오처럼 본문에서 참조하는 독립된 내용과 그 설명을 묶습니다.
<figure>
<img src="diagram.png" alt="시스템 아키텍처 다이어그램">
<figcaption>그림 1. 웹 애플리케이션의 기본 아키텍처</figcaption>
</figure><mark>는 검색어처럼 지금 맥락에서 눈여겨볼 부분을 표시합니다. 브라우저는 보통 노란 배경으로 보여 줍니다.
<p>이 문장에서 <mark>가장 중요한 부분</mark>은 바로 이것입니다.</p><time>은 날짜와 시간을 나타냅니다. 화면에는 “크리스마스”나 “오늘 밤 11시”처럼 사람이 읽기 좋은 글을 보여 주고, datetime 속성에는 2025-12-25나 2025-06-14T23:00처럼 프로그램이 읽을 수 있는 형식으로 같은 시점을 적습니다. 검색 엔진이나 캘린더 도구는 이 값을 읽어 날짜를 정확히 처리합니다.
<p>이 이벤트는 <time datetime="2025-12-25">크리스마스</time>에 시작합니다.</p>
<p>게시물 작성 시간: <time datetime="2025-06-14T23:00">오늘 밤 11시</time></p>멀티미디어 요소
예전에는 웹 페이지에서 비디오나 오디오를 재생하려면 Flash 같은 플러그인을 설치해야 했습니다. 이제는 <video>와 <audio> 요소로 플러그인 없이 미디어를 넣고 재생할 수 있습니다.
비디오: <video>
<video>는 페이지에 비디오를 넣습니다. 다음 예는 자주 쓰는 속성을 한꺼번에 붙인 것이고, 각 속성의 뜻은 코드 아래에서 하나씩 봅니다. 여는 태그와 닫는 태그 사이의 문장과 링크는 <video>를 지원하지 않는 브라우저에서만 보입니다.
<video src="my_video.mp4" controls width="640" height="360" poster="poster.jpg" autoplay loop muted>
죄송합니다. 귀하의 브라우저는 비디오 태그를 지원하지 않습니다.
<a href="my_video.mp4">비디오 다운로드</a>
</video>주요 속성은 다음과 같습니다.
src: 비디오 파일의 경로입니다.controls: 재생과 일시 정지, 볼륨, 진행 막대 같은 브라우저의 기본 조작 화면을 보여 줍니다.width,height: 플레이어의 너비와 높이입니다. 이미지처럼 비율을 알려 주는 데 쓰고, 표시 크기는 CSS로 조절합니다.poster: 재생하기 전에 보여 줄 이미지의 경로입니다.autoplay: 페이지를 열면 자동으로 재생합니다. 소리가 나는 자동 재생은 사용자를 놀라게 하므로, 대부분의 브라우저는 소리를 끈 자동 재생은 허용하지만 소리가 나는 자동 재생은 사용자가 그 사이트에서 조작하기 전에는 대개 막습니다.loop: 끝까지 재생하면 처음부터 다시 재생합니다.muted: 처음부터 소리를 끕니다. 자동 재생을 쓰려면 보통 함께 지정해야 합니다.
<video>와 종료 태그 사이의 글과 링크는 <video> 요소 자체를 모르는 아주 오래된 브라우저에서만 보입니다. 파일을 찾지 못했을 때 대신 보여 주는 오류 안내는 아닙니다.
브라우저마다 지원하는 영상 형식(코덱)이 다를 수 있으므로, <source> 요소로 여러 형식의 파일을 함께 제공할 수 있습니다. 브라우저는 위에서부터 읽어 재생할 수 있는 첫 번째 파일을 고릅니다.
<video controls>
<source src="video.webm" type="video/webm">
<source src="video.mp4" type="video/mp4">
브라우저가 비디오를 지원하지 않습니다.
</video>오디오: <audio>
<audio>는 페이지에 오디오를 넣습니다. src, controls, autoplay, loop, muted, <source>의 쓰임은 <video>와 같습니다.
<audio src="background_music.mp3" controls>
오디오 요소를 지원하지 않는 브라우저입니다.
<a href="background_music.mp3">오디오 파일 다운로드</a>
</audio>controls를 빼면 오디오 요소는 화면에 아무것도 보이지 않으므로, 사용자가 재생하거나 멈출 방법이 없어집니다. 배경 음악처럼 자동으로 소리를 내는 기능은 대부분의 브라우저가 막으며, 스크린 리더의 음성과 겹쳐 방해가 되므로 쓰지 않는 편이 좋습니다.
더 깊이: 브라우저는 언제 자동 재생을 허용할까
자동 재생을 허용하는 조건은 HTML 표준이 아니라 브라우저마다 정한 정책입니다. 예를 들어 Chrome은 소리를 끈 자동 재생을 항상 허용하고, 소리가 나는 자동 재생은 사용자가 그 사이트에서 클릭이나 탭 같은 조작을 한 뒤, 데스크톱에서 그 사이트의 미디어 참여 지수(Media Engagement Index)가 기준을 넘었을 때, 또는 사이트를 홈 화면에 추가하거나 PWA로 설치했을 때 허용합니다. 미디어 참여 지수는 사용자가 그 사이트에서 소리가 나는 영상을 재생해 본 이력을 바탕으로 합니다. 그래서 같은 페이지도 처음 방문한 사람과 자주 오는 사람에게 다르게 동작할 수 있습니다.
자바스크립트로 재생할 때는 이 차이를 코드에서 다뤄야 합니다. video.play()는 Promise를 돌려주고, 브라우저가 재생을 막으면 이 Promise가 거부됩니다. 거부를 처리하지 않으면 재생 중이라고 가정한 화면이 실제 상태와 어긋나므로, 거부되었을 때는 재생 버튼을 보여 주고 사용자가 누르면 다시 play()를 호출하는 식으로 만듭니다. Chrome의 정책과 권장 처리 방법은 Chrome의 자동 재생 정책 설명에 있습니다.
새 입력 유형과 속성
<input>의 type에는 입력의 종류를 세분화한 값이 많이 추가되었습니다. 알맞은 유형을 쓰면 브라우저가 기본 검사를 해 주고, 모바일 기기는 그 입력에 맞는 키보드를 보여 줍니다.
type="email": 이메일 주소입니다. 제출할 때 형식을 검사하며, 모바일 키보드에@가 보입니다.type="url": URL입니다. 제출할 때https://같은 형식인지 검사합니다.type="tel": 전화번호입니다. 모바일에서 숫자 키패드를 보여 주지만, 나라마다 형식이 달라 형식을 검사하지는 않습니다.type="number": 숫자입니다.min,max,step으로 범위와 간격을 정합니다.type="range": 슬라이더로 범위 안의 숫자를 고릅니다.type="date",type="time",type="datetime-local": 날짜, 시간, 날짜와 시간을 고르는 선택기를 보여 줍니다.type="color": 색상 선택기를 보여 줍니다.type="search": 검색어 입력란입니다. 브라우저에 따라 입력을 지우는 버튼이 생깁니다.
type="range"는 다음처럼 씁니다.
<label for="volume">볼륨:</label>
<input type="range" id="volume" name="volume" min="0" max="100" value="50">함께 쓰는 속성도 있습니다.
placeholder: 입력이 비어 있을 때 보이는 안내 문구입니다.required: 반드시 채워야 하는 필드로, 비어 있으면 제출이 막힙니다.autofocus: 페이지를 열면 이 필드에 바로 초점을 줍니다. 스크린 리더 사용자에게는 페이지의 앞부분을 건너뛰게 하므로 꼭 필요할 때만 씁니다.min,max,step:number나range에서 최솟값, 최댓값, 증감 간격입니다.pattern: 값이 따라야 할 형식을 정규 표현식으로 정합니다. 예를 들어pattern="[0-9]{3}-[0-9]{4}-[0-9]{4}"는010-1234-5678같은 형식만 허용합니다. 값 전체가 이 패턴과 맞아야 하며, 빈 값은 검사하지 않습니다.list와<datalist>: 입력란에 자동 완성 제안을 보여 줍니다.<datalist>의id를 입력의list속성에 적어 연결합니다.
<label for="browser">선호하는 브라우저:</label>
<input list="browsers" name="browser" id="browser">
<datalist id="browsers">
<option value="Chrome">
<option value="Firefox">
<option value="Safari">
<option value="Edge">
</datalist>입력란에 초점을 주거나 글자를 입력하면 네 브라우저 이름이 제안으로 나타납니다. 다만 <select>와 달리 제안은 고르기 쉽게 보여 줄 뿐이어서, 목록에 없는 값도 직접 입력해 제출할 수 있습니다.
더 깊이: pattern이 조용히 무시되는 경우
pattern의 값은 자바스크립트의 정규 표현식으로 해석되는데, 표준은 이 식을 v 플래그(unicodeSets)를 켜고 만들도록 정합니다. 2023년 중반 이전에는 u 플래그를 썼고, 이 변경으로 문자 클래스 [...] 안의 규칙이 엄격해졌습니다. v 플래그에서는 ]와 \ 말고도 (, ), [, {, }, /, -, |를 글자 그대로 쓰려면 문자 클래스 안에서 \로 이스케이프해야 합니다.
문제는 잘못된 정규 표현식이 오류를 내지 않는다는 점입니다. 값이 올바른 정규 표현식이 아니면 브라우저는 pattern이 없는 것처럼 아무 검사도 하지 않습니다. 예를 들어 영문과 숫자, 하이픈을 허용하려고 pattern="[A-Za-z0-9-]+"처럼 하이픈을 문자 클래스 끝에 그냥 적으면, v 플래그에서는 잘못된 식이 되어 어떤 값이든 통과합니다. 같은 뜻은 [A-Za-z0-9\-]+처럼 하이픈을 이스케이프해 적어야 합니다.
그래서 pattern을 정한 뒤에는 맞지 않는 값을 실제로 넣어 제출이 막히는지 확인하는 것이 좋습니다. 개발자 도구의 콘솔에서 new RegExp('[A-Za-z0-9-]+', 'v')처럼 같은 식을 v 플래그로 만들어 보면, 잘못된 식은 그 자리에서 SyntaxError를 냅니다. 이 규칙은 MDN의 pattern 설명에 정리되어 있습니다.
Web API 둘러보기
Web API는 브라우저가 자바스크립트에 제공하는 기능의 창구입니다. HTML 요소처럼 태그 하나를 추가해서 쓰는 것이 아니라, 자바스크립트 코드로 불러 씁니다. 여기서는 주요 API의 개념만 소개하고, 자세한 사용법은 뒤의 자바스크립트 장에서 다룹니다.
- Geolocation API: 사용자의 현재 위치(위도와 경도)를 얻습니다. 지도나 위치 기반 서비스에 쓰며, HTTPS 페이지에서 사용자가 허락했을 때만 동작합니다. 사용자가 거절할 때를 대비한 대안도 만들어 둡니다.
- Web Storage API: 브라우저에 데이터를 저장합니다.
localStorage에 저장한 값은 같은 출처(origin)에서 브라우저를 닫았다 열어도 대개 남아 있어 사용자 설정 같은 데 씁니다. 하지만 사용자가 지우거나 비공개 탐색 모드에서는 사라질 수 있으므로 영구 보관을 보장하지는 않습니다.sessionStorage에 저장한 값은 그 탭에서만 유지되어, 새로고침해도 남지만 탭을 닫으면 지워집니다. 두 저장소 모두 페이지의 스크립트가 읽을 수 있으므로 비밀번호 같은 민감한 정보는 저장하지 않습니다. - Canvas API:
<canvas>요소에 자바스크립트로 2D 그래픽을 그립니다. 차트, 그림판, 간단한 게임에 씁니다. - Drag and Drop API: 요소나 파일을 마우스로 끌어다 놓는 기능을 만듭니다. 파일 업로드나 목록의 순서 바꾸기에 씁니다.
- Web Workers API: 오래 걸리는 계산을 백그라운드에서 실행해, 계산하는 동안에도 화면이 멈추지 않게 합니다. Worker는 화면의 DOM을 직접 바꿀 수 없으므로, 결과를 메시지로 페이지에 보내고 화면은 페이지 쪽 코드가 고칩니다.
- Fetch API: 서버에 데이터를 요청하거나 보내고 응답을 비동기로 받습니다. 받은 데이터로 페이지를 새로고침하지 않고 내용을 바꿀 수 있습니다. 네트워크가 끊긴 것은 요청 자체의 실패이고,
404나500은 오류 상태를 담은 응답입니다.fetch()는 응답을 받으면 상태 코드와 상관없이 성공으로 끝나므로,response.ok나 상태 코드를 직접 확인해야 합니다.
이 밖에도 오프라인 동작을 돕는 Service Worker, 서버와 실시간으로 메시지를 주고받는 WebSocket 같은 API가 있습니다. 기능마다 지원하는 브라우저와 사용 조건이 다르므로, 쓰기 전에 문서에서 지원 범위와 필요한 권한을 확인합니다.
실습: 미디어와 새 입력 유형
새 요소와 입력 유형을 써 보는 페이지를 만들어 봅니다. web-dev-practice 폴더에 html5_features.html을 만들고 다음 코드를 씁니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML5 신규 요소와 API</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 20px;
background-color: #f5f5f5;
color: #333;
}
.container {
max-width: 800px;
margin: 0 auto;
background-color: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
h1, h2 {
color: #007bff;
text-align: center;
margin-bottom: 30px;
}
video, audio {
display: block;
margin: 20px auto;
max-width: 100%;
border-radius: 8px;
box-shadow: 2px 2px 8px rgba(0,0,0,0.1);
}
form {
margin-top: 40px;
padding: 20px;
border: 1px solid #eee;
border-radius: 8px;
background-color: #fdfdfd;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
color: #555;
}
input[type="email"],
input[type="tel"],
input[type="url"],
input[type="number"],
input[type="date"],
input[type="time"],
input[type="search"],
input[type="color"],
input[type="range"] {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 1em;
box-sizing: border-box; /* padding과 border를 너비에 포함 */
}
input[type="range"] {
padding: 0;
height: 25px; /* 높이 조정 */
}
button {
background-color: #28a745;
color: white;
padding: 12px 25px;
border: none;
border-radius: 5px;
font-size: 1.1em;
cursor: pointer;
transition: background-color 0.3s ease;
margin-top: 20px;
}
button:hover {
background-color: #218838;
}
</style>
</head>
<body>
<div class="container">
<h1>HTML5의 새로운 기능 탐색</h1>
<section>
<h2>멀티미디어 콘텐츠</h2>
<p>HTML5는 플러그인 없이도 비디오와 오디오를 쉽게 삽입할 수 있게 되었습니다.</p>
<h3>예시 비디오</h3>
<video controls width="640" style="width: 100%; height: auto;">
<source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
<source src="https://www.w3schools.com/html/mov_bbb.ogg" type="video/ogg">
<p>죄송합니다. 귀하의 브라우저는 비디오를 지원하지 않습니다.</p>
</video>
<h3>예시 오디오</h3>
<audio controls>
<source src="https://www.w3schools.com/html/horse.mp3" type="audio/mpeg">
<source src="https://www.w3schools.com/html/horse.ogg" type="audio/ogg">
<p>죄송합니다. 귀하의 브라우저는 오디오를 지원하지 않습니다.</p>
</audio>
<p><small>(* 비디오/오디오 소스는 W3Schools 예시를 참조했습니다.)</small></p>
</section>
<section>
<h2>새로운 폼 입력 타입</h2>
<p>사용자로부터 더욱 다양한 종류의 정보를 쉽게 입력받을 수 있습니다.</p>
<form action="#" method="get">
<div class="form-group">
<label for="userEmail">이메일:</label>
<input type="email" id="userEmail" name="userEmail" placeholder="[email protected]" required>
</div>
<div class="form-group">
<label for="phoneNumber">전화번호:</label>
<input type="tel" id="phoneNumber" name="phoneNumber" placeholder="010-1234-5678" pattern="[0-9]{3}-[0-9]{4}-[0-9]{4}">
</div>
<div class="form-group">
<label for="websiteUrl">개인 웹사이트:</label>
<input type="url" id="websiteUrl" name="websiteUrl" placeholder="https://my-portfolio.dev">
</div>
<div class="form-group">
<label for="favColor">선호하는 색상:</label>
<input type="color" id="favColor" name="favColor" value="#4285F4">
</div>
<div class="form-group">
<label for="eventDate">이벤트 날짜:</label>
<input type="date" id="eventDate" name="eventDate">
</div>
<div class="form-group">
<label for="meetingTime">회의 시간:</label>
<input type="time" id="meetingTime" name="meetingTime">
</div>
<div class="form-group">
<label for="quantity">수량 (1-10):</label>
<input type="number" id="quantity" name="quantity" min="1" max="10" value="1">
</div>
<div class="form-group">
<label for="satisfaction">만족도 (0-100):</label>
<input type="range" id="satisfaction" name="satisfaction" min="0" max="100" value="75">
</div>
<div class="form-group">
<label for="searchQuery">검색어:</label>
<input type="search" id="searchQuery" name="q" placeholder="검색어를 입력하세요..." list="searchSuggestions">
<datalist id="searchSuggestions">
<option value="HTML5">
<option value="CSS3">
<option value="JavaScript API">
</datalist>
</div>
<button type="submit">폼 제출</button>
</form>
</section>
</div>
</body>
</html>비디오와 오디오는 W3Schools의 예시 파일을 불러오므로, 재생하려면 인터넷에 연결되어 있어야 하고 브라우저가 그 형식을 지원해야 합니다. 재생 버튼이 보이는 것과 파일이 실제로 재생되는 것은 따로 확인하며, 재생되지 않으면 Network 패널에서 미디어 파일의 요청과 응답 상태를 먼저 봅니다. 비디오의 width="640"은 HTML 속성으로 적은 너비이지만, style의 width: 100%가 더 우선하므로 실제 표시 너비는 부모 영역에 맞춰집니다. 이 예제에는 height 속성이 없어서 width 하나만으로는 비율을 미리 알려 주지 못합니다. 이미지에서 본 것처럼 비율을 알려 주려면 width와 height를 함께 적어야 합니다. 포스터 이미지는 준비하지 않았으므로 poster를 생략했습니다.
폼은 method="get"이고 action="#"이므로, 검사를 통과해 제출하면 같은 페이지를 다시 열면서 주소에 입력값이 쿼리 문자열로 붙습니다. 이 페이지에는 값을 저장하거나 처리하는 서버 코드가 없으므로, 연습할 때는 개인 정보 대신 연습용 값을 씁니다.
정리
- HTML은 버전 번호 없이 계속 갱신되는 표준이며, HTML5는 시맨틱 요소, 미디어, 새 입력 유형, Web API를 묶어 부르는 이름입니다.
<time>의datetime은 사람이 읽는 글과 별도로 프로그램이 읽을 날짜를,<mark>는 눈여겨볼 부분을 나타냅니다.<video>와<audio>는controls로 기본 조작을 보여 주고,<source>로 여러 형식을 제공하며, 소리 나는 자동 재생은 대부분 막힙니다.- 새 입력 유형은 브라우저의 기본 검사와 알맞은 키보드를 제공하며,
pattern은 값 전체를 검사하지만 빈 값은 검사하지 않습니다. datalist는 제안일 뿐 목록 밖의 값도 허용합니다.- Web API는 자바스크립트로 쓰는 브라우저 기능이며, 위치 정보처럼 보안 컨텍스트와 권한이 필요한 것도 있습니다.
연습 문제
1. 전화번호 입력 규칙
이메일에 [email protected]을 입력하고, 전화번호를 ① 빈 값, ② 01012345678, ③ 010-1234-5678로 바꿔 가며 제출했습니다. 각각 제출될까요? 이메일을 비우면 어떻게 될까요?
해설 보기
①은 제출됩니다. 전화번호에는 required가 없고, pattern은 빈 값을 검사하지 않기 때문입니다. ②는 하이픈이 없어 pattern과 맞지 않으므로 형식 안내가 나오며 제출이 막히고, ③은 패턴과 맞으므로 제출됩니다. type="tel"만으로는 형식을 검사하지 않으므로, 이 검사는 pattern이 하는 것입니다.
이메일을 비우면 required 때문에 필수 입력 안내가 나오고 제출이 막힙니다.
2. 제안에 없는 검색어
검색어 칸에 제안 목록에 없는 DOM을 직접 입력해 제출했습니다. 제출될까요? 제출된 뒤 주소창에는 무엇이 보일까요?
해설 보기
제출됩니다. datalist는 입력을 돕는 제안 목록일 뿐 목록 밖의 값을 막지 않습니다. 제안한 값 중 하나만 허용하려면 select를 쓰거나 따로 검사해야 합니다.
GET 방식이므로 주소 뒤에 ?userEmail=learner%40example.com&phoneNumber=&websiteUrl=&favColor=%234285f4&eventDate=&meetingTime=&quantity=1&satisfaction=75&q=DOM 같은 쿼리 문자열이 붙고, action="#"에서 온 빈 프래그먼트가 남아 주소는 ...&q=DOM#처럼 #으로 끝납니다. 입력값의 @는 %40, 색상 값의 #은 %23으로 인코딩되고, 색상 값은 브라우저가 소문자로 바꿉니다. 이름이 name 속성의 값이라는 점도 확인할 수 있습니다. 검색어의 키는 id의 searchQuery가 아니라 name의 q입니다.
3. 선택 입력과 형식 검사
전화번호를 입력하지 않아도 되지만, 입력했다면 반드시 010-1234-5678 형식이어야 한다는 규칙을 만들려고 합니다. 지금 코드에서 무엇을 바꿔야 할까요? 반대로 반드시 입력하게 하려면 무엇을 더할까요?
해설 보기
지금 코드가 이미 그 규칙입니다. required가 없으므로 빈 값은 허용되고, 값이 있으면 pattern이 형식을 검사합니다. 빈 값과 형식이 틀린 값은 서로 다른 조건이기 때문입니다.
반드시 입력하게 하려면 required를 더합니다. 어느 경우든 브라우저의 검사는 우회할 수 있으므로, 서버에서도 같은 규칙을 검사해야 합니다.
다음 글 SVG와 캔버스 기초에서는 도형을 HTML처럼 선언하는 SVG와, 자바스크립트로 픽셀을 그리는 Canvas를 비교하며 그래픽을 직접 그려 봅니다.