![](/zbxe/layouts/mr_layouts_1st/images/default/blank.gif)
강좌 & 팁
발로하는 번역입니다. - 번역 결과에 절대로 책임지지 않습니다. (경고 했음!)
simple-schema
--------------------------------------------------------------------------------------
simple-schema는 반응형 스키마 유효성 검사를 지원하는 미티어 패키지이다.
주로 Collection2 와 AutoForm 패키지에서 simple-schema를 사용한다.
물론 simple-schema 패키지만을 사용할 수도 있다.
목차 (DocToc을 이용하여 생성됨)
--------------------------------------------------------------------------------------
설치
기본적인 사용법도도
예
SimpleSchemas 조합
SimpleSchemas 추출
유효성 검사 대상 오브젝트
스키마 키
스키마 규칙
type
label
optional
min/max
exclusiveMin/exclusiveMax
decimal
minCount/maxCount
allowedValues
regEx
blackbox
trim
custom
defaultValue
autoValue
데이터 정리
데이터 유효성 검사
명명된 검사 컨텍스트
이름 없는 유효성 검사 컨텍스트
오브젝트의 유효성 검사
Object내에 하나의 키만 검사
검사 옵션
check() 또는 Match.test()를 사용한 유효성 검사
사용자 작성 유효성 검사
수동으로 유효성 검사 에러 추가
클라이언트측 사용자 정의 비동기적 유효성 검사
기타 검사 컨텍스트 메소드
기타 SimpleSchema 메쏘드
유효성 검사 메시지 사용자 정의
날짜
Collection2 와 AutoForm
모범 사례 코드 예제
조건에 따라 유효성 검사 대상으로 결정되는 필드 만들기
다른 키에 대한 키의 유효성 검사
디버그 모드
스키마 옵션 확장
라이센스
기여
감사
설치
--------------------------------------------------------------------------------------
미티어 앱 디렉토리에서 다음과 같이 입력한다.
$ meteor add aldeed:simple-schema
기본적인 사용법
--------------------------------------------------------------------------------------
하나 이상의 SimpleSchema 인스턴스를 생성하고 이 인스턴스로 사용하여
오브젝트의 유효성 검사를 한다.
컬렉션에 삽입 하거나 업데이트 하는 작업에 대하여 유효성 검사를 하려면
생성된 SimpleSchema 인스턴스를 컬렉션에 연결해야 한다.
이를 위해서 먼저 미티어 앱에 aldeed:collection2 패키지를 추가해야 한다.
더불어 미티어 앱에 aldeed:autoform 패키지를 추가하면,
스키마에 대한 유효성 검사 처리가 포함된 폼을 자동으로 만들 수 있다.
예
-------
// 스키마를 정의한다.
BookSchema = new SimpleSchema({
title: {
type: String,
label: "Title",
max: 200
},
author: {
type: String,
label: "Author"
},
copies: {
type: Number,
label: "Number of copies",
min: 0
},
lastCheckedOut: {
type: Date,
label: "Last date this book was checked out",
optional: true
},
summary: {
type: String,
label: "Brief summary",
optional: true,
max: 1000
}
});
// 스키마에 대한 오브젝트 유효성 검사
obj = {title: "Ulysses", author: "James Joyce"};
isValid = mySchema.namedContext("myContext").validate(obj);
// 또는
isValid = mySchema.namedContext("myContext").validateOne(obj, "keyToValidate");
// 또는
isValid = Match.test(obj, mySchema);
// 또는
check(obj, mySchema);
// 반응형 메소드를 이용해서 유효성 검사 오류 보기
if (Meteor.isClient) {
Meteor.startup(function() {
Tracker.autorun(function() {
var context = BookSchema.namedContext("myContext");
if (!context.isValid()) {
console.log(context.invalidKeys());
}
});
});
}
SimpleSchemas 조합
------------------
하나 이상의 하위 속성을 공유하는 스키마들을 서브 스키마로 만들면
코드를 깔끔하고 간결하게 만들 수 있다.
예:
AddressSchema = new SimpleSchema({
street: {
type: String,
max: 100
},
city: {
type: String,
max: 50
},
state: {
type: String,
regEx: /^A[LKSZRAEP]|C[AOT]|D[EC]|F[LM]|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEHINOPST]|N[CDEHJMVY]|O[HKR]|P[ARW]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY]$/
},
zip: {
type: String,
regEx: /^[0-9]{5}$/
}
});
CustomerSchema = new SimpleSchema({
billingAddress: {
type: AddressSchema
},
shippingAddresses: {
type: [AddressSchema],
minCount: 1
}
});
또 다른 조합 예는,
여러 곳에서 간단한 스키마를 재사용하고 싶지만, 위와 같은 서브 스키마같은
서브 도큐먼드를 정의하고 싶지 않을 때, SimpleSchema 생성자를 이용하여
조합 할 수 있다.
cmsBaseSchema = new SimpleSchema({ ... });
cmsPageSchema = new SimpleSchema([cmsBaseSchema, {additionalField: {type: String} }]);
SimpleSchemas 추출
------------------
간혹 무척 큰 SimpleSchema 오브젝트에서, 스키마의 일부만 뽑아 새로운 스키마를
정의하고 싶을 때가 있다.
이런 경우 얻고 싶은 스키마의 키들을 배열로 지정하고,
pick 메쏘드를 사용하면 된다.
var profileSchema = new SimpleSchema({
firstName: {type: String},
lastName: {type: String},
username: {type: String}
});
var nameSchema = profileSchema.pick(['firstName', 'lastName']);
유효성을 검사 대상이 되는 오브젝트
--------------------------------------------------------------------------------------
유효성 검사 대상의 오브젝트는 일반적인 오브젝트거나 몽고 modifier 오브젝트( $set 대상, 기타 키)
다.
다시 말해, Collection.insert() 또는 Collection.update()함수의 대상이 되는 오브젝트들이 처리
대상이다.
스키마 키
--------------------------------------------------------------------------------------
기본적인 스키마 키는 유효성 검사가 되어질 오브젝트에서 예상되는 키(속성)의 이름이다
그렇지만 필요하다면 중첩된 배열이나 오브젝트를 검사하기 위해서 몽고 스타일의 도트 표기형
문자열을 사용 할수 있다.
예를 들면 :
MySchema = new SimpleSchema({
"mailingAddress.street": {
type: String
},
"mailingAddress.city": {
type: String
}
});
배열에 대한 표기는 $를 사용한다.
MySchema = new SimpleSchema({
"addresses.$.street": {
type: String
},
"addresses.$.city": {
type: String
}
});
위의 예에서는
mailingAddress 오브젝트나 addresses 배열, 혹은 addresses.$ 오브젝트는 분명히 정의하지 않았다
이것은 암묵적으로 정의 되어 지기 때문에 큰 문제는 없다.
그렇지만 이렇게 암묵적으로 정의된 오브젝트 및 오브젝트의 배열은 옵션화 된다는 점에 주의해야 한다.
이말은
오브젝트 자체가 도큐먼트에 존재하거나 검사되어지는 modifier 일 경우에 해당 속성이 적용된다는
뜻이다.
보통, 스키마에 오브젝트와 오브젝트 배열을 명시적으로 정의하면 깔끔하다.
다음은 최소,최대 배열 갯수를 가지고 있고, 사용 될 오브젝트 배열을 명시적으로 정의한 예이다
MySchema = new SimpleSchema({
addresses: {
type: [Object],
minCount: 1,
maxCount: 4
},
"addresses.$.street": {
type: String
},
"addresses.$.city": {
type: String
}
});
스키마 규칙
--------------------------------------------------------------------------------------
스키마에 적용할수 있는 다양한 규칙에 대해서 기술한다.
type
----
type에는 다음과 같은 표준 자바스크립트 오브젝트 타입을 사용할 수 있다.
* String
* Number
* Boolean
* Object
이것 말고 Date 같은 생성자 함수나 사용자 정의 오브젝트도 사용할 수 있다.
다른 형식으로 배열임을 표시하고 싶다면 '[]' 를 사용하여 아래와 같이 표기하면된다.
* [String]
* [Number]
* [Boolean]
* [Object]
* [Date]
label
-----
유효성 검사 오류 메시지는 label 필드에 정의된 문자열을 이용한다.
label이 따로 정의 되어 있지 않다면 (역자 주:영어에 한해서)
디폴트로 키 이름을 사람이 이해할 수 있도록 바꾸어 사용한다.
예를 들어, 키 이름이 "firstName" 이라면 "First name"으로 바꾸어
label의 값으로 사용한다.
만약 상황에 따라서 label의 값이 달라지도록 처리하고 싶다면
콜백함수를 정의하여 처리할 수 있다.
MySchema = new SimpleSchema({
firstName: {
type: String,
label: function () {
return Session.get("lang") == "de"
? "Vorname" : "first name";
}
}
});
또 다른 사용법으로
동작 중에 하나 혹은 그 이상의 라벨을 변경하려면 labels() 메소드를 사용하면 된다.
MySchema.labels({
password: "Enter your password"
});
이 메소드는 반응형 라벨을 만든다.
어떤 필드의 라벨을 구하려면, MySchema.label(fieldName)를 사용한다.
이 메소드는 사용가능한 문자열을 반환한다.
이 메소드도 반응형이다.
optional
--------
삽입 및 업데이트시에 스키마에 정의된 키에 해당하는 데이터를 요구하는 것이 디폴트 동작이다.
만약 요구 조건에서 제외 하려면 optional 필드를 true 로 설정한다.
그런데 복잡한 키들을 처리하는 경우에 '요구 조건'이 뭔지를 이해하기란 어렵다.
아래는 요구 조건이 어떻게 해석되는지에 대한 간단한 설명이다.
* 만약 type이 Array이거나 배열오브젝트([]로 표현되는)가 요구 된다는 의미는
해당 키가 반드시 값을 가져야 한다는 것을 의미하지만, 빈 배열일 경우는 상관없다.
(만약 빈 배열이 문제가 된다면 "minCount: 1" 옵션을 추가 한다. )
* 배열안에 항목이 있거나 "$"으로 키 이름이 끝날 때, optional 옵션은 효과가 없다.
즉, 뭔가가 배열로 존재하면 요구되는 조건에 부합 되지 않는다.
* 키가 깊은 하위 레벨에서 요구되고, 속하는 오브젝트가 존재해야만 키는 반드시 값을 가지게 된다.
유효성 검사가 되어지는 오브젝트가 Mongo modifier 오브젝트이면,
유효성 검사 에러에 대한 요구나 키 결과에 대한 설정을 취소하거나 null 바꾼다.
마지막 설명은 좀 이해하기 어려울 수 있는데
다음 두 개의 예제를 살펴 보자 :
* "friends.address"은 옵션이어야 하고
"friends.address.city" 은 유효성 검사 대상이어야 한다고 하자.
만약 유효성 검사 대상 오브젝트에 "friends.address"을 설정되어 있고,
"friends.address.city" 은 그렇지 않다면, 유효성 검사 에러가 발생한다.
반면에, "friends.address"은 설정되어 있다면,
"friends.address.city" 에 대한 유효성 검사 에러는 발생할 수 없다.
왜냐하면 해당 오브젝트는 존재하지 않기 때문이다.
* "friends.$.name" 이란 유효성 검사 대상 키가 요구되고,
유효성 검사 대상 오브젝트 안에 어떤 오브젝트도 friends 배열이 가지고 있지 않으면,
"friends.$.name"에 대한 유효성 검사 에러는 발생하지 않는다.
friends 배열이 오브젝트를 가지고 있지 않으면, 모든 존재하는 오브젝트는 유효하다,
그리고 name 속성이 빠졌다면 각 오브젝트는 잠재적으로 유효성 검사 에러를 갖게된다.
예를 들어,
friends 배열안에 두개의 오브젝트가 있고 , 두개 다 name 속성이 빠졌다면,
"friends.0.name" 와 "friends.1.name" 둘 다 유효성 검사 에러가 발생할 것이다.
min/max
-------
* type 이 Number 또는 [Number]라면, 최소,최대 수치값을 정의한다.
* type 이 String 또는 [String]이라면 문자열의 최소, 최대 길이를 정의한다.
* type 이 Date 또는 [Date] 라면 포함되는 최소,최대 날짜를 정의한다.
이 필드의 값으로 인자가 필요 없은 최소,최대 값을 반환하는 함수를 사용할 수 있는데
이 방식은 무척 유용하다. 필드에 대한 최소 Date 에 "today" 같은 것을 사용할 수 있기 때문이다.
exclusiveMin/exclusiveMax
-------------------------
이 옵션을 true 로 설정하면 min/max 로 설정된 수치 값의 범위를 배타적으로 적용한다는 것을 표시한다.
디폴트는 false 이고 , 범위 적용이 포함 관계가 된다.
decimal
-------
type 이 Number 이거나 [Number] 이지만 이 필드의 값이 정수이외 값을 허용하기를 원한다면
decimal 옵션을 true 로 설정한다. 디폴트는 false 이다.
minCount/maxCount
-----------------
최소 또는 최대 배열 길이를 정의한다. type이 배열 값이거나 Array일 때만 사용된다
allowedValues
-------------
배열에 허용되는 값을들을 지정한다. 키의 값에 이 값들 중 하나가 아닐때는 무효 처리된다.
regEx
-----
키에 대한 유효성 검사를 위한 매칭되어야 할 정규식을 지정한다.
정규식 배열일 경우에는 순서대로 테스트 된다.
SimpleSchema.RegEx 오브젝트는 regEx 에 값으로 사용할 수 있는 몇가지 표준 정규식을 가지고 있다.
TLD :
* SimpleSchema.RegEx.Email 은 .com 같은 TLD(Top Level Domain)가 요구되는 전자 메일에 대한 정규식이다.
* SimpleSchema.RegEx.Domain 은 .com 같은 TLD 가 요구되는 도메인에 대한 정규식이다.
* SimpleSchema.RegEx.WeakDomain 은 최소의 정확한 도메인 및 IPv4와 IPv6 에 대한 정규식이다.
* SimpleSchema.RegEx.IP 은 IPv4 또는IPv6 에 대한 정규식이다.
* SimpleSchema.RegEx.IPv4 은 IPv4에 대한 정규식이다.
* SimpleSchema.RegEx.IPv6 은 IPv6에 대한 정규식이다.
* SimpleSchema.RegEx.Url 은 HTTP, HTTPS 및 FTP 의 URL에 대한 정규식이다.
* SimpleSchema.RegEx.Id 은 random 패키지의 Random.id()가 발생한 id 에 대한 정규식이다.
이것은 id와 연관성 검사를 위해서 사용 가능하다.
* SimpleSchema.RegEx.ZipCode 은 5,9 자리 우편번호에 대한 정규식이다.
부담 없이 더 필요한 것들을 요청하기 바란다.
AutoForm 을 사용하여 구현된 e-mail 또는 url 의 유효성 검사를 사용한다면,
폼 입력은 기본적으로 email 또는 url 타입이 될 것이다.
blackbox
--------
오브젝트 타입의 키를 사용 하는 경우 역시 오브젝트의 속성은 검사 될 것이다.
이럴 경우에 스키마에 관련된 모든 속성을 정의해야만 한다
이렇게 하는 것이 가능하지 않거나 오브젝트의 속성을 검사하지 않으려면,
blackbox 옵션을 true 로 설정하여 오브젝트 안에 모든 유효성 검사를 생략하면된다.
사용자 정의 오브젝트는 디폴트로 blackbox 오브젝트로 처리되어진다
그러나, collection2 를 사용할 경우라면, 클라이언트와 서버사이에서
사용자 정의 오브젝트 타입을 잃어 버리지 않도록 조심해야 한다.
일반적 오브젝트를 사용자 정의 오브젝트로 바꾸는 작업은 변환 함수를
이용하면 된다.
이런 변환없이, 클라이언트 측에서 삽입과 업데이트 처리는
클라이언트에서는 성공할 수 있지만 서버에서는 실패한다.
사용자 정의 타입을 읽어 버리는 것에 대하여 신경 쓰고 싶지 않다면,
변환처리를 사용하는 대신에 사용자 정의 오브젝트 타입에 대하여
"blackbox: true" 를 사용하면 된다.
trim
----
키의 문자열 값에 앞뒤 공백을 제거되기 원하지 않으면 trim 을 false로 설정한다.
(즉, 앞 과 뒤 공백이 유지되어야 한다면).
이렇게 하지 않으면, 모든 문자열은 mySimpleSchema.clean() 함수를 호출 할 때
앞 뒤 공백이 제거된다.
custom
------
사용자 지정 유효성 검사 섹션을 참조할 것.
defaultValue
------------
오브젝트에 필드가 포함되지 않았거나 undefined 로 선언되었을때 ,
필드를 자동으로 포함하고 해당 필드의 값으로 설정되기를 원하는 값을 설정한다.
이 값은 mySimpleSchema.clean() 를 호출할때 오브젝트에 삽입될 것이다.
규정되지 않은 오브젝트를 정리할때만 디폴트값으로 설정 된다.
다음과 같은 점이 혼동될 수 있음에 주의 할 것:
* 디폴트 값 자체는 정리되지 않는다. 예를 들면, 디폴트 값이 "" 라면
정리 과정에서 removeEmptyStrings() 함수가 수행될 때 이 값은 제거되지 않을 것이다.
* 설정된 값이 없다면 디폴트 값은 항상 추가된다.
옵션 처리된 오브젝트의 자식 속성이거나, 존재하지 않는 옵션 처리된 오브젝트라도,
해당 속성은 추가될 것이고, 그 속성은 디폴트 값으로 설정되어질 것이다
사실상, 하나의 오브젝트의 속성으로 디폴트 값이 제공되면, 그 오브젝트의 모든 속성에
대한 디폴트 값으로 제공되거나 유효성 검사 오류를 혼동할 위험을 감수해야 한다는 의미이다
더 많은 제어가 필요한 경우에는, autoValue 옵션을 대신 사용 해야 한다.
autoValue
---------
autoValue 옵션은 mySimpleSchema.clean() 처리 과정에서 호출되어
필요에 따라 정리될 오브젝트의 속성값을 바꾸기 위한 함수를 정의할 수 있도록 한다.
이것은 오브젝트에 있는 다른 필드의 값을 바탕으로 내부적으로 원하는 값이나 디폴트 값을
설정할 수 있게 해주는 강력한 기능이다
autoValue 함수는 도큐먼트나 modifier를 전달된 인수로 받는다.
그러나 특별한 경우가 아니라면 이것을 사용할 경우는 없다.
대신, 함수 컨텍스트는 반환 시켜야 할 것을 처리하기 위한 다양한 속성과 메소드를 제공한다.
autoValue 함수가 아무것도 돌려주지 않는 경우(즉, undefined를 반환한다.)에,
필드의 값은 도큐먼트든 modifier 든 지정할 수 있는 무언가가 되어야 한다.
만약 필드가 도큐먼트 나 modifier 에 이미 있다면,
도큐먼트 나 modifier 에 같은 값을 유지할 것이다.
도큐먼트 나 modifier 에 필드가 없다면 이 값은 유지되지 않는다.
도큐먼트 나 modifier에서 필드가 필요가 없어, 제거하려면 this.unset() 을 반드시 호출해야 한다.
어떤 다른 반환 값은 필드의 값을 사용할 수 있다.
업데이트 수행에 대하여 특별한 유사 modifier 오브젝트를 반환할 수 있다.
{$inc: 1} 와 {$push: new Date}가 그 예이다.
autoValue 함수에 대하여 이런것이 가능한 속성과 메소드를 나열하였다.
* isSet: 필드가 도큐먼트나 modifier에 이미 설정되어 있으면 이 값은 true이다.
* unset(): undefined 를 반환했을 때 원래값이 사용되는 것을 금지하기 위해서 이 메소드를 호출한다.
* value: isSet 가 true 인 경우, 도큐먼트나 modifier 에 필드의 현재값을 갖는다.
* operator: isSet 가 true 이고 isUpdate 가 true 이면
이것은 이 필드가 바뀌고 있을 때 modifier 의 업데이트 연산자의 이름을 갖는다.
예를 들어, modifier가 {$set: {name: "Alice"}} 였다며,
name 필드에 대한 autoValue 함수에서,
this.isSet 는 true 가 되고 ,
this.value 는 "Alice" 가 되고,
this.operator는 "$set"이 될것이다.
* field(): 다른 필드의 정보를 얻으려면 이 메소드를 사용한다.
필드 이름만을 인수로 (스키마 키)를 전달한다.
반환하는 오브젝트는 해당 필드에 대한 isSet,value, operator 속성를 가진다.
* siblingField(): 같은 부모 오브젝트를 가지는 다른 필드에 대한 정보를 얻기 위해이 메소드를 사용한다.
field()와 동일하게 동작한다.
하위 스키마를 사용할 때나 오브젝트의 배열을 처리하는 경우에 유용하다.
사용 예는 aldeed:collection2 패키지 문서를 참조 할 것.
데이터 정리
--------------------------------------------------------------------------------------
SimpleSchema 인스턴스는 여러가지 방법으로 데이터를 정리하거나 변경하는 정리 메쏘드를 제공한다.
사전에 피할 수 있는 유효성 검사 에러들을 미리 피하기 위해서 유효성 검사를 사전에 호출하려는 것이다.
정리 메소드는 첫번째 아규먼트엔 정리될 오브젝트를 지정하고,
두번째 아규먼트에는 다음과 같은 선택 옵션을 지정한다.
* filter : 스키마에 발견되지 않는 속성을 필터링 할것인가에 대한 유무. 디폴트는 True 이다.
* autoConvert : 가능한 경우에 올바른 형식으로 속성 타입을 변환 처리 할 것인가에 대한 유무.
디폴트는 True 이다.
* removeEmptyStrings : 일반적인 오브젝트나 $set 안에 빈 문자열의 값을 갖는 키를 제거할 것인가에 대한 유무.
디폴트는 True 이다.
* trimStrings : 문자열 값의 앞 뒤 공백을 삭제 할 것인가에 대한 유무. 디폴트는 True 이다.
* getAutoValues : autoValue 함수를 실행하고 자동화된 값이나 defaultValue 값을 삽입할 것인가의 유무.
디폴트는 True 이다.
* isModifier : 첫 번째 인수가 modifier 오브젝트인가에 대한 판단값 ? 디폴트는 False 이다.
* extendAutoValueContext: autoValue 함수의 컨텍스에 추가될 오브젝트를 지정한다.
기타 주의 점 :
* 정리되는 오브젝트는 원본이다. 즉, 참조 된 원본 오브젝트가 정리된다.
정리 메쏘드의 반환값을 사용해서는 안된다.
* 필터는 명시적이든 묵시적이든 스키마가 허용하지 않는 모든 키를 제거한다.
유효성을 검사하는 동안 이런 키들에 대해서 에러가 발생하는 것을 방지한다.
* autoConvert는 값의 자동 변환이 가능하다면 값을 변환 처리하여 불필요한 검사 메시지가
발생하지 않도록 하는데 도움이 된다
예를 들어, 스키마가 문자열을 기대하고 있다면 비문자열을 문자열로 변환하며
스키마가 숫자를 기대하면 문자열을 숫자로 변환한다.
* extendAutoValueContext는 userId 같은 추가적인 중요한 정보를 autoValue 함수에
전달하기 위해 사용 될수 있다.
( Collection2 패키지가 자동으로 이미 autoValue 컨텍스트에 사용자 ID를 추가하여
사용하는 것에 주의할 것.)
mySchema.clean(obj);
// obj가 내부적으로 즉시 변경된다.
참고 : Collection2 패키지는 항상 모든 삽입, 업데이트, 업썰트 전에 정리를 호출한다.
데이터 유효성 검사
--------------------------------------------------------------------------------------
스키마에 대해서 오브젝트 유효성 검사를 하기전에 SimpleSchema에서 새로운 유효성 검사
컨텍스트를 얻어야 한다.
검사 컨텍스트는 각각의 오브젝트들에 대한 유효성 상태를 검사하고 체크하기 위해서 반응형
메소드를 제공한다.
명명된 검사 컨텍스트
-------------------------
가급적 명명된 유효성 검사 컨텍스트를 사용하는 것이 좋다.
이런 방법은, 컨텍스트는 이름에 의해 자동적으로 유지되고, 컨텍스트의 반응형 메소드를 쉽게
연결 지어 생각할수 있다.
명명된 검사 컨텍스트를 얻으려면 namedContext(name)를 호출한다.
var ss = new SimpleSchema({
requiredString: {
type: String
}
});
var ssContext1 = ss.namedContext("userForm");
초기에 정확한 이름을 지정하여, 컨텍스트를 요청할 때 생성된다.
namedContext() 으로 호출하는 것은 namedContext("default")로 호출하는 것과 같다.
이름 없는 유효성 검사 컨텍스트
------------------------------
이름 없는 검사 컨텍스트를 얻으려면 newContext()를 호출한다.
var ss = new SimpleSchema({
requiredString: {
type: String
}
});
var ssContext1 = ss.newContext();
이름 없는 검사 컨텍스트는 어디에도 유지되지 않는다.
도큐먼트가 유효한지 아니면 해당 컨텍스트에 대한 어떤 반응형 메소드가 필요없는지 확인할
필요가있을 때 유용하다.
오브젝트의 유효성 검사
--------------------
검사 컨텍스트에서 스키마에 대한 오브젝트를 검사하려면 myContext.validate(obj, options)를 호출한다.
이 메소드는 스키마에 근거하여 오브젝트가 유효하다면 true 를 반환하고 그렇지 않다면 false 를 반환한다.
또한 컨텍스트 오브젝트안에 유효하지 않은 필드의 목록과 관련된 에러 메세지를 저장하고,
반응형 메소드를 동작 시킨다.
validate()를 과정을 통과한 오브젝트에 대한 유효함이 발견되었다면
그 결과를 보기 위해 myContext.isValid() 함수를 호출 할수 있다.
이 함수는 true 또는 false 를 반환하는 반응형 메소드이다.
옵션 목록은 검사 옵션 섹션을 참조할 것.
Object내에 하나의 키만 검사
------------------------------------
하나의 키에 대해서만 유효성을 검사할 필요가 있을때가 있다.
이런 경우, myContext.validateOne(obj, key, options)를 사용하면 된다.
이것은 검사되어질 지정된 스키마 키만 제외하고, 유효성 검사 메소드와 같은 방식으로 동작한다.
이것은 반응할 모든 반응성 메소드를 동작시킬지도 모른다.
이 메소드는 스키마에 근거해서 기술된 키가 유효하다면 true를 반환하고
그렇지 않다면 false 를 반환한다.
검사 옵션
------------------
validate() 와 validateOne()은 다음과 같은 옵션을 받아들인다.
* modifier : Mongo의 modifier 오브젝트를 검사하고 있는가의 여부 ? 디폴트는 false 이다.
* upsert : 내부적으로 upsert 연산자를 포함하고 있는 modifier 오브젝트를 검사하고
있는가의 여부 ? 디폴트는 false 이다.
* extendedCustomContext :이 오브젝트는 검사시에 실행되는 사용자 정의 유효성 검사 함수의
컨텍스트에 추가된다. 사용자 정의 유효성 검사 섹션을 참조할 것.
check() 또는 Match.test()를 사용한 유효성 검사
----------------------------------------------
스키마는 Check 패키지에서 미티어의 check() 와 Match.test() 메소드의 두번째 인자로
전달될 수 있다.
첫 번째 인수로 지정된 오브젝트가 스키마에 따라 유효하지 않으면
check() 함수는 Match.Error를 발생시킨다.
var mySchema = new SimpleSchema({name: {type: String}});
Match.test({name: "Steve"}, mySchema); // true 반환
Match.test({admin: true}, mySchema); // false 반환
check({admin: true}, mySchema); // Match.Error 발생
사용자 작성 유효성 검사
-----------------------
사용자가 작성한 유효성 검사 메서드를 연결하는 세 가지 방법이 있다.
* SimpleSchema.addValidator(myFunction) 함수를 사용하여
정의된 모든 스키마의 키들 대해 호출될 사용자 정의 유효성 검사 함수를 추가한다.
* mySimpleSchema.addValidator(myFunction) 함수를 사용하여
특정 SimpleSchema 인스턴스의 모든 키에 대해 호출될 사용자 정의 유효성 검사 함수를 추가한다.
* 해당 키에 정의된 시키마의 custom 옵션을 사용하여
특정 스키마의 특정 키에 대해 호출될 사용자 정의 유효성 검사 함수를 추가한다.
모든 사용자 정의 유효성 검사 함수는 동일한 방식으로 작동하고 같은 컨텍스트를 가진다.
* 필요한 사용자 정의 유효성 검사를 수행하고,
값이 유효하지 않다고 판단 되면 에러 타입을 나타내는 문자열을 반환한다.
반환된 값이 문자열이 아닌 경우는 값이 유효하다는 것을 의미한다.
* 에러 타입 문자열은 내장 문자열 또는 원하는 문자열 중 하나이다.
여러분은 사용자 정의 문자열을 반환하는 경우에는 보통 해당 메세지를 정의하고 싶어질 것이다.
* 함수 내에서는 다음 속성들을 포함한다.
- 키 : 스키마 키의 이름 (예: "addresses.0.street")
- genericKey : 스키마 키의 일반 이름 (예 : "addresses.$.street")
- definition : 스키마 정의 오브젝트.
- isSet : 유효한 오브젝트가 키 집합을 가지고 있는가에 대한 여부
- value : 검사하기 위한 값
- operator : 우리는 검사을 하고 있는 것에 대한 Mongo 연산자. 대부분 null 이다.
- field() : 다른 필드의 정보를 얻으려면 이 메소드를 사용한다.
필드 이름만을 인수로 (비 범용 스키마 키)를 전달한다.
반환하는 오브젝트는 해당 필드에 대한 isSet,value, operator 속성를 가진다.
- siblingField() : 같은 부모 오브젝트를 가지는 다른 필드에 대한 정보를 얻기 위해이 메소드를 사용한다.
field()와 동일하게 동작한다.
하위 스키마를 사용할 때나 오브젝트의 배열을 처리하는 경우에 유용하다.
주: 서버에서 일부 사용자 정의 유효성 검사를 하거나 클라이언트 뒤쪽에서 에러를 표시할 필요가 있으면,
클라이언트 섹션에 기술한 비동기 사용자 정의 유효성 검사편을 참조 할 것.
수동으로 유효성 검사 에러 추가
----------------------------------
임시 검사 에러를 반응형으로 표출하고 싶고, 사용자 작성 유효성 검사 함수를 사용할수 없다면
(어쩌면 onSubmit() 함수를 호출하거나 비동기적으로 결과를 기다리는 것 같은 상황),
myContext.addInvalidKeys(errors) 메소드를 사용하여
언제든지 유효성 검사 컨택스트에 하나 이상의 에러를 추가 할수 있다.
추가 가능한 것은 아래와 같은 형식의 에러 오브젝트 배열이다.
{name: key, type: errorType, value: anyValue}
* name: 스키마에 기술된 스키마 키.
* 유형: 에러 타입. 원하는 문자열 이거나 다음과 같은 내장 문자열 중 하나 :
required
minString
maxString
minNumber
maxNumber
minDate
maxDate
minCount
maxCount
noDecimal
notAllowed
expectedString
expectedNumber
expectedBoolean
expectedArray
expectedObject
expectedConstructor
regEx
* value: 옵션이다. 유효하지 않은 경우의 값.
오류 메시지에 [value]로 표기된 분에 대체하는 것으로 사용된다.
타입에 사용자 정의 문자열을 사용하는 경우,관련 메시지를 꼭 작성 해야 한다.
(사용자 검사 메시지 편을 참조할 것).
예 :
SimpleSchema.messages({wrongPassword: "Wrong password"});
myContext.addInvalidKeys([{name: "password", type: "wrongPassword"}]);
클라이언트측 사용자 정의 비동기적 유효성 검사
--------------------------------------------
유효성 검사는 여러 가지 이유로 동기적으로 수행된다.
거의 대부분 이런 방식으로 동작할 것이다.
이것은 사용자가 정의한 유효성 검사 루틴이 비동기적으로 결과를 기다리도록
만드는 것을 어렵게 한다.
아래 루틴은 각 클라이언트에서 모든 username을 발행하지 않고
클라이언트에서 username이 유일하다는 것을 검사하는 한 가지 방법의 예이다
username: {
type: String,
regEx: /^[a-z0-9A-Z_]{3,15}$/,
unique: true,
custom: function () {
if (Meteor.isClient && this.isSet) {
Meteor.call("accountsIsUsernameAvailable", this.value, function (error, result) {
if (!result) {
Meteor.users.simpleSchema().namedContext("createUserForm").addInvalidKeys([{name: "username", type: "notUnique"}]);
}
});
}
}
}
유의해 볼 점은 "accountsIsUsernameAvailable" 서버 메소드를 호출하고 나서
username 이 사용 가능한가를 표시하는 boolean 타입의 결과를 비동기적으로
기다린다는 점이다.
비동기 콜백이 호출되면 수동으로 "notUnique" 에러와 함께 username 키를 무효화 한다.
이것은 유효성 검사가 동기적이라는 사실을 바꾸지는 않는다.
이런 처리를 autoform 에서 사용하고 유효성 검사 에러가 없는 경우라면,
폼은 그대로 처리될 것이다.
그러나 사용자 생성에 실패하고 1초 또는 2초 뒤에, 폼은 "notUnique" 에러를 표출 할것이고,
그래서 최종 결과는 실제 비동기 유효성 검사 과정과 매우 유사하다.
클라이언트와 서버의 코드에서 비동기 처리가 필요할 경우 위와 같은 방식의 기술을 사용할 수 있다.
기타 검사 컨텍스트 메소드
--------------------------------
무효화된 키 데이터 배열을 얻고 싶다면 myContext.invalidKeys()를 호출한다.
배열 내의 각 오브젝트는 세 개의 키를 갖는다.
* name: 스키마에 지정된 스키마 키.
* type: 에러 타입. 직접 추가한 유효성 검사 에러에 나열된 문자열인 required*, min*, max* 등 중 하나
* message: 에러 메시지.
이 메소드는 반응형 메쏘드이다.
지정된 키가 현재 무효화된 상태라면 myContext.keyIsInvalid(key)는 true를 반환한다.
이 메소드는 반응형 메쏘드이다.
지정된 키가 무효화된 상태라면 myContext.keyErrorMessage(key)는 지정된 키에 대한 에러 메시지를 반환한다.
키가 유효하다면 이 메소드는 빈 문자열을 반환한다.
이 메소드는 반응형 메쏘드이다.
유효성 검사 컨텍스트를 리셋하고, 모든 무효화된 필드 메시지를 지우고 디시 유효하게 만들 필요가 있는 경우,
myContext.resetValidation ()를 호출한다.
기타 SimpleSchema 메쏘드
--------------------------
스키마에 정의된 오브젝트를 얻고 싶다면 MySchema.schema([key])를 호출한다.
키를 지정하면 해당 키에 대한 정의된 스키마를 반환된다.
이 함수를 사용할 때는 반환되는 스키마는 SimpleSchema 생성자에 전달했던 것과
정확이 일치 하지 않을 수 있음에 유의해야 한다.
내부적으로 스키마에 정의된 오브젝트는 표준화되고,
이 메소드는 표준화 된 오브젝트를 복사해 반환한다.
유효성 검사 메시지 사용자 정의
--------------------------------------------------------------------------------------
유효성 검사 메시지처리를 사용자가 정의한것으로 바꾸려면,
SimpleSchema.messages() 또는 mySimpleSchemaInstance.messages() 에
메시지 오브젝트를 적용한다.
전역 메세지 보다 기술된 인스턴스 메세지가 우선적으로 적용된다.
메시지 오브젝트의 형식은 다음과 같다.
{
errorType: message
}
특정 필드들에 대한 메세지를 재 정의 할수 있다.
{
"errorType schemaKey": message
}
regEx 에러 타입에 대해서는 반드시 메세지 오브젝트 배열 형태로 기술되어야 한다.
{
"regEx": [
{msg: "Default Message"},
{exp: SimpleSchema.RegEx.Url, msg: "You call that a URL?"}
],
"regEx schemaKey": [
{exp: SimpleSchema.RegEx.Url, msg: "It's very important that you enter a valid URL here"}
]
}
메시지는 문자열로 구성된다.
문자열안에 대괄호( "[" , "]" )로 둘러 쌓아 지정하여 참조할 수 있는 많은 플레이스홀더들이 있다.
* [label] 은 label 필드의 값으로 대치된다.
* [min] 은 minimum 필드의 값으로 대치된다.(문자열의 길이, 수 또는 날짜)
* [max] ] 은 maximum 필드의 값으로 대치된다. (문자열의 길이, 번호 또는 날짜)
* [minCount] 은 minimum 필드의 배열 갯수 값으로 대치된다.
* [maxCount] 은 maximum 필드의 배열 갯수 값으로 대치된다.
* [value] 은 유효하지 않지만 저장된 값들로 대치된다. (모든 에러 타입에 적용되지는 않는다.)
* [type] 은 예상되는 타입으로 대치된다. expectedConstructor 에러 타입 처리에 쓰면 좋다.
한 예로써,
아래는 디폴트 에러 메시지를 직접 정의하는 경우 어떤 식이 될지를 볼 수 있다.
SimpleSchema.messages({
required: "[label] is required",
minString: "[label] must be at least [min] characters",
maxString: "[label] cannot exceed [max] characters",
minNumber: "[label] must be at least [min]",
maxNumber: "[label] cannot exceed [max]",
minDate: "[label] must be on or after [min]",
maxDate: "[label] cannot be after [max]",
minCount: "You must specify at least [minCount] values",
maxCount: "You cannot specify more than [maxCount] values",
noDecimal: "[label] must be an integer",
notAllowed: "[value] is not an allowed value",
expectedString: "[label] must be a string",
expectedNumber: "[label] must be a number",
expectedBoolean: "[label] must be a boolean",
expectedArray: "[label] must be an array",
expectedObject: "[label] must be an object",
expectedConstructor: "[label] must be a [type]",
regEx: [
{msg: "[label] failed regular expression validation"},
{exp: SimpleSchema.RegEx.Email, msg: "[label] must be a valid e-mail address"},
{exp: SimpleSchema.RegEx.WeakEmail, msg: "[label] must be a valid e-mail address"},
{exp: SimpleSchema.RegEx.Domain, msg: "[label] must be a valid domain"},
{exp: SimpleSchema.RegEx.WeakDomain, msg: "[label] must be a valid domain"},
{exp: SimpleSchema.RegEx.IP, msg: "[label] must be a valid IPv4 or IPv6 address"},
{exp: SimpleSchema.RegEx.IPv4, msg: "[label] must be a valid IPv4 address"},
{exp: SimpleSchema.RegEx.IPv6, msg: "[label] must be a valid IPv6 address"},
{exp: SimpleSchema.RegEx.Url, msg: "[label] must be a valid URL"},
{exp: SimpleSchema.RegEx.Id, msg: "[label] must be a valid alphanumeric ID"}
],
keyNotInSchema: "[label] is not allowed by the schema"
});
작성된 메세지의 일관성을 보장하기 위해서 이 메소드는 클라이언트와 서버 모두에서
호출 할 필요가 있다.
이 메소드는 여러번 호출할수 있다.
예를 들면
동작중에 언어를 바꾸면,
이에 반응하여 메세지가 스크린에 변경될 것이다.
시지가 [label] 플레이스홀더를 포함하면, 해당 라벨 이름이 변경될 때도 반응적으로
업데이트 된다.
날짜
--------------------------------------------------------------------------------------
시간의 일관성을 유지하기 위해서,
일반적으로 유효성 검사를 하거나 저장하기 위한 시간들은 UTC 시간대로 설정 한다.
날짜에 대해서만 처리하고자 한다면,
원하는 날짜를 자정 기준의 UTC 시간으로 설정한 Date 오브젝트를 사용하라.
또한 시간 처리가 필요하면,
원하는 시간과 날짜를 UTC 시간으로 설정한 Date 오브젝트를 사용해라.
min 과 max 시간들도 같은 방식으로 처리 할 것
시간의 간격을 다루고 minimum(최소) 시간을 정의 하기 원하면,
min은 minimum(최소) 시간 보다 큰 자정 기준의 UTC 시간대로 설정해야 한다.
이러한 규칙을 따르는 것은, HTML5의 날짜 입력을 시간대가 다른 국가간의 상호 운용성을
보장하며 일반적으로 괜찮은 처리 방식이다.
Collection2 와 AutoForm
--------------------------------------------------------------------------------------
여기에 Collection2 와 AutoForm 패키지에 대한 설명을 다루면 진짜 설명할 분량이 커져 버린다.
각각의 문서를 보기 바란다.
모범 사례 코드 예제
--------------------------------------------------------------------------------------
조건에 따라 유효성 검사 대상으로 결정되는 필드 만들기
-----------------------------------
단지 특정 상황에서만 요구되는 필드가 있는 경우,
먼저 optional 필드를 정의하고,
아래와 유사한 형태의 custom 함수를 정의하여 사용한다.
{
field: {
type: String,
optional: true,
custom: function () {
if (customCondition && !this.isSet && (!this.operator || (this.value === null || this.value === ""))) {
return "required";
}
}
}
}
customCondition 이 뭐가 되었든 해당 필드가 요구되게 만들려면 트리거 되어야 한다.
참고 :
앞으로, true나 false로 반환되는 기능으로 옵션을 처리하게 좀 더 간단한 방식으로 만들 수 있다.
모든 요청을 받아들인다
다른 키에 대한 키의 유효성 검사
--------------------------------
아래는 어떤 값에 대한 유무효의 검사가 다른 값에 기반하고 있을 때 custom 유효성 검사 함수를 사용한 예이다.
SimpleSchema.messages({
"passwordMismatch": "Passwords do not match"
});
MySchema = new SimpleSchema({
password: {
type: String,
label: "Enter a password",
min: 8
},
confirmPassword: {
type: String,
label: "Enter the password again",
min: 8,
custom: function () {
if (this.value !== this.field('password').value) {
return "passwordMismatch";
}
}
}
});
디버그 모드
--------------------------------------------------------------------------------------
모든 명명 된 검사 컨텍스트가 자동으로 브라우저의 콘솔에 모든 잘못된 키 오류를 기록하도록
하기 위해서 명명된 검사 컨텍스트를 생성하기 전에 SimpleSchema.debug = true를 설정한다.
이렇게 하면
개발중에 특정 동작에서 왜 유효성 검사 실패가 발생하였는지를 알아 내는데 도움이 된다.
스키마 옵션 확장
--------------------------------------------------------------------------------------
특별한 경우에 패키지나 앱의 스키마 내에 뭔가 추가적으로 정의하고 싶은 것이 있을 수 있다.
그러나
인식할수 없는 옵션을 스키마에 정의하면 오류가 발생할 것이다.
사용자 정의 옵션을 SimpleSchema 에 지정하고 에러를 회피하기 위해서
SimpleSchema.extendOptions() 메소드를 호출하여야 한다.
이런 예로,
Collection2 패키지가 스키마 옵션을 어떻게 추가하는지 다음에 보여준다.
SimpleSchema.extendOptions({
index: Match.Optional(Match.OneOf(Number, String, Boolean)),
unique: Match.Optional(Boolean),
denyInsert: Match.Optional(Boolean),
denyUpdate: Match.Optional(Boolean)
});
라이센스
--------------------------------------------------------------------------------------
MIT
MIT
기여
--------------------------------------------------------------------------------------
Anyone is welcome to contribute.
기여하는 어떤 분도 환영합니다
Fork, make and test your changes (meteor test-packages ./), and then submit a pull request.
감사
----
(Add your name if it's missing.)
@mquandalle
@Nemo64