들어가기에 앞서
이 글은 Yup의 자세한 사용법을 다루지 않습니다. 자세한 내용은 공식문서를 참고 바랍니다. 이 글에서는 기본적인 사용법을 정리하며 이 중 착각하거나, 놓치고 지나가기 쉬운 부분에 대해 다루고자 합니다.
Yup 이란
Yup은 모델의 스키마를 정의할 수 있도록 하며, 유효 값 검증(validation), 형 변환(parsing), 원하는 값으로 조작(transformation)등의 기능을 제공하는 라이브러리 입니다. 이를 통해 더욱 안정성 있는 어플리케이션의 설계와 구현이 가능합니다.
Yup 사용법
객체의 프로퍼티의 타입으로 사용할 수 있는 타입 중에서 주로 사용되는 아래 다섯 가지에 대해 다루도록 하겠습니다.
- string
- number
- boolean
- date
- array
타입 지정
기본적으로 아래와 같은 방식으로 각각의 프로퍼티의 타입을 지정해 줄 수 있습니다.
const basicSchema = object({
str: string(),
num: number(),
bool: boolean(),
date: date(),
arr: array(), // array().of(number()) 또는 array(number())와 타입 지정 가능
});
당 스키마를 사용하여 validation 오류를 체크할 경우 에러가 발생하는 경우는 이와 같습니다.
- null 값을 갖는 경우
- 타입에 맞지 않는 값을 가진 경우(다만 지정한 타입으로 파싱이 가능한 값의 경우 에러가 발생하지 않습니다.)
// 성공
await basicSchema.validate({ str: undefined });
await basicSchema.validate({ str: '' });
await basicSchema.validate({ str: '문자열' });
await basicSchema.validate({ str: new Date() });
// 실패
await basicSchema.validate({ str: null });
await basicSchema.validate({ str: [] });
그런데 주의해야 할 점이 있습니다. 스키마에서 정의한 프로퍼티가 검증하고자 하는 객체에 존재하지 않아도 에러는 발생하지 않습니다. 극단적으로 아래와 같은 경우에도 에러는 발생하지 않습니다.
// 성공
await basicSchema.validate({});
해당 프로퍼티가 가진 값이 유효한지만 체크하기 때문입니다.
위 경우를 피하고자 한다면 아래 소개할 defined()
또는 required()
와 함께 사용합니다.
defined()
defined()
를 사용 시, 스키마에 정의한 property는 검증하고자 하는 객체에 반드시 존재해야 합니다.
또한 값은 null, undefined 일 수 없습니다.
해당 프로퍼티는 말 그대로 defined 된 유효한 값을 가지고 있어야 하는 것 입니다.
const definedSchema = object({
str: string().defined(),
});
// 성공
await definedSchema.validate({ str: '' });
await definedSchema.validate({ str: '문자열' });
// 실패
await definedSchema.validate({});
await definedSchema.validate({ str: null });
await definedSchema.validate({ str: undefined });
required()
required()
가 지정된 경우 해당 프로퍼티는 반드시 유효한 값을 가지고 있어야 합니다.
defined()
의 역할과 동일하다고 볼 수 있지만, string 타입에 사용된 경우 빈 문자열을 허용하지 않는다는 한 가지 조건이 더 붙습니다.
const requiredSchema = object({
str: string().required(),
});
// 성공
await requiredSchema.validate({ str: '문자열' });
// 실패
await requiredSchema.validate({});
await requiredSchema.validate({ str: '' }); // <- 빈 문자열의 경우 에러발생
await requiredSchema.validate({ str: null });
await requiredSchema.validate({ str: undefined });
nullable()
스키마에 타입이 정의된 프로퍼티의 경우 값으로 null을 가질 수 없습니다.
만약 null 값을 허용해야 하는 프로퍼티의 경우 nullable()
를 사용합니다.
const nullableSchema = object({
str: string().nullable(),
});
// 성공
await nullableSchema.validate({})
await nullableSchema.validate({ str: null })
nullable()
은 해당 프로퍼티의 유효한 값으로 null을 허용한 것입니다.
아래와 같이 defined()
또는 required()
와 함께 사용할 수 있습니다.
const nullableSchema2 = object({
str: string().defined().nullable(),
});
// 성공
await nullableSchema.validate({ str: null })
// 실패
await nullableSchema2.validate({})
Typescript 사용
Yup은 라이브러리 특성상 타입스크립트와 함께 사용하면 더욱 효과적입니다. 아래와 같이 정의한 스키마를 interface가 상속하여 사용할 수 있습니다. 만약 스키마로 관리할 필요성이 떨어지는 프로퍼티의 경우 interface에 정의해 타입을 관리하는 방법도 고려할 수 있습니다.
const typescriptSchema = object({
str: string().required(),
num: number().defined(),
date: date().defined().nullable(),
bool: boolean().default(false),
})
interface Types extends InferType<typeof typescriptSchema> {
arr?: Array<number>;
}
const obj: Types = {
str: '문자열',
num: 12,
date: new Date(),
bool: false
}