Zod는 입력 유효성 검사를 위한 TypeScript 라이브러리입니다. TypeScript는 컴파일 타임에 JavaScript 개발을 위한 타입 안전성을 보장하는 데 있어 심오한 작업을 수행했습니다. Zod는 브라우저에서 양식 유효성 검사와 같은 런타임 유효성 검사를 제공하여 TypeScript를 보완합니다.
부인 성명 한국어 실력이 부적하여 이 글이 구글 번역기를 주로 활용했기 때문에 부정확한 문법과 어휘가 있을수 있습니다. 이 점 양해 부탁드리며, 추후에 다시 검토하여 수정하도록 하겠습니다.
기본 사용법
아래 샘플은 UserSchema라는 Zod 객체 스키마에 대해 user 객체를 구문 분석하려고 시도합니다. 유효성 검사가 성공하면 개체 자체를 반환하고 그렇지 않으면 오류가 발생합니다.
import { z } from 'zod'
const UserSchema = z.object({
id: z.number(),
username: z.string(),
email: z.string().email(),
})
const user = { id: 1, username: 0, email: 'abcd' }
console.log(UserSchema.parse(user))스키마 추론
Zod의 스키마는 타입 추론에도 사용할 수 있으며 이는 코드 재사용에 매우 유용합니다.
const UserSchema = z.object({
id: z.number(),
username: z.string(),
email: z.string().email(),
})
type User = z.infer<typeof UserSchema>
const user: User = {
id: 123,
username: 'Jason',
email: 'json@gmail.com',
}
console.log(UserSchema.parse(user)) // `user` 개체 똑같은안전한 구문 분석
유효성 검사가 실패할 때 오류를 발생시키는 대신 유효성 검사 상태를 나타내는 success 속성을 사용하여 결과를 개체로 래핑합니다. error 속성은 유효성 검사가 실패한 경우에만 액세스할 수 있는 반면, data 속성은 유효성 검사를 통과한 경우에만 사용할 수 있습니다.
const result = UserSchema.parse(user)
if (!result.success) {
console.log(result.error)
} else {
console.log(result.data as User)
}기본 타입
기본 타입에는 z.object, z.string, z.number, z.date 및 z.boolean이 포함됩니다.
const UserSchema = z.object({
username: z.string(),
age: z.number(),
birthday: z.date(),
isProgrammer: z.boolean(),
})특별한 타입
JavaScript에서 잘못된 값을 처리하는 추가 타입입니다.
z.object({
undefined_type: z.undefined(),
null_type: z.null(),
void_type: z.void(),
any_type: z.any(),
unknown_type: z.unknown(), // `any`와 동일하게 사용할 수 있습니다
never_type: z.never(), // 객체에 이 '키'가 없어야 합니다. 그렇지 않으면 실패합니다.
})수정자
필드의 요구 사항을 수정하거나 구체화하기 위해 타입 정의 뒤에 연결되는 추가 논리입니다.
z.object({
optional: z.string().optional(),
nullable: z.string().nullable(), // 'null'일 수 있으며 이는 'optional'과 다릅니다.
nullish: z.string().nullish(), // 'null' 또는 'undefined'일 수 있습니다.
default: z.string().default('안녕'),
randomNum: z.number().default(Math.random),
})문자열 수정자
const UserSchema = z.object({
username: z.string().min(3).max(10), // 문자열 크기
email: z.string().email(),
url: z.string().url(),
})문자열 수정자 더 보기
숫자 수정자
const UserSchema = z.object({
age: z.number().gt(0),
})숫자 수정자 더 보기
리터럴 타입
정확히 일치하는 특정 값입니다.
z.literal('sashimi')
z.literal(true)리터럴 타입 더 보기
변형 목록
Zod Enum을 사용하면 기본적으로 TypeScript 공용체 타입으로 변환됩니다.
z.enum(['Programming', 'Guitar'])배열이 z.enum 절 외부에 선언되면 배열에 as const 키워드를 추가해야 합니다.
const hobbies = ['Programming', 'Guitar'] as const
z.enum(hobbies) // 문제 없음
console.log(hobbies[0])이러한 방식으로 Zod는 정확한 검증을 위해 애플리케이션 전체에서 값이 변경되지 않도록 할 수 있습니다.
Zod Enum 외에도 네이티브 TypeScript Enum도 z.nativeEnum으로 지원될 수 있습니다.
enum Hobbies {
Programming,
Guitar,
}
z.nativeEnum(Hobbies)
const ppl = {
hobbies: Hobbies.Programming,
}물체 타입
스키마의 모양을 얻으려면 shape 속성을 사용하세요. 그러면 어떤 필드가 있는지와 해당 데이터 타입이 표시됩니다.
UserSchema.shape부분 수정자는 스키마 내의 각 필드를 선택 사항으로 만들어 다단계 형식에 유용합니다.
UserSchema.partial().parse(user)RxJS의 pluck과 유사하게 pick은 더 큰 객체에서 지정된 키 값 쌍을 선택합니다.
UserSchema.pick({ username: true }).parse(user)특정 요소를 생략하려면 omit 메소드를 사용하세요. 메소드 서명은 pick과 동일합니다.
UserSchema.omit({ username: true }).parse(user)Zod는 기본적으로 얕은 검사만 수행하므로 Deep Partials를 사용하면 다른 객체에 중첩된 객체를 비교할 수 있습니다.
UserSchema.deepPartial().parse(user)확장을 사용하면 추가 필드를 사용하여 원래 스키마를 새 스키마로 확장할 수 있습니다.
UserSchema.extend({ name: z.string() }).parse(user)기존 스키마를 다른 스키마와 함께 새 스키마로 병합합니다.
UserSchema.merge(UserSchema2).parse(user)존재 없는 키
기본적으로 Zod는 스키마에 정의되지 않은 모든 키 값 쌍을 생략합니다. 예를 들어, 이런 객체가 있다면,
const UserSchema = z.object({
username: z.string().min(5).max(15),
})
const user = {
username: 'Jason', // 스키마에 정의됨
address: '41777 South Bound, West Virginia', // 스키마에 정의하지 않음
}구문 분석 후 결과 객체에는 address 속성이 없습니다.
console.log(UserSchema.parse(user))문서화되지 않은 필드가 최종 출력에 포함되도록 하려면 passthrough를 사용하세요.
const UserSchema = z
.object({
username: z.string().min(5).max(15),
})
.passthrough()그렇지 않으면 원래 스키마 내에 존재하지 않는 제공된 키가 있는 경우 strict 모드에서 오류가 발생합니다.
const UserSchema = z
.object({
username: z.string().min(5).max(15),
})
.strict()배열 타입
배열 타입은 z.array를 사용하여 선언하고 보유할 값 타입을 전달할 수 있습니다.
z.array(z.string())배열에 값이 하나 이상 포함되어 있는지 확인하려면 nonempty 수정자를 사용하세요.
z.array(z.string()).nonempty()배열 타입 더 보기
튜플 타입
튜플 유형을 선언하려면 Zod 유형 선언 배열을 z.tuple 메소드에 전달하세요. 유형 선언은 수정자와 잘 연결될 수 있습니다.
z.tuple([z.number(), z.number(), z.number().gt(4).int()])길이가 무한한 튜플을 선언하려면 rest를 사용하여 나머지 매개변수 선언에 언급되지 않은 요소의 유형을 나타낼 수 있습니다.
z.tuple([z.string(), z.date()]).rest(z.number())유니언 타입
이거는 TypeScript같은 유니언 타입이다.
z.union([z.string(), z.number()]) // id
z.string().or(z.number()) // same태그된 유니언 - 한 필드의 유형은 이전에 정의된 필드의 출력에 따라 달라집니다.
const UserSchema = z.object({
id: z.discriminatedUnion('status', [
z.object({ status: z.literal('success'), data: z.string() }),
z.object({ status: z.literal('failed'), data: z.instanceof(Error) }),
]),
})레코드 타입
객체에 대한 키 값 쌍 유효성 검사입니다. 아래 예에서는 문자열 유형이어야 하는 객체의 '키'만 유효성을 검사합니다.
const UserMap = z.record(z.string()) // 키 만
const usermp = {
abc: 'abc',
def: 'def',
}z.record 메소드에 두 개의 Zod 타입을 제공하여 객체의 키와 값 쌍을 모두 검증하는 것이 가능합니다.
const UserMap = z.record(z.string(), z.number()) // 키과 값맵 타입
이는 위의 record 유형과 매우 유사하지만 실제 JavaScript Map 유형 자체에 맞게 조정되었습니다.
const UserMap = z.map(z.string(), z.object({ name: z.string() }))
const users = new Map([
['id-jogn', { name: 'Jphn' }],
['id-kye', { name: 'Kyle' }],
])셋 타입
const UserMap = z.set(z.number())
const a = new Set([1, 1, 1, 2])
console.log(UserMap.parse(a)) // [1, 2]프로미스 타입
const PromiseSchema = z.promise(z.string())
const p = Promise.resolve('ahaha') // 2단계 검증
console.log(PromiseSchema.parse(p))메시지 수정
유효성 검사에 실패했을 때 표시되는 오류 메시지를 조작하는 등 낮은 수준의 액세스 권한을 부여합니다.
const brandEmail = z
.string()
.email()
.refine((val) => val.endsWith('@email.com'), {
message: '이메일은 @email.com으로 끝나야 합니다.',
})
const email = 'email.com'
console.log(brandEmail.parse(email))사용자 정의를 위해 매우 낮은 수준의 액세스 권한을 제공하는
superRefine이라는 방법도 있습니다.
오류
오류 메시지는 대상 절에 두 번째 인수로 제공하여 사용자 정의할 수 있습니다.
z.string().min(3, '3자 이상이어야 됩니다.')그 외에도 모든 복잡한 오류 메시지를 사람이 더 읽기 쉬운 방식으로 변환하는 Zod에서 제공하는 유효성 검사 오류 패키지가 있습니다.
npm i zod-validation-errorimport { fromZodError } from 'zod-validation-error'
if (!results.success) {
console.log(fromZodError(results.error))
}