안녕하세요 웹 프론트엔드 개발자 설탕시럽입니다.
프로젝트 내 로그인 폼을 구현하는 과정에서 react-hook-form과 yup라이브러리를 사용한 방식을 공유하려고 합니다.
react-hook-form과 yup을 도입하게 된 계기
기존의 react에서 <form>을 통해 내용을 받을 때는 불편한 점이 있었습니다. 입력값을 처리하는 과정에서 onChange와 같은 함수와 react의 상태로 처리하게 되면서 불필요한 렌더링이 발생하는 문제가 있었습니다. 그 외에도 onSubmit함수와 유효성 처리, 에러 처리 등 필요한 기능만큼이나 함수와 상태가 늘어났고 react-hook-form을 도입하기 전까지는 매우 비효율적으로 처리될 수 밖에 없었습니다.
react-hook-form은 이전에도 몇번 도입시킨 적은 있으나, 이번 기회에 yup 라이브러리까지 결합하니 에러처리 측면에서 그 효율성이 정말 뛰어났습니다. react-hook-form과 yup을 도입하게 된 이유이자 얻게되는 장점에 대해 우선 소개해 드리겠습니다.
1. 불필요한 렌더링 줄이기
react-hook-form은 비제어 컴포넌트 방식으로 불필요한 렌더링 없이 input값을 관리할 수 있습니다. 기존의 방식에 비해 더 효율적이고 빠른 속도를 낼 수 있었습니다.
2. 편리한 에러 관리
react-hook-form을 이용하면 error처리 과정에서 별도의 코드 작성없이 손쉽게 처리할 수 있습니다. yup 라이브러리를 적용하면 유효성검사 뿐 만아니라 그 상황에 맞는 에러 메시지까지 효율적으로 관리할 수 있습니다. 기존의 리액트에서는 일일이 그 입력값에 따른 조건을 작성하거나, react-hook-form만 쓰게 되는 경우 세세한 에러메세지 설정을 따로 해줘야 하지만, yup라이브러리를 통해서 더 효율적으로 관리할 수 있었습니다.
3. 코드 단순화
앞에서도 말했지만 기존의 방식에는 상당히 많은 상태와 함수를 정의 해야하며 코드를 깔끔하게 적는다고 해도 코드가 길어지는 효과가 있습니다. 라이브러리를 도입하게 되면서 코드의 상당수 부분이 줄어들고 앞으로 유지보수 측면에서도 효과적일 것이라고 생각했습니다.
라이브러리 적용하기
설치 및 호출
import { useForm } from 'react-hook-form';
import * as Yup from 'yup';
우선 react-hook-form의 useForm을 호출부터 해보겠습니다.
const {register, handleSubmit, formState: {errors}} = useForm<FormData>({
resolver: yupResolver(schema)
});
FormData
const schema = Yup.object({
username: Yup.string().email().required(),
password: Yup.string().matches().required(),
});
type FormData = Yup.InferType<typeof schema>;
Yup 라이브러리는 스키마 유효성 검증에 목적을 가지고 있습니다. 기존의 방식데로 들어오는 데이터에 대한 유효성검증을 하면 일일이 조건문을 통해 분석하겠지만, Yup 라이브러리를 사용해서 좀더 효율적으로 처리할 수 있습니다.
Yup에 다양한 내장 함수가 있겠지만, 위 예제의 경우 문자열인지 검사해 주는 string(), email인지 혹은 정규식으로 커스텀된 규칙을 사용하는 email()과 matches() 그리고 필수로 들어가야하는 required()로 검증할 수 있다.
또한, 함수 argument로 문자열을 넣으면, 해당 조건에 부합하지 못할 경우 문자열을 에러메시지로 반환시킬 수 있습니다. matches()는 정규식을 삽입하고 두번째 argument로 입력하면 됩니다.
register
<input {...register('username')} />
register는 다음 코드와 같이 사용합니다. 원하는 input태그에 삽입하면 해당 이름으로 그 값을 불러오고 Yup 라이브러리를 통한 유효성 검증이 가능해집니다. 기존의 방법처럼 상태나 별도로 정의된 것도 아닌 input값을 불러오는 방법은 handleSubmit에서 확인할 수 있습니다.
handleSubmit
const onSubmit:SubmitHandler<FieldValues> = ({username, password}) => {
console.log(username);
console.log(password);
}
<form onSubmit={handleSubmit(onSubmit)}>
input값의 검증은 Yup에서, 값은 useForm에서 관리해 주기 때문에 해당 데이터를 사용하는 경우는 submit때가 거의 대부분일 것입니다. 따라서 handleSubmit에서 arguments로 그 값들을 전달해 줍니다.
errors
<p style={{color:'red'}}>{errors.password?.message}</p>
가장 효율적이라고 생각한 error 처리 방식입니다. Yup 라이브러리를 더해, 특정 조건에 부합하지 않으면 그에 맞는 에러메세지를 return 할 수 있게 설정할 수 있으며, 위 코드로 불러올 수 있습니다. 위와 같은 방법을 통해 별도의 코드 없이 에러코드를 자동으로 생성과 관리가 가능해집니다.
결론
react-hook-form과 Yup에 대해 자세한 기능을 설명하기 보다는 LoginForm을 만들며 사용했던 기능들 위주로 설명해 보았습니다. 실제로 기존의 useState와 onChange, onSubmit 함수를 정의하고 그 외 유효성검증, 에러처리 등의 길었던 코드를 더욱 가독성 좋고 효율적인 코드로 처리할 수 있어서 매우 유용하게 사용할 수 있었습니다.
아래에 Login 처리한 전체 코드를 남기며 해당 포스트를 보시는 분들이 조금이라도 도움이 됬으면 합니다.
import {useForm} from 'react-hook-form';
import { FieldValues, SubmitHandler } from 'react-hook-form/dist/types';
import { yupResolver } from '@hookform/resolvers/yup';
import * as Yup from 'yup';
const schema = Yup.object({
username: Yup.string().email('email 형식을 입력해주세요').required('이메일(아이디)를 입력해 주세요'),
password: Yup.string().matches(/^(?=.*[A-Za-z])(?=.*\d)(?=.*[@!%*#?&])[A-Za-z\d@!%*#?&]{8,}$/,'8글자 이상 염문자, 숫자, 특수문자를 조합해서 입력하세요').required('비밀번호를 입력해 주세요'),
});
type FormData = Yup.InferType<typeof schema>;
export default function Home() {
const {register, handleSubmit, formState: {errors}} = useForm<FormData>({
resolver: yupResolver(schema)
});
const onSubmit:SubmitHandler<FieldValues> = ({username, password}) => {
axios.post(`http://${window.location.host}/api/auth/login`, {username, password})
.then(onLoginSuccess)
.catch(onError);
}
return (
<div className="mainContainer">
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('username')} placeholder='Email' />
{errors.username && <p style={{color:'red'}}>{errors.username?.message}</p>}
<input {...register('password')} type="password" placeholder='Password' />
<p style={{color:'red'}}>{errors.password?.message}</p>
<input type="submit" value={'Log in'}/>
</form>
</div>
);
}
'React' 카테고리의 다른 글
useState 딥다이브 (0) | 2023.06.04 |
---|---|
JSX (0) | 2023.05.17 |
React의 특징과 장점, 적용 예제 까지! (0) | 2023.05.16 |
Axios Custom Hook TypeScript 환경으로 만들기 (0) | 2023.05.08 |
react에서 websocket 통신하기 (0) | 2023.01.29 |