똑같은 삽질은 2번 하지 말자

zod로 가볍게 validation을 해보자 본문

카테고리 없음

zod로 가볍게 validation을 해보자

곽빵 2024. 3. 31. 22:26

개요

Next.js을 이용해 프로젝트를 진행중 손쉽게 validation을 구축할 수 있는 zod을 활용했던 기록

Zod란?

Typescript에서 타입 안전성을 보장하기 위해 사용되는 스키마 선언 및 유효성 검사 라이브러리이다.

밑과 같은 특징을 가진다.

  • 타입 안전성: Zod 스키마를 정의하면, 이를 기반으로 Typescript 타입을 자동으로 생성할 수 있어, 타입 안정성과 validation을 쉽게 연결 시킬 수 있다.
  • 선언적 스키마 정의: 객체, 배열, 문자열, 숫자, 날짜 등 다양한 Javascript 데이터 타입에 대한 검증 규칙을 선언적으로 정의할 수 있다.
  • 커스텀 검증 로직: 사용자가 직접 커스텀 검증 함수를 정의하여 복잡한 검증 로직을 구현할 수 있다.
  • 에러 핸들링: 유효성 검사 과정에서 발생하는 에러를 자세하게 캐치하여 처리할 수 있다.

이하의 요구사항을 만족하는 샘플 코드를 작성해보자.

요구사항

  • 유저 데이터가 있으며 복수의 데이터가 존재한다.
  • 유저 데이터는 이름, 이메일, 전화번호를 가지고 있다. 그리고 각각의 검증요소는 이하이다.
    • 이름: 필수
    • 이메일: 필수, 이메일 형식
    • 전화번호: 필수, 전화번호 형식
  • 복수의 데이터를 검증할 때 몇번째 데이터에 문제가 있는지를 알 수 있는 에러메세지가 필요

샘플코드

// zod를 이용해 복수의 유저 데이터의 스키마를 정의하며 에러메세지를 설정한다.
const userSchema = z.object({
  name: z.string().nonempty({ message: "Name is required" }),
  email: z.string().nonempty({ message: "Email is required" }).email({ message: "Invalid email format" }),
  phoneNumber: z.string().nonempty({ message: "Phone number is required" }).regex(/^\\+[1-9]{1}[0-9]{3,14}$/, { message: "Invalid phone number format" }),
});

const usersSchema = z.array(userSchema);

// 테스트 데이터
const usersData = [
  { name: "John Doe", email: "john@example.com", phoneNumber: "+1234567890" },
  { name: "Jane Doe", email: "jane@example", phoneNumber: "+0987654321" }, // Invalid email
  { name: "", email: "mike@example.com", phoneNumber: "12345" }, // Invalid name and phone number
];

// 테스트 실행
try {
  usersSchema.parse(usersData); // validation 실행
  console.log("All users data is valid!");
} catch (error) {
  if (error instanceof z.ZodError) {
    // 검증에러가 발생한 뒤, 어느 부분에 에러가 발생했는지를 알 수 있는 에러메세지를 작성
    const errorMessages = error.errors.map(e => `User ${e.path[0]}: ${e.message}`);
    
    // 이하의 에러메세지가 출력
    // Validation errors: ["User 2 Invalid email format", "User 3 Name is required"]
    console.error("Validation errors:", errorMessages);
  }
}

// schema로부터 타입 추출도 할 수 있다.
type User = infer<typeof userSchema>;
type Users = infer<typeof usersSchema>;
  • e.path[0]: 문제가 있는 데이터의 index가 들어있다.
  • e.message에는 schema에서 설정한 메세지가 출력된다.

 

zod를 이용해 데이터의 스키마를 정의하면 그대로 타입으로도 사용할 수 있고 데이터의 형태와 validation의 설정이 그대로 연결되서 이 데이터가 어떤 데이터이며 어떻게 다뤄야하는 데이터인지를 한눈에 알 수 있게 선언적으로 되어 있어 가독성면에서도 상당히 도움이 될 듯 하다.

Comments