현재 진행 중인 프로젝트에서 로그인 기능이 필요하여 로그인 및 회원가입에 대한 폼을 제작해야 했다. 다음은 기존에 입력 폼을 만들던 방식의 예제 코드이다.
function MyForm(){
const [email,setEmail] = useState<string>('');
const handleEmail = (event) => {
setEmail(event.target.value);
};
return
(
<input
type="email"
placeholder="이메일을 입력하세요"
value={email}
onChange={handleEmail}/>
)
}
입력 창에 값이 입력될 때마다 값을 추적하고 setEmail
함수를 호출하여 email
값을 업데이트한다. 문자 1개를 입력할 때마다 setEmail
함수가 실행되는 것이다.
-> 사용자의 입력값이 실시간으로 동기화되는 제어 컴포넌트
로써 동작한다.
React
에서는 state
값이 변경될 때마다 페이지를 다시 렌더링한다.
이러한 이유로 위의 예제 코드의 방식대로 입력을 받게 되면 매우 많은 리렌더링이 발생하게 되어 불필요한 렌더링을 요구하는 코드이다.
불필요한 렌더링은 성능저하를 초래하는 원인이 될 수 있기에 불필요한 렌더링을 없애야 한다고 생각했다.
React-Hook-Form
라이브러리를 사용하여 비제어 컴포넌트
로써 불필요한 렌더링을 제거할 수 있고 상황에 맞게
제어 컴포넌트
도 사용할 수 있어 비제어 컴포넌트
와 제어 컴포넌트
의 장점을 모두 챙길 수 있다.
- 제어 컴포넌트 - 실시간으로 입력값 동기화 -> 입력값에 대한 실시간 피드백 가능
- 비제어 컴포넌트 - 실시간으로 입력값이 동기화되지 않음 -> 불필요한 렌더링 제거
회원가입 폼을 만들기 위해서 특정 규칙에 맞는 입력 값인지 검사를 해야 한다.
이런 유효성 검사에 관한 내용을 폼 내부에 작성하게 되면 코드의 가독성이 떨어진다.
zod
를 사용하면 폼과 유효성 검사를 위한 코드에 관한 내용을 분리하여 작성할 수 있다.
npm install react-hook-form zod @hookform/resolvers // npm
yarn add react-hook-form zod @hookform/resolvers // yarn
const signUpFormSchema = z
.object({
// 이메일 형식 지정
email: z.string().email({ message: '이메일 형식이 아닙니다.' }),
password: z // 비밀번호 형식 지정 (문자와 숫자가 혼합된 8~20자리)
.string()
.regex(
/^(?=.*[a-zA-Z])(?=.*[0-9]).{8,20}$/,
'문자와 숫자가 혼합된 8~20자리의 비밀번호를 입력해주세요.'
),
confirmPassword: z.string(),
nickname: z.string(),
name: z.string(),
})
// 비밀번호와 비밀번호 확인이 일치하는지 확인
.refine((data) => data.password === data.confirmPassword, {
path: ['confirmPassword'],
message: '비밀번호가 일치하지 않습니다.',
});
회원 가입을 하기 위해서 입력받을 각 값의 규칙과 해당 규칙에 맞지 않을 때 출력할 메시지를 정의한다.
email
: 이메일 형식password
: 문자와 숫자가 최소 1개씩 혼합된 8~20자리confirmPassword
: password
의 값과 같아야 함nickname
, name
: 문자열// useForm을 사용하여 회원가입 폼의 상태 관리
const form = useForm({
resolver: zodResolver(signUpFormSchema),
defaultValues,
mode: 'onSubmit',
});
const {
register,
formState: { errors },
} = form;
resolver
: signUpFormSchema
를 전달하면 내가 작성한 규칙대로 form
에서 유효성 검사를 한다.
defaultValues
: 초깃값을 설정한다.
mode
: form
의 유효성 검사를 언제 할지 설정한다.
React-Hook-Form 라이브러리의 useForm 훅을 사용하여 mode를 onSubmit 으로 설정해줌으로써
비제어 컴포넌트
가 되어 불필요한 렌더링을 제거한 것이다.
만약, mode를 onChange로 설정한다면 입력값에 실시간으로 피드백이 가능한제어 컴포넌트
로써 동작할 것이다.
register
: 입력 필드를 React Hook Form에 등록하여 제어하고, 유효성을 검사한다.
formState
: 입력 필드의 상태를 return
한다.
<FormProvider {...form}>
<TextField
{...register('email')}
{errors.email ? errors.email.message : '사용가능한 이메일입니다.'}
/>
</FormProvider>
{...register('email')}
: 입력 필드를 등록하고 스키마에서 email
에 설정한 규칙을 기반으로 유효성 검사를 한다.
{errors.email ? errors.email.message : '사용가능한 이메일입니다.'}
: 규칙에 맞지 않는 입력 값이라면 스키마에서 설정했던 메시지가 출력된다.
zod를 사용하여 유효성 검사에 대한 로직을 분리해서 작성하여 가독성 좋은 입력 필드를 구현했다.
React-Hook-Form
을 사용하여 폼의 상태를 관리하여 불필요한 렌더링을 방지함으로써 성능을 개선하였고,
zod
를 사용하여 유효성 검사를 함으로써 코드의 가독성을 향상시켰다.
좋은 글 감사합니다!