반응형

1. 필요 라이브러리 설치 방법
React18 + TypeScript + react-hook-form 기반 환경
프로젝트 생성 (Vite 기준)
npm create vite@latest my-form-app --template react-ts
cd my-form-app
또는 Yarn
yarn create vite my-form-app --template react-ts
cd my-form-app
react-hook-form 설치
npm install react-hook-form
또는
yarn add react-hook-form
2. 코드 리뷰
import { SubmitHandler } from 'react-hook-form';
/**
* @template T
* Search members of react-hook-form
*/
export type TSearchBaseProps<T> = {
defaultValues?: T;
onSubmit: SubmitHandler<T>;
onReset?: () => void;
};
코드 분석 결과
✔ 제네릭 기반 Form Props 인터페이스
TSearchBaseProps<T>는 Form 컴포넌트의 공통 기반 Props를 만들기 위한 TypeScript 제네릭 타입이다.
✔ SubmitHandler<T>
react-hook-form에서 제공하는 타입
→ submit 이벤트에서 입력 데이터 타입을 정확히 보장한다.
✔ defaultValues
Form의 초기 값 설정
선택적(optional)이라서 필요 없을 경우 생략 가능
✔ onSubmit
Form 제출 시 호출되는 필수 함수
✔ onReset
Reset 버튼 또는 리셋 액션 시 실행되는 선택적 함수
🔧 장점
항목설명
| 타입 안정성 | 모든 Form 데이터 타입이 명확히 추론됨 |
| 재사용성 증가 | 다양한 필터 Form 컴포넌트를 표준형으로 설계 가능 |
| 유지보수 쉬움 | 시스템 규모가 커질수록 큰 효과 |
| react-hook-form 구조와 완벽 호환 | TS 기반 RHF 최적화 |
목표
- 제네릭 기반 Form Props 설계 이해
- react-hook-form + TS에서의 타입 안전성 구현 방법
- Form 화면을 재사용 가능하게 만드는 방법 학습
왜 제네릭 Form 구조가 필요한가
문제점(기존 방식)
❌ Form마다 Props와 구조가 매번 다름
❌ submit 시 타입이 any로 처리됨
❌ UI 재사용 불가능
해결 방법
✔ TypeScript 제네릭을 이용한 Form 표준화
✔ 모든 Form은 동일한 공통 Props를 가지도록 설계
✔ 데이터 타입 안전성 확보
핵심 코드
export type TSearchBaseProps<T> = {
defaultValues?: T;
onSubmit: SubmitHandler<T>;
onReset?: () => void;
};
- <T>: Form 데이터 타입
- defaultValues?: T: 초기값
- SubmitHandler<T>: react-hook-form에서 제공하는 타입
- 재사용 가능한 구조를 통해 필터폼, 등록폼 등에 모두 대응 가능
예제 코드 설명
- Employee Filter Form 예제
- Generic 기반 Form Component
- Data 타입 정의
- submit/reset 이벤트 처리
1) 데이터 타입 정의
// types/TEmployeeFilter.ts
export type TEmployeeFilter = {
name: string;
department: string;
joinDate?: string;
};
2) 공통 Form Props 타입
// types/TFilterBaseProps.ts
import { SubmitHandler } from "react-hook-form";
export type TFilterBaseProps<T> = {
defaultValues?: T;
onSubmit: SubmitHandler<T>;
onReset?: () => void;
};
3) 제네릭 Form Component
// components/GenericFilterForm.tsx
import { useForm } from "react-hook-form";
import { TFilterBaseProps } from "../types/TFilterBaseProps";
export function GenericFilterForm<T>(props: TFilterBaseProps<T>) {
const { defaultValues, onSubmit, onReset } = props;
const { register, handleSubmit, reset } = useForm<T>({ defaultValues });
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register("name" as any)} placeholder="이름" />
<input {...register("department" as any)} placeholder="부서" />
<input {...register("joinDate" as any)} type="date" />
<button type="submit">검색</button>
<button
type="button"
onClick={() => {
reset();
onReset?.();
}}
>
초기화
</button>
</form>
);
}
4) 실제 페이지에서 사용
// pages/EmployeeSearchPage.tsx
import React from "react";
import { GenericFilterForm } from "../components/GenericFilterForm";
import { TEmployeeFilter } from "../types/TEmployeeFilter";
export default function EmployeeSearchPage() {
const defaultValues: TEmployeeFilter = {
name: "",
department: "",
joinDate: "",
};
const handleSubmit = (data: TEmployeeFilter) => {
console.log("검색 결과:", data);
};
const handleReset = () => {
console.log("검색창 초기화 완료");
};
return (
<div>
<h2>직원 검색</h2>
<GenericFilterForm<TEmployeeFilter>
defaultValues={defaultValues}
onSubmit={handleSubmit}
onReset={handleReset}
/>
</div>
);
}
A modern, clean, and professional cover image for a programming lecture titled "TypeScript Generic-Based Form Reusability Pattern: Advanced Form Design with React Hook Form". Include visual elements representing TypeScript (e.g., the TS logo or type annotations), React Hook Form (e.g., form components, hooks), and reusable form patterns (e.g., modular, interconnected form blocks or components). Use a tech-oriented color scheme, such as blues, purples, or dark themes with bright accents, to convey a high-level, advanced programming concept. Include abstract representations of generic types and dynamic forms. The style should be sleek, contemporary, and suitable for a developer audience.



react-helmet을 완전히 제거하고 react-helmet-async로 대체 (가장 추천)
npm uninstall react-helmet
npm install react-helmet-async
import { HelmetProvider, Helmet } from "react-helmet-async";
function App() {
return (
<HelmetProvider>
<Helmet>
<title>My App</title>
</Helmet>
<div>...</div>
</HelmetProvider>
);
}
반응형
'교육' 카테고리의 다른 글
| react-helmet의 기본 개념과 사용법 (0) | 2025.11.18 |
|---|---|
| 「React 18 + TypeScript + MobX 기반 구조에서 useStore 훅 설계와 스토어 계층 아키텍처 이해」 (0) | 2025.11.17 |
| #007 React useMemo : 성능 최적화의 정석 (0) | 2025.11.13 |
| #006 Context Provider (컨텍스트 프로바이더) (0) | 2025.11.13 |
| #005 React Context 교육자료: 장바구니 상태 관리 (0) | 2025.11.12 |