TypeScript Zod 검증 패턴
Zod 스키마를 사용하여 런타임 데이터 검증 및 정적 타입을 동시에 관리하는 패턴 모음입니다.
import { z } from 'zod';
/**
* 사용자 정보 스키마 정의
*/
const userSchema = z.object({
id: z.string().uuid(),
username: z.string().min(3).max(20),
email: z.string().email(),
age: z.number().int().min(18).optional(),
role: z.enum(['admin', 'user', 'guest']).default('user'),
createdAt: z.date().default(() => new Date()),
});
/**
* 스키마로부터 타입 추출
*/
type User = z.infer<typeof userSchema>;
/**
* 입력 데이터 검증 예시
*/
function validateUser(data: unknown) {
const result = userSchema.safeParse(data);
if (!result.success) {
// 검증 실패 시 상세 에러 메시지 구성
const errorMessages = result.error.errors.map(err => ({
path: err.path.join('.'),
message: err.message
}));
return { success: false, errors: errorMessages };
}
// 검증 성공 시 타입이 보장된 데이터 반환
return { success: true, data: result.data };
}
/**
* 복잡한 조건부 검증 (Refine) 예시
*/
const passwordResetSchema = z.object({
password: z.string().min(8),
confirmPassword: z.string(),
}).refine((data) => data.password === data.confirmPassword, {
message: "Passwords don't match",
path: ["confirmPassword"],
});
/**
* API 요청 본문 검증 미들웨어 예시 (가상)
*/
const createUpdateUserSchema = userSchema.partial().extend({
username: z.string().min(3).max(20),
});
// 사용 예시
const rawData = {
id: "550e8400-e29b-41d4-a716-446655440000",
username: "johndoe",
email: "invalid-email",
age: 15
};
const validation = validateUser(rawData);
if (!validation.success) {
console.log("Validation failed:", validation.errors);
}