기본적인 폼 유효성 검사 구현
폼 유효성 검사는 사용자 입력의 정확성을 보장하고 잘못된 데이터가 서버로 전송되는 것을 방지하는 중요한 과정입니다.
React에서는 클라이언트 사이드 유효성 검사를 구현하여 사용자 경험을 향상시킬 수 있습니다.
실시간 유효성 검사
실시간 유효성 검사는 사용자가 입력하는 동안 즉시 피드백을 제공합니다.
import React, { useState } from 'react';
function RealTimeValidationForm() {
const [email, setEmail] = useState('');
const [emailError, setEmailError] = useState('');
const validateEmail = (value) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!value) {
setEmailError('Email is required');
} else if (!emailRegex.test(value)) {
setEmailError('Invalid email format');
} else {
setEmailError('');
}
};
const handleEmailChange = (e) => {
const value = e.target.value;
setEmail(value);
validateEmail(value);
};
return (
<form>
<div>
<label htmlFor="email">Email:</label>
<input
id="email"
type="email"
value={email}
onChange={handleEmailChange}
aria-invalid={!!emailError}
aria-describedby="email-error"
/>
{emailError && <span id="email-error" className="error">{emailError}</span>}
</div>
</form>
);
}
이 예제에서는 이메일 입력 필드의 실시간 유효성 검사를 구현했습니다.
사용자가 입력할 때마다 validateEmail
함수가 호출되어 유효성을 검사하고 적절한 에러 메시지를 표시합니다.
제출 시 유효성 검사
폼 제출 시에 모든 필드의 유효성을 한 번에 검사할 수도 있습니다.
import React, { useState } from 'react';
function SubmitValidationForm() {
const [formData, setFormData] = useState({ username: '', password: '' });
const [errors, setErrors] = useState({});
const validateForm = () => {
let newErrors = {};
if (!formData.username) newErrors.username = 'Username is required';
if (!formData.password) newErrors.password = 'Password is required';
else if (formData.password.length < 6) newErrors.password = 'Password must be at least 6 characters';
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const handleSubmit = (e) => {
e.preventDefault();
if (validateForm()) {
// 폼 제출 로직
console.log('Form submitted:', formData);
} else {
console.log('Form has errors');
}
};
const handleChange = (e) => {
const { name, value } = e.target;
setFormData({ ...formData, [name]: value });
};
return (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="username">Username:</label>
<input
id="username"
name="username"
value={formData.username}
onChange={handleChange}
aria-invalid={!!errors.username}
aria-describedby="username-error"
/>
{errors.username && <span id="username-error" className="error">{errors.username}</span>}
</div>
<div>
<label htmlFor="password">Password:</label>
<input
id="password"
name="password"
type="password"
value={formData.password}
onChange={handleChange}
aria-invalid={!!errors.password}
aria-describedby="password-error"
/>
{errors.password && <span id="password-error" className="error">{errors.password}</span>}
</div>
<button type="submit">Submit</button>
</form>
);
}
이 예제에서는 폼 제출 시 validateForm
함수를 호출하여 모든 필드의 유효성을 검사합니다.
유효성 검사를 통과하지 못하면 폼 제출이 방지되고 에러 메시지가 표시됩니다.
커스텀 유효성 검사 규칙 생성
복잡한 유효성 검사 규칙이 필요한 경우, 별도의 유효성 검사 함수를 만들어 사용할 수 있습니다.
const validationRules = {
required: (value) => value.trim() !== '' || 'This field is required',
minLength: (length) => (value) =>
value.length >= length || `Must be at least ${length} characters`,
maxLength: (length) => (value) =>
value.length <= length || `Must be no more than ${length} characters`,
pattern: (regex, message) => (value) =>
regex.test(value) || message
};
function validateField(value, rules) {
for (let rule of rules) {
const result = rule(value);
if (result !== true) return result;
}
return true;
}
// 사용 예:
const usernameRules = [
validationRules.required,
validationRules.minLength(3),
validationRules.maxLength(20),
validationRules.pattern(/^[a-zA-Z0-9_]+$/, 'Only alphanumeric characters and underscores are allowed')
];
const error = validateField(username, usernameRules);
이 접근 방식을 사용하면 재사용 가능한 유효성 검사 규칙을 만들고 조합할 수 있습니다.
접근성을 고려한 유효성 검사
접근성 있는 폼을 만들기 위해 다음 사항들을 고려해야 합니다.
- 적절한 레이블 사용 : 모든 입력 필드에 대해 명확한 레이블을 제공합니다.
- ARIA 속성 활용 :
aria-invalid
,aria-describedby
등의 속성을 사용하여 스크린 리더 사용자에게 유효성 상태를 알립니다. - 에러 메시지 연결 : 에러 메시지를 해당 입력 필드와 프로그래밍적으로 연결합니다.
- 키보드 접근성 : 모든 폼 요소와 에러 메시지에 키보드로 접근 가능해야 합니다.
<div>
<label htmlFor="email">Email:</label>
<input
id="email"
type="email"
value={email}
onChange={handleEmailChange}
aria-invalid={!!emailError}
aria-describedby="email-error"
/>
{emailError && (
<span id="email-error" className="error" role="alert">
{emailError}
</span>
)}
</div>
유효성 검사 상태에 따른 UI 변경
유효성 검사 결과에 따라 UI를 동적으로 변경할 수 있습니다.
<input
className={emailError ? 'input-error' : 'input-valid'}
// ... 다른 속성들
/>
<button type="submit" disabled={!isFormValid}>
Submit
</button>
이러한 방식으로 사용자에게 시각적 피드백을 제공하고, 폼이 유효하지 않을 때 제출을 방지할 수 있습니다.
주의사항
- 성능 고려 : 실시간 유효성 검사를 구현할 때 성능에 주의해야 합니다. 필요한 경우 디바운싱 기법을 사용하여 불필요한 검사를 줄일 수 있습니다.
- 서버 사이드 검증 : 클라이언트 사이드 유효성 검사는 편의성을 위한 것이며, 보안을 위해 반드시 서버 사이드에서도 유효성 검사를 수행해야 합니다.
- 일관성 : 애플리케이션 전체에서 일관된 유효성 검사 패턴과 에러 메시지를 사용하세요.
- 국제화 : 에러 메시지를 하드코딩하지 말고, 국제화(i18n) 라이브러리를 사용하여 다국어 지원을 고려하세요.
React에서 폼 유효성 검사를 구현할 때는 사용자 경험, 성능, 그리고 접근성을 모두 고려해야 합니다.
실시간 검사와 제출 시 검사를 적절히 조합하고, 명확하고 즉각적인 피드백을 제공함으로써 사용자 친화적인 폼을 만들 수 있습니다.
또한, 재사용 가능한 유효성 검사 로직을 만들어 코드의 중복을 줄이고 일관성을 유지하는 것이 중요합니다.