본문 바로가기

TypeScript

[TypeScript] TypeScript와 Zod를 활용한 효율적인 폼 관리: React Hook Form 도입기

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를 통해 스키마를 정의하고 이를 리졸버로 사용하니 폼 제출 시 자동으로 검사가 이루어집니다. 이 덕분에 코드의 가독성이 높아지고 유지보수성도 크게 향상되었습니다.

 

느낀 점

  1. 유효성 검사 통합: Zod를 사용하면 모든 유효성 검사를 중앙 집중식으로 관리할 수 있어, 필드별로 중복된 코드를 줄일 수 있었습니다. 오류 메시지를 스키마 내에서 정의하므로 일관성을 유지할 수 있었습니다.
  2. 타입 안전성: TypeScript와 함께 사용하면서 타입 안전성을 더욱 높일 수 있었습니다. Zod의 스키마를 통해 입력 데이터의 형태를 명확히 정의하고, 이로 인해 런타임 에러를 사전에 방지할 수 있었습니다.
  3. 개발 속도 향상: React Hook Form과 Zod의 조합 덕분에 폼을 구현하는 속도가 빨라졌습니다. 간단한 설정으로 복잡한 폼 기능을 손쉽게 구현할 수 있었고, 이는 프로젝트 전체의 개발 속도에도 긍정적인 영향을 미쳤습니다.
  4. 유지보수 용이성: 코드가 더욱 깔끔해지고 구조가 명확해지면서, 팀원들이 코드를 이해하고 수정하는 데 드는 시간도 줄어들었습니다. 이는 팀 협업의 효율성을 높이는 데 크게 기여했습니다.

결론적으로, React Hook Form과 Zod를 사용한 폼 관리는 기존에 비해 많은 장점을 가져다주었습니다. 앞으로도 이러한 도구들을 활용하여 더욱 효율적이고 안전한 애플리케이션을 개발해 나갈 계획입니다.

 

이 포스팅이 비슷한 고민을 하고 있는 분들에게 도움이 되길 바랍니다!