ykss.netlify.app
TanStack Form vs React Hook Form
두 라이브러리의 핵심 차이는 "제어(controlled) 모델 vs 비제어(uncontrolled) ref 모델". TanStack Form 은 타입 안전성과 합성, React Hook Form 은 리렌더 최소화와 가벼움.
핵심 요약
두 라이브러리 비교 표:
| 차원 | React Hook Form | TanStack Form |
|---|---|---|
| 모델 | 비제어(ref + register) | 제어(value + onChange) |
| 리렌더 | 최소화(필드별 isolation) | 더 자주(전형적 React state) |
| 타입 추론 | 보통 (zod resolver 와 결합 시 강함) | end-to-end 타입 안전 |
| 합성 | useFormContext + custom hooks | form.Field / withForm 으로 강력 |
| 프레임워크 | React 전용 | React/Vue/Solid/Lit/Svelte 공통 코어 |
| 번들 | 매우 작음 | 더 큼(코어 + 어댑터) |
| 학습 곡선 | 낮음 | 중간 |
핵심 코드 비교:
// React Hook Form
const { register, handleSubmit } = useForm<FormValues>();
<input {...register('username', { required: true })} />
// TanStack Form
const form = useForm({ defaultValues: { username: '' } });
<form.Field name="username" validators={{ onChange: ({ value }) => ... }}>
{(field) => <input value={field.state.value} onChange={(e) => field.handleChange(e.target.value)} />}
</form.Field>
zod 와 결합 시 둘 다 우수하지만 TanStack Form 은 타입이 필드 단위까지 자동 좁혀지는 반면, React Hook Form 은 resolver 경유 추론이 필요.
폼 라이브러리 비교의 근본 축은 "폼 상태를 어디에 두느냐" 다.
- React Hook Form: DOM 의 input 에 ref 만 등록 — 폼 상태는 비제어 로, 리렌더 최소.
- TanStack Form: 모든 필드를 React state 로 관리 — 제어, 합성 가능, 타입 안전.
둘 다 동일 기능(검증, async, 합성)을 제공하지만 렌더링 모델/타입 추론/번들 크기/리액트 네이티브 호환성 에서 의도가 정반대 가까이 갈린다.
프론트엔드 면접에서 "폼 라이브러리 어떻게 쓰세요?" 는 단순 도구 질문이 아니라 제어/비제어 차이, 리렌더 최소화, 타입 추론, zod/yup 통합 같은 더 큰 주제로 자연스럽게 확장된다. 이 글은 그 비교를 한 페이지에 정리해주는 잣대 역할이다.
선택 기준 요약:
- 번들 크기/리렌더 비용이 우선 → React Hook Form
- 타입 안전 + 다른 프레임워크 호환 + 합성 → TanStack Form
- React Native 동일 코드 → TanStack Form (제어이므로 그대로 동작)
학습 포인트
면접 답변으로 연결할 학습 포인트입니다.
비제어 vs 제어 — 리렌더 비용의 차이
React Hook Form 은 input 에 ref 만 걸어 컴포넌트 리렌더 없이 값을 추적한다. 결과적으로 100개 짜리 폼에서 한 필드 입력이 다른 필드를 리렌더하지 않는다. TanStack Form 은 React state 모델이라 기본적으로 더 자주 렌더링되지만, subscribe/Field 단위 격리로 보완 가능하다.
// React Hook Form: ref 등록
<input {...register('email')} /> // 리렌더 거의 없음
// TanStack Form: state 갱신
field.handleChange(value) // 해당 Field 만 리렌더
"제어 컴포넌트 = 안티패턴" 이라는 단정. 폼 규모/검증 복잡도/타입 안정성 요구가 더 크면 제어 모델이 더 좋을 수 있다.
타입 안전성 — 어디까지 추론되는가
TanStack Form 은 useForm({ defaultValues }) 로부터 모든 필드 이름·타입을 자동 좁힘. 오타를 컴파일 타임에 잡고, 검증 콜백의 value 까지 정확히 추론된다.
const form = useForm({ defaultValues: { age: 0 } });
// form.Field name="age" 안에서 value 는 자동으로 number
React Hook Form 은 useForm<FormValues>() 처럼 수동 제네릭 이 필요하고, dot path('user.address.city') 추론은 zod resolver 와 결합할 때 가장 강력하다. 즉 Zod 와의 통합 정도 에서 격차를 메운다.
"두 라이브러리의 타입 안전성이 같다" 라고 보는 것. defaults 기반 추론 만 쓰면 TanStack 이 명백히 우세, schema 기반 으로 가면 격차가 좁혀진다.
프레임워크 비종속성과 합성
TanStack Form 은 코어와 어댑터를 분리해 React/Vue/Solid/Svelte 에서 동일 API 로 쓴다. 또한 withForm / form.Field 로 재사용 가능한 폼 블록 을 합성한다.
// 재사용 가능한 ProfileFields
const ProfileFields = withForm({
defaultValues: { name: '', email: '' },
render: ({ form }) => (
<>
<form.AppField name="name">{(f) => <Input field={f} />}</form.AppField>
<form.AppField name="email">{(f) => <Input field={f} />}</form.AppField>
</>
),
});
React Hook Form 은 React 전용이지만 useFormContext + custom hook 으로 충분히 합성된다. "코드 일관성을 모노레포 전체에서" 같은 요구가 있으면 TanStack 이 유리.
프레임워크 비종속성을 "현재 안 쓰니 무가치" 로 보는 것. 디자인 시스템을 멀티 플랫폼으로 늘릴 때 큰 차이가 된다.
읽는 순서
- 1이론
제어/비제어 컴포넌트 차이, RHF 의 register/ref 모델, TanStack Form 의 form.Field/withForm 모델을 정리한다. 두 모델이 만드는 리렌더 그래프 를 그려본다.
- 2구현
회원가입 폼(이름·이메일·비밀번호·약관 동의)을 동일 검증으로 두 라이브러리에 모두 구현. React DevTools Profiler 로 입력 시 리렌더 수와 코드 라인 수를 비교.
- 3실무
현재 프로젝트의 가장 큰 폼(필드 ≥ 10) 을 골라, RHF/TanStack 으로 마이그레이션 시 비용/이득을 표로 정리한다. 마이그레이션 ROI 가 양수면 작은 PR 로 시도.
- 4설명
동료에게 "두 라이브러리의 핵심 모델 차이" 를 5분 안에 설명한다. 제어 vs 비제어 라는 한 단어로 시작해 트레이드오프로 확장.
면접 연결 질문
[감점 답변] "인기 있어서 RHF". [좋은 답변] 결정 트리: (1) 번들/리렌더 최소화 > 타입 자동 추론 이면 RHF, (2) 타입 안전 + 모노레포/멀티 프레임워크 + 합성 이면 TanStack. 추가로 (3) zod 사용 강제면 두 쪽 다 가능하지만 RHF 가 더 가볍고, (4) RN 호환성이 중요하면 TanStack(제어)이 더 안전. 회사 표준·기존 코드 베이스도 함께 본다.
[감점 답변] "ref 라서 빠름". [좋은 답변] ref 로 DOM 값을 직접 읽기 때문에 React state 갱신이 없어 리렌더가 일어나지 않음. 단점: (1) 다른 필드와 연동되는 UI(가격 합계, 미리보기) 를 만들 때 별도 watch/구독 로직이 필요, (2) React Native 처럼 ref 로 DOM 직접 접근이 불가능한 환경에서 동작이 어려움, (3) 테스트 시 controlled 컴포넌트보다 값 주입/검증 이 까다로울 수 있음.
[감점 답변] "둘 다 zod 를 쓰니 비슷". [좋은 답변] (1) TanStack Form: defaultValues 만으로도 추론이 강하고, zod 를 추가로 붙이면 검증 메시지까지 타입화. (2) React Hook Form: zodResolver(schema) 를 거치면 register 경로에 대한 타입 가드 가 schema 에서 옴. 다만 복잡 dot path 의 추론은 zod 의 infer 한계에 좌우됨. 결론: schema-first 방식이면 두 라이브러리 격차가 좁혀지지만, 추론의 "기본값" 만으로 보면 TanStack 이 더 풍부.
자기 점검
"렌더 횟수 차이가 항상 RHF 의 우위" 라는 절대화. 실제로는 TanStack 도 Field 단위 구독으로 격차를 좁힐 수 있다.
"새 게 더 좋다" 식 주장. 학습 곡선 비용을 인정하면서 어디서 회수되는가 를 구체 사례로 들어야 한다.