TypeScript를 사용하면서 폼 관리를 더욱 효율적으로 하기 위해 고민하던 중, Zod와 함께 React Hook Form을 사용하는 방법을 알게 되었습니다. 이번 포스팅에서는 두 라이브러리를 도입하면서 제 코드가 어떻게 변화했는지, 그리고 이 과정에서 느낀 점들을 정리해 보겠습니다.
1. React-Hook-Form과 Zod를 사용하지 않은 예시
import React, { useState } from 'react';
const ContactForm = () => {
const [formData, setFormData] = useState({
name: '',
email: '',
message: '',
});
const [errors, setErrors] = useState({});
const handleChange = (e) => {
setFormData({ ...formData, [e.target.name]: e.target.value });
};
const validate = () => {
const newErrors = {};
if (!formData.name) newErrors.name = '필수값입니다.';
if (!formData.email) newErrors.email = '필수값입니다.';
if (!formData.message) newErrors.message = '필수값입니다.';
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const handleSubmit = (e) => {
e.preventDefault();
if (validate()) {
// data 콘솔에 나타나게 해보기
console.log('Form submitted:', formData);
setFormData({ name: '', email: '', message: '' }); // 초기화
setErrors({});
}
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>Name:</label>
<input type="text" name="name" value={formData.name} onChange={handleChange} />
{errors.name && <span>{errors.name}</span>}
</div>
<div>
<label>Email:</label>
<input type="email" name="email" value={formData.email} onChange={handleChange} />
{errors.email && <span>{errors.email}</span>}
</div>
<div>
<label>Message:</label>
<textarea name="message" value={formData.message} onChange={handleChange}></textarea>
{errors.message && <span>{errors.message}</span>}
</div>
<button type="submit">Submit</button>
</form>
);
};
export default ContactForm;
2. React-Hook-Form과 Zod를 사용한 예시
import React from 'react';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import { zodResolver } from '@hookform/resolvers/zod';
const schema = z.object({
name: z.string().min(1, '필수값입니다.'),
email: z.string().email('이메일 형식에 맞지 않습니다.').min(1, '필수값입니다.'),
message: z.string().min(1, '필수값입니다.'),
});
const ContactForm = () => {
// useForm 훅을 사용하여 폼 상태 및 유효성 검사 관련 메서드를 가져옵니다.
const {
register,
handleSubmit,
formState: { errors } } = useForm({
resolver: zodResolver(schema), // Zod 스키마를 사용하여 유효성 검사를 설정합니다.
});
// 폼이 제출될 때 호출되는 함수입니다.
const onSubmit = (data) => {
console.log('Form submitted:', data); // 제출된 데이터를 콘솔에 출력합니다.
// 여기에서 데이터 처리 또는 폼 리셋 등의 추가 작업을 수행할 수 있습니다.
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label>Name:</label>
<input type="text" {...register('name')} />
{errors.name && <span>{errors.name.message}</span>}
</div>
<div>
<label>Email:</label>
<input type="email" {...register('email')} />
{errors.email && <span>{errors.email.message}</span>}
</div>
<div>
<label>Message:</label>
<textarea {...register('message')}></textarea>
{errors.message && <span>{errors.message.message}</span>}
</div>
<button type="submit">Submit</button>
</form>
);
};
export default ContactForm;
코드 변화
React Hook Form과 Zod를 통합함으로써, 폼 데이터의 유효성 검사를 더 간편하게 관리할 수 있게 되었습니다. 기존에는 각 입력 필드에서 수동으로 유효성 검사를 처리해야 했지만, Zod를 통해 스키마를 정의하고 이를 리졸버로 사용하니 폼 제출 시 자동으로 검사가 이루어집니다. 이 덕분에 코드의 가독성이 높아지고 유지보수성도 크게 향상되었습니다.
느낀 점
- 유효성 검사 통합: Zod를 사용하면 모든 유효성 검사를 중앙 집중식으로 관리할 수 있어, 필드별로 중복된 코드를 줄일 수 있었습니다. 오류 메시지를 스키마 내에서 정의하므로 일관성을 유지할 수 있었습니다.
- 타입 안전성: TypeScript와 함께 사용하면서 타입 안전성을 더욱 높일 수 있었습니다. Zod의 스키마를 통해 입력 데이터의 형태를 명확히 정의하고, 이로 인해 런타임 에러를 사전에 방지할 수 있었습니다.
- 개발 속도 향상: React Hook Form과 Zod의 조합 덕분에 폼을 구현하는 속도가 빨라졌습니다. 간단한 설정으로 복잡한 폼 기능을 손쉽게 구현할 수 있었고, 이는 프로젝트 전체의 개발 속도에도 긍정적인 영향을 미쳤습니다.
- 유지보수 용이성: 코드가 더욱 깔끔해지고 구조가 명확해지면서, 팀원들이 코드를 이해하고 수정하는 데 드는 시간도 줄어들었습니다. 이는 팀 협업의 효율성을 높이는 데 크게 기여했습니다.
결론적으로, React Hook Form과 Zod를 사용한 폼 관리는 기존에 비해 많은 장점을 가져다주었습니다. 앞으로도 이러한 도구들을 활용하여 더욱 효율적이고 안전한 애플리케이션을 개발해 나갈 계획입니다.
이 포스팅이 비슷한 고민을 하고 있는 분들에게 도움이 되길 바랍니다!
'TypeScript' 카테고리의 다른 글
[TypeScript] Props를 선언할 때 type과 interface 중에 어떤 것을 사용할까? (0) | 2024.12.03 |
---|---|
[우아한 타입 스크립트 with 리액트] 타입이란 (1) | 2024.08.26 |
[우아한 타입 스크립트 with 리액트] 타입스크립트의 등장 (0) | 2024.08.24 |
[우아한 타입 스크립트 with 리액트] 자바스크립트의 한계 (0) | 2024.08.23 |
TypeScript에 대해 얼마나 알고 있는지 (0) | 2024.07.11 |