HJS

Zod

Zod는 TypeScript 친화적인 스키마 기반 데이터 검증 라이브러리입니다. React에서는 주로 React Hook Form과 함께 폼 데이터를 검증할 때 많이 사용됩니다.

💡 주요 특징

1️⃣ 설치 및 기본 사용법

🔹 설치하기

yarn add zod
# 또는
npm install zod

🔹 기본적인 스키마 정의 및 검증

import { z } from "zod";

const userSchema = z.object({
  firstName: z.string().min(1, 'First name is required'),
  lastName: z.string().min(1, 'Last name is required')
});

try {
  userSchema.parse({ firstName: 'John', lastName: '' });
} catch (e) {
  console.log(error);
}   

✔️ parse를 사용하면 검증이 실패할 경우 오류를 발생합니다.
✔️ safeParse를 사용하면 오류 대신 결과를 객체로 반환합니다.




2️⃣ React Hook Form과 Zod 통합하기

Zod는 React Hook Form과 함께 사용하면 더욱 강력한 폼 검증을 수행할 수 있습니다.

🔹React Hook Form과 Zod 설정

yarn add @hookform/resolvers
# 또는
npm install @hookform/resolvers

🔹 React Hook Form에서 Zod 적용하기

"use client"

import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { z } from "zod";

const signInSchema = z.object({
  email: z.string().email({ message: "Invalid email" }).min(1, { message: "Email required" }),
  password: z.string().min(8, "Password must be at least 8 characters")
});

const SignInForm = () => {
  const { register, handleSubmit, formState } = useForm({
  mode: "onChange",
    resolver: zodResolver(signInSchema),
  });

  const onSubmit = async (data) => {
    console.log(data);
  }
  
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register("email")} placeholder="Email" />
      {formState.errors.email && <p>{formState.errors.email.message}</p>}

      <input type="password" {..register("password")} placeholder="Password" />
      {formState.errors.password && <p>{formState.errors.password.message}</p>}

      <button type="submit" disabled={!formState.isValid}>
        Sign In
      </button>
    </form>
  )
}

✔️ zodResolver를 사용해 Zod와 React Hook Form을 연결할 수 있습니다.
✔️ formState.errors를 통해 검증 오류 메시지를 표시할 수 있습니다.
✔️ mode: "onChange"를 설정하면 입력값이 변경될 때마다 검증이 실행됩니다.

3️⃣ 고급 사용법

🔹 비동기 검증 (예: 이메일 중복 체크)

const asyncSchema = z.object({
  email: z.string().email("Invalid email")
})

const SignInForm = () => {
  const { register, handleSubmit, formState } = useForm({
    resolver: zodResolver(asyncSchema),
    mode: "onBlur",
    asyncResolver: async (value) => {
      const res = await fetch("/api/validate-email", {
        method: "POST",
        body: JSON.stringify({ email: values.email })
      });
      const data = await res.json();
      return data.isValid ? { values } : { values: {}, errors: { email: { message: "Email already taken" } } }
    }
  })

  return (
    <form onSubmit={handleSubmit((data) => console.log(data))}>
      <input {...register("email")} placehandler="Email" />
      {formState.errors.email && <p>{formState.errors.email.message}</p>}

      <button type="submit">Sign In</button>
    </form>
  )
}

✔️ asyncResolver를 사용하면 서버와 연동하여 검증할 수 있습니다.
✔️ mode: "onBlur"를 설정하면 입력 필드에서 포커스를 벗어날 때 검증이 실행됩니다.