[WEB-006][기초] 폼 검증과 친절한 오류 메시지 만들기
페이지 정보

본문
[이번 수업]
이메일 폼에 검증과 접근 가능한 오류를 적용합니다.
[선수지식]
WEB-001·004·005의 HTML·접근성·DOM 이벤트를 알면 됩니다.
[학습목표]
1. label·name·autocomplete과 검증 속성을 연결한다.
2. Validity API로 오류를 표시하고 해당 입력에 포커스를 옮긴다.
3. 브라우저 검증과 서버 검증의 경계를 설명한다.
[핵심개념]
폼(form)은 입력값을 묶어 제출합니다. input의 `name`은 제출 이름입니다. label의 `for`와 input의 `id`를 연결하고 `autocomplete`으로 값의 의미를 알립니다.
`required`, `minlength`, `type="email"`, `min`, `max`는 입력 제약입니다. `input.validity`의 `valueMissing`, `tooShort`, `typeMismatch`로 원인을 읽습니다. 제약은 HTML에 선언하고 JavaScript는 안내를 보완합니다.
오류는 색뿐 아니라 수정 방법을 글로 알립니다. `aria-describedby`로 오류를 연결하고 `aria-invalid`로 상태를 표시합니다. 실패 시 입력에 포커스를 두고 결과는 `role="status"`로 알립니다.
`novalidate`는 기본 말풍선만 끕니다. 브라우저 검증은 우회할 수 있으므로 서버가 자료형·길이·허용값·권한을 다시 검사해야 합니다.
[따라하기]
다음을 form.html로 저장합니다. 서버나 라이브러리는 필요 없습니다.
```html
<!doctype html>
<html lang="ko">
<meta charset="utf-8">
<title>폼 검증 연습</title>
<h1>신청</h1>
<form id="signup" novalidate>
<label for="email">이메일</label>
<input id="email" name="email" type="email" required
autocomplete="email" aria-describedby="email-error">
<p id="email-error" aria-live="polite"></p>
<button type="submit">확인</button>
<p id="result" role="status"></p>
</form>
<script>
const form = document.querySelector("#signup");
const email = document.querySelector("#email");
const error = document.querySelector("#email-error");
const result = document.querySelector("#result");
function validate() {
let message = "";
if (email.validity.valueMissing) message = "필수 입력입니다.";
else if (email.validity.typeMismatch) {
message = "이메일 형식을 확인하세요.";
}
error.textContent = message;
email.setAttribute("aria-invalid", String(Boolean(message)));
return !message;
}
email.addEventListener("input", validate);
form.addEventListener("submit", (event) => {
event.preventDefault();
if (!validate()) {
result.textContent = "입력을 다시 확인하세요.";
email.focus();
return;
}
result.textContent = "입력 형식을 확인했습니다.";
});
</script>
</html>
```
파일을 두 번 눌러 엽니다. 터미널은 macOS `open form.html`, Windows `start form.html`, Linux `xdg-open form.html`을 씁니다.
빈 값은 필수 오류, `hello`는 형식 오류, `hello@example.com`은 성공 문장을 표시합니다. 서버 전송은 없습니다.
[흔한 실수]
- placeholder만 쓰고 label을 생략합니다.
- 빨간색만 표시하고 해결 방법을 쓰지 않습니다.
- 수정 뒤 오류 상태를 지우지 않습니다.
- JavaScript 검증만 믿고 서버 검증을 생략합니다.
[보안 주의]
서버에서 자료형, 길이, 허용값, 권한을 다시 검증하고 요청 크기·빈도를 제한하세요. 입력을 화면에 표시할 때 `innerHTML` 대신 안전한 인코딩이나 `textContent`를 사용합니다. 민감정보를 URL·로그에 남기거나 오류에 내부 경로·비밀값을 노출하지 않습니다.
[직접 해볼 과제]
1. 이름 필드를 추가하고 `required`, `minlength="2"` 오류를 연결하세요.
2. Tab·Shift+Tab·Enter만으로 입력, 오류 이동, 성공 확인을 시험하세요.
[확인문제]
1. label의 for와 input의 id를 연결하는 이유는 무엇인가요?
2. aria-describedby와 aria-invalid는 무엇을 전달하나요?
3. 브라우저 검증 뒤에도 서버 검증이 필요한 이유는 무엇인가요?
[다음 학습]
WEB-007에서는 입력 결과를 상태로 보관하고 화면을 다시 렌더링합니다.
[공식 참고 자료]
- HTML 폼 표준: https://html.spec.whatwg.org/multipage/forms.html
- WCAG 오류 식별 설명: https://www.w3.org/WAI/WCAG22/Understanding/error-identification.html
- OWASP 입력 검증 지침: https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html
이메일 폼에 검증과 접근 가능한 오류를 적용합니다.
[선수지식]
WEB-001·004·005의 HTML·접근성·DOM 이벤트를 알면 됩니다.
[학습목표]
1. label·name·autocomplete과 검증 속성을 연결한다.
2. Validity API로 오류를 표시하고 해당 입력에 포커스를 옮긴다.
3. 브라우저 검증과 서버 검증의 경계를 설명한다.
[핵심개념]
폼(form)은 입력값을 묶어 제출합니다. input의 `name`은 제출 이름입니다. label의 `for`와 input의 `id`를 연결하고 `autocomplete`으로 값의 의미를 알립니다.
`required`, `minlength`, `type="email"`, `min`, `max`는 입력 제약입니다. `input.validity`의 `valueMissing`, `tooShort`, `typeMismatch`로 원인을 읽습니다. 제약은 HTML에 선언하고 JavaScript는 안내를 보완합니다.
오류는 색뿐 아니라 수정 방법을 글로 알립니다. `aria-describedby`로 오류를 연결하고 `aria-invalid`로 상태를 표시합니다. 실패 시 입력에 포커스를 두고 결과는 `role="status"`로 알립니다.
`novalidate`는 기본 말풍선만 끕니다. 브라우저 검증은 우회할 수 있으므로 서버가 자료형·길이·허용값·권한을 다시 검사해야 합니다.
[따라하기]
다음을 form.html로 저장합니다. 서버나 라이브러리는 필요 없습니다.
```html
<!doctype html>
<html lang="ko">
<meta charset="utf-8">
<title>폼 검증 연습</title>
<h1>신청</h1>
<form id="signup" novalidate>
<label for="email">이메일</label>
<input id="email" name="email" type="email" required
autocomplete="email" aria-describedby="email-error">
<p id="email-error" aria-live="polite"></p>
<button type="submit">확인</button>
<p id="result" role="status"></p>
</form>
<script>
const form = document.querySelector("#signup");
const email = document.querySelector("#email");
const error = document.querySelector("#email-error");
const result = document.querySelector("#result");
function validate() {
let message = "";
if (email.validity.valueMissing) message = "필수 입력입니다.";
else if (email.validity.typeMismatch) {
message = "이메일 형식을 확인하세요.";
}
error.textContent = message;
email.setAttribute("aria-invalid", String(Boolean(message)));
return !message;
}
email.addEventListener("input", validate);
form.addEventListener("submit", (event) => {
event.preventDefault();
if (!validate()) {
result.textContent = "입력을 다시 확인하세요.";
email.focus();
return;
}
result.textContent = "입력 형식을 확인했습니다.";
});
</script>
</html>
```
파일을 두 번 눌러 엽니다. 터미널은 macOS `open form.html`, Windows `start form.html`, Linux `xdg-open form.html`을 씁니다.
빈 값은 필수 오류, `hello`는 형식 오류, `hello@example.com`은 성공 문장을 표시합니다. 서버 전송은 없습니다.
[흔한 실수]
- placeholder만 쓰고 label을 생략합니다.
- 빨간색만 표시하고 해결 방법을 쓰지 않습니다.
- 수정 뒤 오류 상태를 지우지 않습니다.
- JavaScript 검증만 믿고 서버 검증을 생략합니다.
[보안 주의]
서버에서 자료형, 길이, 허용값, 권한을 다시 검증하고 요청 크기·빈도를 제한하세요. 입력을 화면에 표시할 때 `innerHTML` 대신 안전한 인코딩이나 `textContent`를 사용합니다. 민감정보를 URL·로그에 남기거나 오류에 내부 경로·비밀값을 노출하지 않습니다.
[직접 해볼 과제]
1. 이름 필드를 추가하고 `required`, `minlength="2"` 오류를 연결하세요.
2. Tab·Shift+Tab·Enter만으로 입력, 오류 이동, 성공 확인을 시험하세요.
[확인문제]
1. label의 for와 input의 id를 연결하는 이유는 무엇인가요?
2. aria-describedby와 aria-invalid는 무엇을 전달하나요?
3. 브라우저 검증 뒤에도 서버 검증이 필요한 이유는 무엇인가요?
[다음 학습]
WEB-007에서는 입력 결과를 상태로 보관하고 화면을 다시 렌더링합니다.
[공식 참고 자료]
- HTML 폼 표준: https://html.spec.whatwg.org/multipage/forms.html
- WCAG 오류 식별 설명: https://www.w3.org/WAI/WCAG22/Understanding/error-identification.html
- OWASP 입력 검증 지침: https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html
- 이전글[BACK-006][기초] 로그인 세션과 토큰 흐름 이해하기 26.09.01
- 다음글[JSTS-006][기초] npm·모듈·패키지 한 번에 이해하기 26.09.01
댓글목록
등록된 댓글이 없습니다.
