// Zod
- 타입스크립트의 타입 안정성을 향상시켜주는TypeScript-first 스키마 선언 및 검증 라이브러리
- 공식 문서: https://zod.dev/
▪ 설치
npm install zod
▪ 스키마 정의 및 검증
import { z } from 'zod';
const 스키마명 = z.자료형({
데이터명: z.자료형().검증메소드(),
});
const 스키마명 = z.자료형().검증메소드();
스키마명.parse(검증할데이터);
스키마에 위반되는 입력이 들어오면 런타임 에러가 발생한다.
'use server';
import { z } from 'zod';
const usernameSchema = z.string().min(5).max(10);
export async function createAccount(prevState: any, formData: FormData) {
const data = {
username: formData.get('username'),
email: formData.get('email'),
password: formData.get('password'),
confirm_password: formData.get('confirm_password'),
};
usernameSchema.parse(data.username);
}
'use server';
import { z } from 'zod';
const formSchema = z.object({
username: z.string().min(3).max(10),
email: z.string().email(),
password: z.string().min(10),
confirm_password: z.string().min(10),
});
export async function createAccount(prevState: any, formData: FormData) {
const data = {
username: formData.get('username'),
email: formData.get('email'),
password: formData.get('password'),
confirm_password: formData.get('confirm_password'),
};
formSchema.parse(data);
}
▪ safeParse
safeParse를 사용하여 검증하면 에러를 throw 하지 않는다.
데이터가 유효한 경우 success의 값이 true, 유효하지 않은 경우 false이다.
또한 유효하지 않은 경우에는 에러 정보(error)도 함께 반환한다.
'use server';
import { z } from 'zod';
const formSchema = z.object({
username: z.string().min(3).max(10),
email: z.string().email(),
password: z.string().min(10),
confirm_password: z.string().min(10),
});
export async function createAccount(prevState: any, formData: FormData) {
const data = {
username: formData.get('username'),
email: formData.get('email'),
password: formData.get('password'),
confirm_password: formData.get('confirm_password'),
};
const result = formSchema.safeParse(data);
if (!result.success) {
return result.error.flatten();
}
}
'use client';
import FormInput from '@/components/form-input';
import FormButton from '@/components/form-btn';
import SocialLogin from '@/components/social-login';
import { useFormState } from 'react-dom';
import { createAccount } from '@/app/create-account/actions';
function CreateAccount() {
const [state, action] = useFormState(createAccount, null);
return (
<div className="flex flex-col gap-10 py-8 px-6">
<div className="flex flex-col gap-2">
<h1 className="font-custom-bold">회원가입</h1>
<h2>Fill in the form below to join!</h2>
</div>
<form action={action} className="flex flex-col gap-3">
<FormInput
name="username"
type="text"
placeholder="Username"
required
errors={state?.fieldErrors.username}
/>
<FormInput
name="email"
type="email"
placeholder="Email"
required
errors={state?.fieldErrors.email}
/>
<FormInput
name="password"
type="password"
placeholder="Password"
required
errors={state?.fieldErrors.password}
/>
<FormInput
name="confirm_password"
type="password"
placeholder="Confirm Password"
required
errors={state?.fieldErrors.confirm_password}
/>
<FormButton text="Create account" />
</form>
<SocialLogin />
</div>
);
}
export default CreateAccount;
// 메시지 커스텀
- 자료형이 잘못되었을 때
const 스키마명 = z.object({
필드명: z
.string({
invalid_type_error: '메시지',
})
});
- 필수값을 입력하지 않았을 때
const 스키마명 = z.object({
필드명: z
.string({
required_error: '메시지',
})
});
- 길이 조건을 벗어났을 때
const 스키마명 = z.object({
필드명: z
.min(길이, '메시지')
});
// refine
- 사용자 정의 검증 메소드
const 스키마명 = z.object({
필드명: z
.refine(조건(true || false 반환), '메시지')
});
const formSchema = z.object({
username: z
.string({
invalid_type_error: 'Username must be a string!',
required_error: 'Write down your username',
})
.min(3, 'Username is too short.')
.max(10)
.refine((username) => !username.includes('potato'), 'No potatoes allowed'),
email: z.string().email(),
password: z.string().min(10),
confirm_password: z.string().min(10),
});
※ form 전체에 해당하는 refine을 정의한 후 특정 부분에 error를 보낼 수도 있다.
const 스키마명 = z.object({
필드명: z
...
})
.refine(조건 || 함수, {
message: '메시지'
path: ['필드name']
});
// regex
정규표현식을 사용하여 입력을 검증할 수도 있다.
const 스키마명 = z.object({
필드명: z
.regex(정규표현식, '메시지')
});
'use server';
import { z } from 'zod';
const passwordRegex = new RegExp(
/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).+$/,
);
const formSchema = z
.object({
password: z
.string()
.min(10)
.regex(
passwordRegex,
'A password must have lowercase, UPPERCASE, a number and special characters. ',
),
confirm_password: z.string().min(10),
})
export async function createAccount(prevState: any, formData: FormData) {
const data = {
password: formData.get('password'),
confirm_password: formData.get('confirm_password'),
};
const result = formSchema.safeParse(data);
if (!result.success) {
return result.error.flatten();
}
}
// coerce
- 강제로 형변환을 시켜준다.
- formData로 받는 데이터 타입을 모두 string인데, string이 아닌 다른 자료형(원래 자료형)으로 검증하기 위해 사용한다.
const 스키마명 = z.coerce.원하는자료형().검증메소드()
const tokenSchema = z.coerce.number().min(100000).max(999999);
'클라이언트 > Next.js' 카테고리의 다른 글
[Next.js] 이미지 컴포넌트 사용하기 (0) | 2024.06.15 |
---|---|
[Next.js] Prisma 사용하여 데이터베이스 연동하기 (0) | 2024.06.10 |
[Next.js] 렌더링 과정 및 개념 (0) | 2024.05.07 |
[Next.js] 배포(Deploying) (0) | 2024.03.04 |
[Next.js] Metadata title 추가하기 (0) | 2024.03.03 |