하루코딩 세싹이

[ReactJS] react-hook-form이란? useForm 완벽 정리 본문

개발 준비/ReactJS&TypeScript

[ReactJS] react-hook-form이란? useForm 완벽 정리

떼떼히 2025. 6. 13. 11:12
728x90
반응형

react-hook-form

react-hook-form은 React에서 폼을 간단하고 효율적으로 관리할 수 있게 도와주는 라이브러리로, 최소한의 리렌더링으로 빠른 성능을 제공하며, 입력값 등록(register), 검증(validate), 상태 추적(watch), 제출 처리(handleSubmit) 등을 쉽게 구현할 수 있다. 기존의 복잡한 폼 상태 관리 방식보다 코드량이 적고 직관적이며, 유효성 검사 라이브러리와도 쉽게 연동할 수 있어 유지보수가 편리한 것이 특징이다.

 

useForm

폼 전반을 관리하는 핵심 훅
기능: 등록, 제출, 초기값, 에러 상태 관리 등

const { register, handleSubmit, formState: { errors } } = useForm();

 

 

useFormContext

FormProvider 하위에서 하위 컴포넌트들이 form 상태를 공유할 수 있도록 함
사용 시점: 깊은 컴포넌트에서 register, errors 등에 접근해야 할 때

const { register } = useFormContext();

 

 

useFieldArray

배열 형태의 입력값을 다룰 때 사용
예시: 체크리스트, 항목 추가/삭제 등

const { fields, append, remove } = useFieldArray({ name: "items", control });

 

 

useWatch

특정 필드의 값을 실시간으로 "감시"
사용 예시: 값에 따라 다른 UI를 보여줄 때

const watchValue = useWatch({ name: "email" });

 

 

Controller

react-select 같은 커스텀 컴포넌트를 react-hook-form과 연결할 때 사용

<Controller
  name="customSelect"
  control={control}
  render={({ field }) => <CustomComponent {...field} />}
/>

 

 

FormProvider

여러 컴포넌트에서 같은 form 상태 공유하고 싶을 때

<FormProvider {...methods}>
  <YourFormComponent />
</FormProvider>

 

 

useFormState

특정 필드들의 에러, 상태만 별도로 관리하고 싶을 때

const { isDirty, errors } = useFormState({ control });

 

 


 

 

useForm 이해하기

useForm은 React에서 폼 상태를 간단하고 효율적으로 관리할 수 있게 해주는 훅이다. 이 훅을 사용하면 복잡한 폼 로직 없이도 입력값 관리, 유효성 검사, 에러 메시지 출력 등을 쉽게 구현할 수 있다. 특히 register, handleSubmit, formState 등 다양한 유틸 함수를 통해 코드가 깔끔해지고 유지보수도 편리해진다.

또한 useForm은 성능 면에서도 유리하다. 입력값이 변경될 때 불필요한 리렌더링을 최소화하고, 빠르고 가벼운 동작을 제공한다. 기본적인 유효성 검사는 물론, yup이나 zod와 같은 라이브러리를 이용해 스키마 기반 검증도 쉽게 연동할 수 있으며, TypeScript와의 궁합도 좋아 타입 안정성 있는 폼을 만들 수 있다. 이러한 장점 덕분에 React 프로젝트에서 자주 사용되는 폼 관리 도구이다.

import { useForm } from 'react-hook-form';

function MyForm() {
  const { register, handleSubmit, formState: { errors } } = useForm();

  const onSubmit = (data) => {
    console.log(data); // 사용자가 입력한 값
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register("username", { required: true })} />
      {errors.username && <span>이름은 필수입니다</span>}

      <input type="submit" value="제출" />
    </form>
  );
}

 

 

주요 기능 요약

기능 설명
register() input 요소를 useForm과 연결해줌
handleSubmit() 폼 제출 시 유효성 검사 후 실행할 함수
formState.errors 유효성 검사 실패 시 에러 정보
reset() 입력값 초기화
setValue() 특정 필드 값 설정
watch() 실시간으로 입력값 감지

 

 

useForm 사용방법

터미널에 입력하여 설치하기

npm install react-hook-form


사용하기
이메일과 비밀번호 받기 예제

const { register, handleSubmit, formState: { errors } } = useForm();

<form onSubmit={handleSubmit(onSubmit)}>
  <input {...register("email", { required: "이메일은 필수입니다" })} />
  {errors.email && <p>{errors.email.message}</p>}

  <input type="password" {...register("password", { required: true, minLength: 6 })} />
  {errors.password && <p>비밀번호는 6자 이상</p>}

  <input type="submit" />
</form>

 

 

 

유효성 검사 포함

import React from 'react';
import { useForm } from 'react-hook-form';

export default function ValidatedForm() {
  const { register, handleSubmit, formState: { errors } } = useForm();

  const onSubmit = (data) => {
    alert(`안녕하세요, ${data.name}님!`);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <div>
        <label>이름</label>
        <input {...register("name", { required: "이름은 필수입니다" })} />
        {errors.name && <p style={{ color: 'red' }}>{errors.name.message}</p>}
      </div>

      <div>
        <label>이메일</label>
        <input {...register("email", {
          required: "이메일은 필수입니다",
          pattern: {
            value: /^\S+@\S+$/i,
            message: "이메일 형식이 아닙니다"
          }
        })} />
        {errors.email && <p style={{ color: 'red' }}>{errors.email.message}</p>}
      </div>

      <button type="submit">제출</button>
    </form>
  );
}



기본값 설정 & 폼 초기화 (reset)

import React from 'react';
import { useForm } from 'react-hook-form';

export default function FormWithDefault() {
  const { register, handleSubmit, reset } = useForm({
    defaultValues: {
      name: '세희',
      email: 'example@example.com'
    }
  });

  const onSubmit = (data) => {
    console.log('제출된 값:', data);
    reset(); // 폼 초기화
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register('name')} />
      <input {...register('email')} />
      <button type="submit">제출</button>
      <button type="button" onClick={() => reset()}>초기화</button>
    </form>
  );
}

 

 

 

useForm을 대체할 수 있는 다른 라이브러리들

Formik
useFormik() 훅을 사용하거나 <Formik> 컴포넌트를 사용할 수 있다.react-hook-form보다 다소 무겁지만 직관적인 구조를 가지고 있다.

const formik = useFormik({
  initialValues: { email: '' },
  onSubmit: values => console.log(values),
});

 

 

React Final Form
Redux 창시자인 Dan Abramov가 추천하는 가벼운 라이브러리이다. 
상태 변경을 최소화해서 성능이 좋다는 장점이 있다.

import { Form, Field } from 'react-final-form';

<Form
  onSubmit={onSubmit}
  render={({ handleSubmit }) => (
    <form onSubmit={handleSubmit}>
      <Field name="email" component="input" />
    </form>
  )}
/>

 

 

Zod + Custom Hook (자체 구현)
useState나 useReducer로 직접 form 상태를 관리하면서 zod로 validation을 할 수도 있다.

const [email, setEmail] = useState('');
const schema = z.object({ email: z.string().email() });
반응형