Zod
- TypeScript 기반의 스키마 선언 및 유효성 검사 라이브러리
- TypeScript 의 타입 시스템과 완벽하게 통합되어 런타임에서 데이터 유효성을 검사할 수 있음
- 타입 안정성, 간결한 구문, 비동기 유효성 검사, 확장성, 유연한 검증 로직 구성을 제공
* 스키마 선언이란?
import { z } from 'zod';
// 사용자 데이터 구조 정의
const UserSchema = z.object({
name: z.string(), // 이름은 문자열이어야 함
age: z.number(), // 나이는 숫자여야 함
email: z.string().email() // 이메일 형식이어야 함
});
- 데이터의 구조와 규칙을 미리 정의하는 것
- (데이터가 어떤 형태여야 하는지, 어떤 제약조건을 가져야 하는지를 명시)
주요 장점
1. 런타임 타입 안정성
- TypeScript는 컴파일 타임에만 타입 체크를 수행하지만, Zod는 런타임에서도 데이터 유효성을 검증한다.
- 외부 데이터(API 응답, 사용자 입력)의 안전성을 보장할 수 있다.
2. 스키마 재사용성과 타입추론
- 한 번 정의한 스키마를 여러 곳에서 재사용할 수 있다.
- 스키마에서 TypeScript 타입을 자동으로 추론
3. 풍부한 유효성 검사와 에러 처리
- 다양한 유효성 검사 기능 제공
- 명확한 에러 메시지와 처리 방법
4. 개발 편의성
- 의존성 없는 독립적인 라이브러리
- 직관적이고 간단한 API 구조
주요 단점
1. 번들 크기 증가
- 프로덕션 번들에 포함되어 앱 크기가 커질 수 있음
2. 런타임 오버헤드
- 대규모 데이터나 복잡한 스키마의 경우 약간의 성능 저하가 발생할 수 있음
3. 학습 곡선
- 복잡한 스키마를 작성할 때 초기 학습이 필요
4. 유연성 부족
- 개발자가 원하는 수준의 유연성을 제공하지 못할 수 있음
주요 사용 방법
1. 기본 타입 정의
const stringSchema = z.string();
const numberSchema = z.number();
const booleanSchema = z.boolean();
const nullSchema = z.null();
const undefinedSchema = z.undefined();
2. 객체 스키마
const userSchema = z.object({
id: z.number(),
name: z.string(),
email: z.string().email(),
age: z.number().optional(),
metadata: z.record(z.string()) // 동적 키를 가진 객체
});
3. 배열 스키마
const numberArray = z.array(z.number());
const stringArray = z.string().array();
const tupleSchema = z.tuple([z.string(), z.number()]);
스키마 메서드
[유효성 검사 메서드]
1. parse
const stringSchema = z.string();
stringSchema.parse("fish"); // => returns "fish"
stringSchema.parse(12); // throws error
- 정의된 스키마에 대해 데이터의 유효성을 검증한다.
- 데이터가 유효하면 전달한 값의 깊은 복사본이 반환됨
- 데이터가 유효하지 않으면(실패 시) 에러를 발생시킴 (throw error)
- try-catch 블록으로 에러 처리를 해줘야 한다.
2. safeParse
stringSchema.safeParse(12);
// => { success: false; error: ZodError }
stringSchema.safeParse("billie");
// => { success: true; data: 'billie' }
- 성공/실패 여부와 데이터/에러를 객체로 반환
- 검증에 실패했을 때 에러를 throw 하지 않고 결과 객체를 반환
- 에러 처리가 필요하지만 try-catch를 사용하고 싶지 않을 때 유용하다.
3. parseAsync
const stringSchema = z.string().refine(async (val) => val.length <= 8);
await stringSchema.parseAsync("hello"); // => returns "hello"
await stringSchema.parseAsync("hello world"); // => throws error
- 비동기 검증이 필요한 경우 사용
- Promise 를 반환하고 검증 실패 시 에러를 throw
- 비동기 검증이 필요하지만 에러 throw를 피하고 싶다면 safeParseAsync를 대신 사용할 수 있음
4. refine
const myString = z.string().refine((val) => val.length <= 255, {
message: "String can't be more than 255 characters",
});
- 기본 유효성 검사 외 사용자 정의(커스텀) 검증 로직을 추가할 수 있게 해주는 기능
- 비동기 검증 시 parseAsync 와 같이 사용해야 오류가 발생하지 않음
[변환 메서드]
- transform
const emailToDomain = z
.string()
.email()
.transform((val) => val.split("@")[1]);
emailToDomain.parse("colinhacks@example.com"); // => example.com
- 스키마의 유효성 검사가 완료된 후 데이터를 원하는 형태로 변환할 수 있게 해주는 기능
[조합 메서드]
// 유니온 타입
const stringOrNumber = z.union([z.string(), z.number()]);
// 인터섹션 타입
const combinedSchema = z.intersection(
z.object({ name: z.string() }),
z.object({ age: z.number() })
);
[선택적 필드]
const optionalString = z.string().optional(); // string | undefined
const nullableString = z.string().nullable(); // string | null
const nullishString = z.string().nullish(); // string | null | undefined
1. optional
- 필수 입력을 선택적 입력으로 변경하는 메서드(undefined를 허용하도록 만듦)
2. nullable
- null 값을 허용하도록 만드는 메서드(undefined는 허용X)
3. nullish
- optional과 nullable을 동시에 적용한 것과 같은 효과를 주는 메서드
- null과 undefined 둘 다 허용
[문자열 유효성 검사 옵션]
z. string (). min ( 5 , { message : "5자 이상이어야 합니다." });
z. string (). max ( 5 , { message : "5자 이하여야 합니다." });
z. string (). length ( 5 , { message : "정확히 5자여야 합니다." });
z. string (). email ({ message : "잘못된 이메일 주소입니다." });
z. string (). url ({ message : "잘못된 url입니다." });
z. string (). emoji ({ message : "이모지가 아닌 문자가 포함되어 있습니다." });
z. string (). uuid ({ message : "잘못된 UUID입니다." });
z. string (). includes ( "tuna" , { message : "tuna를 포함해야 합니다." });
z. string (). startsWith ( "https://" , { message : "보안 URL을 제공해야 합니다." });
z. string (). endsWith ( ".com" , { message : ".com 도메인만 허용됩니다" });
z. string (). datetime ({ message : "날짜/시간 문자열이 잘못되었습니다! UTC여야 합니다." });
z. string (). ip ({ message : "IP 주소가 잘못되었습니다" });
- 더 다양한 메서드는 zod 공식 문서에 잘 정리되어 있다!
React Hook Form과 Zod
- react-hook-form 과 zod 를 통합해 복잡한 폼 관리와 유효성 검사를 간편하게 처리할 수 있다.
- zodResolver를 통해 두 라이브러리를 쉽게 통합이 가능하다.
- Zod : 런타임 시점의 타입 검증 제공
- React Hook Form : 불필요한 리렌더링 방지
🧐 느낀점
개인프로젝트의 회원가입 기능 구현 중 이전에 들어보았던 react-hook-form 과 zod 를 활용해서 구현하고자 먼저 zod 에 대해서 정리해보면서 구조와 사용방법에 대해서 공부했다. react-hook-form 도 좀 더 정리해보고 프로젝트에 적용해 볼 예정이다!
'Library' 카테고리의 다른 글
React Hook Form (0) | 2025.01.22 |
---|