// 헷갈렸던 실수
const inputUsername = e.target.value; // 문자열
console.log('유효한가?', inputUsername.validity.valid); // ❌ 문자열에는 validity 없음
// 올바른 이해
const inputValue = e.target.value; // 사용자 입력 텍스트 (문자열)
const inputElement = e.target; // HTML input 요소 (객체)
console.log('유효한가?', inputElement.validity.valid); // ✅ 정상 작동
e.target은 DOM 요소, e.target.value는 입력값. 각각의 역할을 명확히 구분.
2-3. setCustomValidity의 악순환 문제
// ❌ 악순환 구조
if (!inputElement.validity.valid) {
inputElement.setCustomValidity('에러'); // 이 순간부터 계속 invalid
}
// ✅ 단순하고 안정적
const handleChange = (e) => {
if (e.target.value.length > 0 && !e.target.checkValidity()) {
e.target.reportValidity();
}
};
valid가 false로 고정되어 조건문이 항상 true.
브라우저 기본 검증만 활용하는 것이 안정적.
2-4. 브라우저 검증 API 활용법
새로 배운 속성들
inputElement.validity.valid // 전체 검증 통과 여부
inputElement.validity.patternMismatch // 정규표현식 불일치
inputElement.validity.tooShort // 최소 길이 미달
inputElement.validity.valueMissing // 필수값 누락
inputElement.validationMessage // 브라우저 생성 에러 메시지
inputElement.checkValidity() // 검증 실행
inputElement.reportValidity() // 에러 메시지 표시
if (inputValue.length > 0 && !inputElement.checkValidity()) {
inputElement.reportValidity();
}
3. 최종 코드
// 목표
// 사용자 입력 검증 구현하기
// 조건
// 1.input 속성 이용하기
// 요구 사항
// 1. 이메일은 username@example.com 형식 검증
// 2. 비밀번호는 9자 이상, 대문자, 소문자, 숫자 1개씩 이상 포함
// 3. 이메일과 비밀번호 유효성 검사 각각 실시간 검사 실행 (사용자 입력과 동시에)
// 4. 유효성 검사를 무사히 마친 뒤 로그인 버튼을 누르면 얼럿 창에 UserEmail 명시
import styles from './LoginForm.module.css';
export default function LoginForm() {
// 사용자명 입력 시 실행되는 함수 (입력과 동시에 유효성 검사 및 이메일 상태 업데이트 )
const handleUserEmailChange = (e) => {
const inputElement = e.target;
const inputUserEmail= e.target.value; // 입력된 값을 변수에 저장
// 이메일 형식 실시간 검사
if (inputUserEmail.length > 0 && !inputElement.checkValidity()) {
inputElement.reportValidity();
}
};
// 비밀번호 입력 시 실행되는 함수 (입력과 동시에 유효성 검사)
const handleUserPasswordChange = (e) => {
const inputElement = e.target;
const inputUserPassword = e.target.value; // 입력된 비밀번호를 변수에 저장
// 비밀번호 형식 실시간 검사
if (inputUserPassword.length > 0 && !inputElement.checkValidity()) {
inputElement.reportValidity();
}
};
// 로그인 버튼 클릭 시 실행되는 함수
const handleSubmit = (e) => {
e.preventDefault();
// 제출 시점에 값 추출
const formData = new FormData(e.target);
const userEmail = formData.get('email');
alert(`Welcome, ${userEmail} 😀! Login successful.`);
};
return (
<div className={styles.container}>
<form onSubmit={handleSubmit} noValidate={false}>
<div className={styles.card}>
{/* 제목 영역 */}
<div className={styles.title}>
<h1>Login</h1>
</div>
{/* 입력 필드 영역 */}
<div className={styles.inputField}>
<div>
<label>
Email
<input
id="email"
name="email"
onChange={handleUserEmailChange}
type="email"
placeholder="username@example.com"
autoComplete="email"
required
title="올바른 이메일 형식을 입력해주세요"
/>
</label>
</div>
<div>
<label>
Password
<input
id="password"
name="password"
onChange={handleUserPasswordChange}
type="password"
placeholder="Enter your password"
pattern="(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d@$!%*?&]{9,}" // 9자 이상, 대소문자와 숫자 포함
minLength={9}
autoComplete="current-password"
required
title="9자 이상, 대문자/소문자/숫자를 포함해주세요"
/>
</label>
</div>
</div>
{/* 로그인 버튼 영역 */}
<div className={styles.button}>
<button type="submit">Login</button>
</div>
</div>
</form>
</div>
);
}