React Hooks 도입 후 Custom Hook으로 폼 로직 분리하기

문제 상황

프로젝트 내 여러 폼 컴포넌트에서 동일한 패턴의 상태 관리 코드가 반복되고 있었다. 회원가입, 로그인, 프로필 수정 등 각 폼마다 useState로 입력값을 관리하고, 변경 핸들러와 유효성 검사를 구현하는 코드가 중복됐다.

React Hooks를 올해 초부터 도입했지만, 아직 Custom Hook을 적극 활용하지 못하고 있었다.

useForm 훅 구현

import { useState } from 'react';

function useForm(initialValues) {
  const [values, setValues] = useState(initialValues);
  const [errors, setErrors] = useState({});

  const handleChange = (e) => {
    const { name, value } = e.target;
    setValues(prev => ({
      ...prev,
      [name]: value
    }));
  };

  const handleSubmit = (callback) => (e) => {
    e.preventDefault();
    callback(values);
  };

  return {
    values,
    errors,
    handleChange,
    handleSubmit,
    setErrors
  };
}

적용 예시

function SignupForm() {
  const { values, handleChange, handleSubmit } = useForm({
    email: '',
    password: '',
    nickname: ''
  });

  const onSubmit = async (formValues) => {
    try {
      await api.signup(formValues);
    } catch (err) {
      console.error(err);
    }
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input
        name="email"
        value={values.email}
        onChange={handleChange}
      />
      <input
        name="password"
        type="password"
        value={values.password}
        onChange={handleChange}
      />
      <button type="submit">가입</button>
    </form>
  );
}

결과

5개의 폼 컴포넌트에 적용해 약 200줄의 중복 코드를 제거했다. 유효성 검사 로직도 나중에 훅 내부로 통합할 계획이다.

Custom Hook이 단순히 로직 재사용을 넘어, 컴포넌트를 더 선언적으로 만들어준다는 걸 체감했다. Hooks의 조합 가능성을 활용하면 더 많은 패턴을 추상화할 수 있을 것 같다.

React Hooks 도입 후 Custom Hook으로 폼 로직 분리하기