📝
DOM
중급 · 선수: 19_이벤트_처리
20. 폼과 입력
브라우저가 자동으로 검증해 줍니다. `form.checkValidity()`, 요소의 `validity` 객체로 자바스크립트에서도 검사할 수 있습니다.
formsubmitvalidationFormData
소요 시간
⏱ 약 1.5시간
난이도
📊 중급
선수 조건
🎯 단원 19
결과물
브라우저가 자동으로 검증해 줍니다. `form.checkValidity()`, 요소의 `validity` 객체로 자바스크립트에서도 검사할 수 있습니다.
이 강의에서 배우는 것
- 1input/change/submit 이벤트의 차이를 안다.
- 2HTML5 내장 검증(required, type, pattern) 을 사용한다.
- 3`FormData` 로 폼 데이터를 한 번에 수집한다.
- 4자바스크립트로 입력값을 제어(controlled)하고 검증한다.
- 5제출 시 `preventDefault` 후 fetch 등으로 전송하는 패턴을 익힌다.
소개
브라우저가 자동으로 검증해 줍니다. `form.checkValidity()`, 요소의 `validity` 객체로 자바스크립트에서도 검사할 수 있습니다.
핵심 개념
1. input vs change vs submit
- `input`: 값이 바뀔 때마다 (텍스트 입력 중 매 키)
- `change`: 포커스가 벗어나며 값이 바뀌었을 때 (text), 또는 선택이 바뀐 즉시 (select/checkbox)
- `submit`: 폼이 제출될 때 (form 요소)
javascript
form.addEventListener("submit", (e) => {
e.preventDefault();
// 데이터 처리
});2. HTML5 검증
html
<input type="email" required minlength="3" />브라우저가 자동으로 검증해 줍니다. `form.checkValidity()`, 요소의 `validity` 객체로 자바스크립트에서도 검사할 수 있습니다.
3. FormData
javascript
const data = new FormData(form);
data.get("email");
for (const [k, v] of data) console.log(k, v);`FormData` 는 파일을 포함한 전송에도 사용됩니다.
4. controlled 입력
입력값을 자바스크립트가 항상 가지고 있고 화면에도 그대로 반영하는 패턴.
javascript
input.addEventListener("input", (e) => {
state.value = e.target.value.toUpperCase();
input.value = state.value;
});5. 제출 패턴
javascript
form.addEventListener("submit", async (e) => {
e.preventDefault();
if (!form.checkValidity()) {
form.reportValidity();
return;
}
const data = new FormData(form);
// 다음 단원에서 배울 fetch 로 전송
});핵심 예제
| 파일 | 다루는 내용 |
|---|---|
| index.html | 예제 폼 |
| 01_input_submit.js | input/submit 이벤트 |
| 02_validation.js | HTML5 검증 활용 |
| 03_formdata.js | FormData 사용 |
| 04_controlled.js | 자바스크립트가 값 통제 |
src/01_input_submit.js
javascript
/**
* input 과 submit 이벤트.
*/
const form = document.querySelector("#loginForm");
const email = form.querySelector("[name=email]");
email.addEventListener("input", (e) => {
console.log("입력 중:", e.target.value);
});
form.addEventListener("submit", (e) => {
e.preventDefault();
console.log("폼 제출됨");
});
src/02_validation.js
javascript
/**
* HTML5 검증 API 활용.
*/
const form = document.querySelector("#loginForm");
form.addEventListener("submit", (e) => {
if (!form.checkValidity()) {
e.preventDefault();
form.reportValidity();
console.log("검증 실패");
} else {
console.log("검증 통과");
}
});
src/03_formdata.js
javascript
/**
* FormData 로 한 번에 값 수집.
*/
const form = document.querySelector("#loginForm");
form.addEventListener("submit", (e) => {
e.preventDefault();
if (!form.checkValidity()) {
form.reportValidity();
return;
}
const data = new FormData(form);
for (const [key, value] of data) {
console.log(`${key} = ${value}`);
}
});
src/04_controlled.js
javascript
/**
* 자바스크립트가 입력값을 통제(대문자로 강제).
*/
const username = document.querySelector("[name=username]");
const echo = document.querySelector("#echo");
username.addEventListener("input", (e) => {
const upper = e.target.value.toUpperCase();
e.target.value = upper;
echo.textContent = `현재 값: ${upper}`;
});
src/index.html
html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<title>폼과 입력</title>
</head>
<body>
<form id="loginForm">
<label>이메일 <input type="email" name="email" required /></label>
<label>비밀번호 <input type="password" name="password" required minlength="4" /></label>
<label>이름 <input type="text" name="username" /></label>
<label><input type="checkbox" name="remember" /> 자동 로그인</label>
<button type="submit">제출</button>
</form>
<p id="echo"></p>
<script src="01_input_submit.js"></script>
<script src="02_validation.js"></script>
<script src="03_formdata.js"></script>
<script src="04_controlled.js"></script>
</body>
</html>
자주 하는 실수
- `submit` 에서 `preventDefault` 를 잊어 페이지가 새로고침.
- `e.target.value` 대신 `e.value` 로 접근.
- checkbox 의 값은 `.checked`, 텍스트는 `.value` 라는 점을 혼동.
- FormData 사용 시 input 에 `name` 속성을 빼먹음.
- 비밀번호 일치 등 도메인 검증을 HTML5 만으로 처리하려 함.
FAQ
Q1. checkValidity 와 reportValidity 차이?
checkValidity 는 검사만, reportValidity 는 실패 시 사용자에게 메시지를 띄웁니다.
Q2. controlled 입력이 항상 좋은가요?
매 키마다 렌더링 비용이 있을 수 있으니 필요할 때만 사용합니다.
Q3. file input 도 FormData 로 전송 가능?
가능하고 `multipart/form-data` 로 자동 인코딩됩니다.
과제
이메일과 비밀번호 입력 폼을 만들고, 제출 시 FormData 로 값을 콘솔에 출력하세요. 비어 있으면 막습니다.
homework/README.md
이메일과 비밀번호 입력을 받는 폼을 만들고:
- 제출 시 새로고침을 막는다.
- FormData 로 값을 모아 콘솔에 출력한다.
- 빈 값이면 제출을 막는다.
답안은 `answer/homework_01.html`, `answer/homework_01.js` 참고.
homework/answer/homework_01.html
html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<title>과제 20-1</title>
</head>
<body>
<form id="login">
<label>이메일 <input type="email" name="email" required /></label>
<label>비밀번호 <input type="password" name="password" required /></label>
<button type="submit">로그인</button>
</form>
<script src="homework_01.js"></script>
</body>
</html>
homework/answer/homework_01.js
javascript
/**
* 폼 제출 시 FormData 로 값을 출력합니다.
*/
const form = document.querySelector("#login");
form.addEventListener("submit", (event) => {
event.preventDefault();
if (!form.checkValidity()) {
form.reportValidity();
return;
}
const data = new FormData(form);
for (const [key, value] of data) {
console.log(`${key}: ${value}`);
}
});
다음 단원
[21_Fetch와_JSON](../../06_브라우저_API/21_Fetch와_JSON/) — 서버와 데이터 주고받기