[TypeScript] 속성 검증 라이브러리 비교 분석
반응형
목차
라이브러리 개요
1. Zod
import { z } from "zod";
const UserSchema = z.object({
id: z.string().uuid(),
email: z.string().email(),
age: z.number().min(0).max(120)
});
2. Joi
import * as Joi from 'joi';
const schema = Joi.object({
username: Joi.string().min(3).max(30).required(),
email: Joi.string().email().required()
});
3. Yup
import * as yup from 'yup';
const schema = yup.object({
name: yup.string().required(),
age: yup.number().positive().integer()
});
4. Lodash
import * as _ from 'lodash';
const validateUser = (user: unknown) => {
if (!_.isObject(user)) return false;
return _.every([
_.has(user, 'name') && _.isString(user.name),
_.has(user, 'age') && _.isNumber(user.age)
]);
};
기능 비교
1. 타입 안전성
Zod: ⭐⭐⭐⭐⭐
- 최고 수준의 TypeScript 통합
- 자동 타입 추론
Joi: ⭐⭐⭐
- TypeScript 지원은 있으나 제한적
Yup: ⭐⭐⭐⭐
- TypeScript 지원 우수
Lodash: ⭐⭐
- 타입 검사는 가능하나 TypeScript 통합 제한적
2. 검증 기능
// Zod
const ResourceSchema = z.object({
type: z.enum(["vpc", "subnet"]),
config: z.record(z.unknown())
});
// Joi
const schema = Joi.object({
type: Joi.string().valid('vpc', 'subnet'),
config: Joi.object().pattern(Joi.string(), Joi.any())
});
// Yup
const schema = yup.object({
type: yup.string().oneOf(['vpc', 'subnet']),
config: yup.object().test(value => true)
});
// Lodash
const validateResource = (resource: unknown) => {
return _.isObject(resource) &&
_.has(resource, 'type') &&
_.includes(['vpc', 'subnet'], resource.type) &&
_.isObject(_.get(resource, 'config'));
};
3. 커스텀 검증
// Zod
const withCustomValidation = z.object({}).refine(
data => customValidation(data),
"Custom validation failed"
);
// Joi
const withCustomValidation = Joi.object().custom((value, helpers) => {
if (!customValidation(value)) {
return helpers.error('custom.invalid');
}
return value;
});
// Yup
const withCustomValidation = yup.object().test(
'custom',
'Custom validation failed',
value => customValidation(value)
);
// Lodash
const withCustomValidation = (data: unknown) => {
return _.conformsTo(data, {
field: value => customValidation(value)
});
};
성능 분석
번들 크기
const bundleSizes = {
zod: '17.5kB',
joi: '97.1kB',
yup: '37.2kB',
lodash: '71.5kB' // 전체 패키지 기준
};
검증 속도 (10,000회 실행)
const benchmarkResults = {
zod: 145, // ms
joi: 320, // ms
yup: 210, // ms
lodash: 95 // ms (단순 타입 체크 기준)
};
사용 사례
1. 복잡한 객체 구조 검증
// Zod
const ComplexSchema = z.object({
nested: z.object({
array: z.array(z.string())
}).optional()
});
// Lodash
const validateComplex = (data: unknown) => {
return _.isObject(data) &&
(_.isUndefined(data.nested) ||
(_.isObject(data.nested) &&
_.isArray(data.nested.array) &&
_.every(data.nested.array, _.isString)));
};
2. 조건부 검증
// Zod
const ConditionalSchema = z.object({
type: z.string(),
data: z.any().refine(
(data, ctx) => ctx.parent.type === 'number' ? _.isNumber(data) : true
)
});
// Lodash
const validateConditional = (obj: unknown) => {
if (!_.isObject(obj)) return false;
if (obj.type === 'number') {
return _.isNumber(obj.data);
}
return true;
};
각 라이브러리의 특징적 장점
Zod
- 강력한 TypeScript 통합
- 런타임 타입 안전성
- 직관적인 API
Joi
- 풍부한 검증 규칙
- 상세한 에러 메시지
- 깊은 객체 검증
Yup
- Form 라이브러리 통합
- Promise 기반 검증
- 직관적인 API
Lodash
- 가볍고 빠른 검증
- 유연한 커스텀 검증
- 다양한 유틸리티 함수 제공
권장 사용 상황
Zod 권장
- TypeScript 프로젝트
- 복잡한 타입 검증
- 강력한 타입 추론 필요
Lodash 권장
- 간단한 타입 체크
- 유연한 커스터마이징
- 성능이 중요한 경우
Joi 권장
- 복잡한 검증 규칙
- 상세한 에러 처리
- JavaScript 프로젝트
Yup 권장
- Form 검증
- 간단한 객체 검증
- Promise 기반 로직
결론
각 라이브러리는 고유한 장점이 있습니다:
- Zod: 타입 안전성과 검증을 모두 잡고 싶을 때
- Lodash: 간단하고 유연한 검증이 필요할 때
- Joi: 복잡한 검증 규칙이 필요할 때
- Yup: 폼 검증이 주요 사용 사례일 때
이러한 비교를 통해, TypeScript 프로젝트에서의 리소스 속성 검증에는 Zod가 가장 적합한 선택임을 알 수 있습니다. Zod는 뛰어난 TypeScript 지원, 높은 성능, 그리고 타입 안전성을 제공하면서도 직관적인 API를 제공합니다.
반응형
댓글