zod
zod는 타입스크립트를 우선하는 스키마 선언 / 검증 라이브러리입니다.
validation을 도와준다고도 생각할 수 있는데
문법은 간결하고 쉬우면서도 기능은 강력합니다.
공식 documentation에 따르면
스키마라는 용어는 모든 데이터 유형을 광범위하게 지칭하기 위해 사용하고 있다고하며
목표는 중복 형식 선언을 제거하기 위함이라고 합니다.
제로 종속성 / 8kb의 번들사이즈라는 것이 흥미롭네요
달레님의 포스트를 보며 제 나름대로 정리한 내용임을 미리 밝힙니다.
https://www.daleseo.com/zod-why-validation/
zod가 필요한 이유는 타입스크립트에 한계점이 존재하기 때문입니다.
예컨대 타입스크립트는 컴파일 시점에서의 타입에러만 잡아낼 수 있습니다.
즉 런타임에서는 타입스크립트가 아무런 힘을 쓰지 못하게됩니다.
또한 타입스크립트로는 부족한 부분이 있습니다.
예컨대 타입스크립트는 Number 자료형만 입력받도록 강제하는 것은 가능하지만
1부터 10까지의 숫자만 입력받도록 강제하는 것이나
정수 / 실수를 구분하는 것은 가능하지 않습니다.
외부에서 들어오는 데이터를 효과적으로 검증하기 위해서는
이렇듯 자료형을 제한하는 것 뿐만 아니라 다양한 제한이 필요합니다.
예컨대 이메일을 입력받고자 하는 경우 이메일의 양식에 맞게 입력을 받아야할 것입니다.
zod와 비슷한 역할을 하는 라이브러리로는
joi / yup / typia 등이 있으니 참고해보시면 좋을 것 같습니다.
https://github.com/XionWCFM/react-hook-form-example
제가 작성한 예제코드는 위 레포지토리에서 확인 가능합니다.
간단하게 사용해보기
npm i zod
yarn add zod
간단하게 설치할 수 있습니다.
import z from 'zod';
const schema = z.object({
name: z.string(),
age: z.number().min(10),
});
기본적인 사용방법은 다음과 같습니다.
zod에서 z를 불러옵니다.
z.object()를 통해 객체인 스키마를 정의할 수 있습니다.
인자로 객체를 넘겨주고 키값과 타입을 정의해줍니다.
기본적으로 string, number 등 typescript에서 지원해주는 대부분의 타입은 지원된다고 생각할 수 있습니다.
import { z } from "zod";
const User = z.object({
username: z.string(),
});
User.parse({ username: "Ludwig" });
// extract the inferred type
type User = z.infer<typeof User>;
// { username: string }
다음은 zod 공식문서에서 보여주는 예제입니다.
z.* 메서드의 반환값에는 .parse메서드가 들어가있음을 알 수 있습니다.
또한 z.infer<typeof 스키마>의 형태로 타입을 받아올 수 있습니다.
parse함수와 safeParse함수
User.parse({ username: "이은희" });
User.safeParse({username:"손흥민"})
z의 메서드들을 호출하여 반환된 값들은 parse메서드 , safeParse메서드를 가집니다.
이 두가지 메서드는 모두 인자로 전달받은 값이 정의된 스키마에 대응되는지 확인하고
대응되는 경우에는 인자로 전달받은 값을 그대로 리턴해줍니다.
둘의 가장 큰 차이점은 다음과 같습니다.
parse()메서드를 사용했는데 스키마에 대응되지 않는 타입이 인자로 들어간 경우에는
위 화면과 같이 ZodError를 throw합니다.
반면 safeParse()메서드를 사용하게되면
위와 같이
실패했을 경우에는 error:프로퍼티와 success:false를 가진 객체가 반환되고
성공했을 경우에는 data 프로퍼티와 success:true를 가진 객체가 반환됩니다.
널리쉬 메서드와 널에이블 메서드
위에서 본 예제를 그대로 다시 가져왔습니다.
z.string().nullable()
z.string().nullish()
두 비슷해보이는 메서드의 차이는
undefined를 허용하느냐 허용하지 않느냐입니다.
nullish | undefined도 true null도 true |
nullable | undefined는 false 오직 null만 true |
zod는 react-hook-form과 통합도 가능합니다.
npm i react-hook-form zod @hookform/resolvers
그렇게하기 위해서는 @hookform/resolvers가 필요합니다.
'use client';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import * as z from 'zod';
const schema = z.object({
name: z.string().min(1, { message: 'Required' }),
age: z.number().min(10),
});
const ZodComponent = () => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm({
resolver: zodResolver(schema),
});
return (
<form
onSubmit={handleSubmit((d) => console.log(d))}
className=" border border-slate-500 bg-slate-400"
>
<h2>ZodComponent</h2>
<input {...register('name')} />
<input type="number" {...register('age', { valueAsNumber: true })} />
<input type="submit" />
</form>
);
};
export default ZodComponent;
리액트 훅폼 깃허브에서 제공해주는 예제코드입니다.
@hookform/resolvers/zod 경로에서 zodResolver를 import해옵니다.
이 zodResolver가 리액트훅폼과 zod를 통합시키는 역할을 수행하게 됩니다.
zod를 이용하여 스키마를 정의한 뒤 useForm의 인자객체에
resolver키값으로 zodResolver(정의해둔스키마)의 호출값을 넘겨주면 끝입니다!
formState:{errors}에는 우리가 zod 스키마를 정의하는 곳에서
{message:""}에 넣어준 값이 들어가게됩니다.
age가 10이상이면서 name의 length가 1이상일때에만 submit이 활성화되고
조건이 만족되지 않은 경우에는 submit이 불가하게 됩니다.
더 자세한 정보는 공식문서를 보면서 감을 익혀나가시는 것을 추천드려요!
레퍼런스
https://github.com/react-hook-form/resolvers#zod
https://articles.wesionary.team/react-hook-form-schema-validation-using-zod-80d406e22cd8
'react' 카테고리의 다른 글
forwardRef를 이용해 ref를 다는데... 타입은 어떻게 함? (1) | 2023.06.19 |
---|---|
zod를 이용해 회원가입 폼을 만들어보기 (0) | 2023.06.18 |
msw를 이용해 데이터 모킹하고 Suspense와 함께 react-query로 가져오기 (3) | 2023.06.12 |
[react-query] react-query의 query key는... (0) | 2023.06.06 |
[react-query]@tanstack/react-query를 사용해보자 (1) | 2023.06.05 |