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의 조합 가능성을 활용하면 더 많은 패턴을 추상화할 수 있을 것 같다.