← JavaScript 강의 목록으로
📝
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.jsinput/submit 이벤트
02_validation.jsHTML5 검증 활용
03_formdata.jsFormData 사용
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>

자주 하는 실수

  1. `submit` 에서 `preventDefault` 를 잊어 페이지가 새로고침.
  2. `e.target.value` 대신 `e.value` 로 접근.
  3. checkbox 의 값은 `.checked`, 텍스트는 `.value` 라는 점을 혼동.
  4. FormData 사용 시 input 에 `name` 속성을 빼먹음.
  5. 비밀번호 일치 등 도메인 검증을 HTML5 만으로 처리하려 함.

FAQ

Q1. checkValidity 와 reportValidity 차이?

checkValidity 는 검사만, reportValidity 는 실패 시 사용자에게 메시지를 띄웁니다.

Q2. controlled 입력이 항상 좋은가요?

매 키마다 렌더링 비용이 있을 수 있으니 필요할 때만 사용합니다.

Q3. file input 도 FormData 로 전송 가능?

가능하고 `multipart/form-data` 로 자동 인코딩됩니다.

과제

이메일과 비밀번호 입력 폼을 만들고, 제출 시 FormData 로 값을 콘솔에 출력하세요. 비어 있으면 막습니다.

homework/README.md

이메일과 비밀번호 입력을 받는 폼을 만들고:

  1. 제출 시 새로고침을 막는다.
  2. FormData 로 값을 모아 콘솔에 출력한다.
  3. 빈 값이면 제출을 막는다.

답안은 `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/) — 서버와 데이터 주고받기

예제 코드 / 강의 자료

전체 강의 자료와 예제 코드는 GitHub에서 자유롭게 받아볼 수 있습니다.

GitHub에서 보기 ↗