우리의 커뮤니티 게스트 게시물 의 출처는 조엘 앤드류스. 조엘은 비가 많이 내리는 캐나다 서부 해안에 거주하는 다국어 개발자이다. 그는 백엔드 개발자, 데이터베이스 관리자, DevOps 담당자, 제품 소유자, 때때로 웹 및 Android 프론트엔드 개발자 등 다양한 역할을 맡고 있으며, Kashoo에서 다양한 업무를 수행하고 있습니다. 그는 다음 분야에 대한 깊은 애정을 가지고 있습니다. 카우치베이스 (특히 카우치베이스 모바일) 데이터 스토리지 솔루션의 장단점을 논의할 때 완전히 편향되지 않습니다.
클라이언트 및 서버 구성요소로 시스템을 구축할 때는 클라이언트가 서버에 저장하려는 데이터의 유효성을 검사하고 권한이 있는 사람만 데이터를 보거나 수정할 수 있도록 하는 것이 중요합니다. 그렇지 않으면 악의적인 클라이언트가 시스템을 악용하여 온갖 끔찍한 일을 저지를 수 있습니다. 그렇기 때문에 카슈는 여러 모바일 장치와 웹 애플리케이션 간에 데이터를 동기화하기 위해 Couchbase Mobile과 Sync Gateway를 사용하기 시작하면서 모든 문서 속성과 이를 읽고, 만들고, 바꾸고, 삭제하는 데 필요한 권한(즉, 채널)에 대한 포괄적인 검증을 수행하도록 동기화 기능을 구축했습니다.
유연성 동기화 게이트웨이의 동기화 기능 API 은 축복이자 저주가 될 수 있습니다. 몇 가지 문서 유형만 있는 단순한 버킷으로 시작할 때는 정리와 유지 관리가 그리 어렵지 않았고, 유효성 검사도 충분히 수행할 수 있었습니다. 하지만 점점 더 많은 문서 유형을 추가하면서 동기화 함수의 크기와 복잡성이 걷잡을 수 없이 커졌습니다. 포괄적인 유효성 검사를 수행하는 동기화 함수를 작성하는 일은 문서 유형이 추가될수록, 즉 코드에 어떤 구조를 적용하기 시작하지 않으면 점점 더 관리하기 어려워집니다.
이로 인해 동기화 게이트웨이 데이터베이스의 동기화 기능을 네 가지 주요 단계로 나누게 되었습니다:
-
문서의 유형 파악
-
사용자가 작업을 수행하는 데 필요한 채널 중 하나에 속해 있는지 확인합니다.
-
각 문서 속성의 유효성 검사
-
문서에 채널 할당하기
이는 두 번째 동기화 게이트웨이 데이터베이스를 도입하기 전까지는 잘 작동했습니다. 동기화 함수는 외부 라이브러리를 동적으로 로드하는 기능이 없는 단일 코드 블록으로 정의되기 때문에 첫 번째 데이터베이스의 동기화 함수를 위해 만들었던 대략적인 프레임워크를 두 번째 데이터베이스의 동기화 함수에 복제했습니다. 그러나 개발자로서 이러한 코드 복제는 한 동기화 기능을 개선할 때 변경 사항을 다른 동기화 기능에 수동으로 포팅해야 하거나 기능 면에서 서로 점차 차이가 나기 때문에 마음에 들지 않았습니다.
따라서 저희는 대략적인 프레임워크를 코드 복제 없이 동기화 게이트웨이 데이터베이스 간에 공유할 수 있는 독립형 도구로 더욱 발전시키기로 결정했습니다. 동기화 게이트웨이의 동기화 함수 API는 외부 라이브러리의 사용을 허용하지 않기 때문에 동적 링크가 아닌 코드 생성 방식을 택했습니다. 문서 유형 정의를 JavaScript 객체로 작성한 다음 유틸리티를 사용하여 해당 정의를 미리 생성된 템플릿으로 가져와 일관된 독립적인 동기화 함수를 만들 수 있습니다.
이제 문서 유형(또는 "스키마")을 매우 선언적인 방식으로 정의할 수 있게 되어 코드 작성보다는 구성 작성에 가깝고 문서 유형 정의가 실제로 권한 부여, 유효성 검사 및 채널 할당을 수행하는 코드와 완전히 독립적으로 유지될 수 있게 되었습니다. 이로써 이전에 필요했던 코드 중복을 상당 부분 제거할 수 있었습니다. 그리고 그것은 우리에게 매우 효과적이었습니다. 실제로 너무 잘 작동해서 다음과 같이 결정했습니다. 릴리스 그리고 다른 사람들이 우리의 노력을 중복하지 않도록 이 유틸리티를 오픈 소스 소프트웨어로 지원하기로 했습니다. 이 유틸리티는 synctos라고 불리며, 현재 매우 허용적인 MIT 라이선스에 따라 사용할 수 있습니다.
초기 출시 이후 기능을 확장하여 현재는 기존 4단계가 아닌 5단계로 실행되며 각 단계가 훨씬 더 강력해졌습니다:
-
문서의 유형 파악
-
다음을 결정하여 사용자에게 권한을 부여합니다.
-
사용자가 작업을 수행하는 데 필요한 채널 중 하나에 속해 있는 경우
-
사용자가 작업 수행에 필요한 역할 중 하나에 속하는 경우
-
사용자에게 작업을 수행할 수 있는 권한이 명시적으로 부여된 경우
-
-
각 문서 속성의 유효성 검사
-
액세스 권한을 할당합니다:
-
채널에 사용자 및/또는 역할 추가
-
역할에 사용자 추가
-
-
문서에 채널 할당하기
다음은 문서 유형 정의 예시를 통해 synctos가 어떤 기능을 제공하는지 알 수 있습니다:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
{ // A request/requisition for payment of an invoice paymentRequisition: { // Determine whether the document is of this type typeFilter: function(doc, oldDoc) { return doc.type === 'paymentRequisition' || oldDoc.type === 'paymentRequisition'; }, // The channels that the document will be assigned to. // In order for a user to perform each operation, it must belong to at least one of the listed channels for that operation type. channels: { add: [ 'create-payment-requisition' ], replace: [ 'replace-payment-requisition' ], remove: [ 'remove-payment-requisition' ] }, // Define what is expected of each of the properties that belong to this document type propertyValidators: { type: { // The document's type type: 'string', required: true, immutable: true }, businessId: { // The ID of the business with which the payment requisition is associated type: 'integer', required: true, immutable: true, minimumValue: 1 }, invoiceRecordId: { // The ID of the invoice with which the payment requisition is associated type: 'integer', required: true, immutable: true, minimumValue: 1 }, issuedAt: { // When the payment requisition was sent/issued type: 'datetime', immutable: true }, issuedByUserId: { // The ID of the user that issued the payment requisition type: 'string', immutable: true, mustNotBeEmpty: true }, invoiceRecipients: { // Who received the payment requisition type: 'string' } } } } |
싱크토스는 다음을 사용하여 쉽게 시작할 수 있습니다. npm (의 패키지 관리자 Node.js). 빈 디렉터리에서 다음을 실행합니다:
|
1 |
npm install synctos |
이렇게 하면 최신 버전의 synctos가 로컬 node_modules 디렉토리에 다운로드됩니다. synctos가 다운로드되었으므로 이제 위의 문서 정의 예제를 "example-doc-definitions.js"라는 파일에 저장하면 synctos를 사용하여 이 파일에서 동기화 함수를 생성할 수 있습니다:
node_modules/synctos/make-sync-function ./example-doc-definitions.js ./example-generated-sync-function.js
그러면 텍스트 편집기에서 "example-generated-sync-function.js"를 열면 알 수 있듯이 synctos의 사전 정의된 템플릿과 제공한 문서 정의를 결합하여 완전히 독립적인 동기화 함수가 생성되었을 것입니다. 그런 다음 생성된 동기화 함수를 동기화 게이트웨이 구성 파일에 그대로 삽입할 수 있습니다.
다음은 인메모리 인스턴스를 사용하는 간단한 동기화 게이트웨이 예제 구성입니다. Walrus 데이터베이스 엔진을 추가하여 Couchbase Server 버킷을 설정하지 않고도 동기화 기능을 사용해 볼 수 있습니다. 문자열 "%GENERATED_SYNC_FUNCTION%"를 이전 단계에서 생성한 동기화 기능으로 대체합니다. 백틱/백따옴표(`) 동기화 함수를 둘러싸고 있는 사용자 지정 추가는 동기화 게이트웨이에서 여러 줄의 문자열을 허용하는 JSON 형식에 추가됩니다. 구성 파일.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
{ "databases": { "synctos-test": { "server": "walrus:", "users": { "my-user": { "admin_channels": [ "create-payment-requisition", "replace-payment-requisition" ], "password": "password" } }, "sync": `%GENERATED_SYNC_FUNCTION%` } } } |
위의 동기화 게이트웨이 구성을 "example-sync-gateway-config.json"으로 저장한 다음 새 구성으로 동기화 게이트웨이를 실행합니다:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
/path/to/sync_gateway ./example-sync-gateway-config.json Now use a tool like curl to create a new instance of the "paymentRequisition" document type. For example: curl -X PUT -u "my-user:password" -H "Content-Type: application/json" -d '{ "type": "paymentRequisition", "businessId": 15, "invoiceRecordId": 79, "issuedAt": "2017-01-11T18:21:18-0800", "issuedByUserId": "my-user", "invoiceRecipients": "foo@example.com,bar@example.com" }' "https://localhost:4984/synctos-test/myDoc1" The response will indicate success: {"id":"myDoc1","ok":true,"rev":"1-ed7b6831f4339188eee412082d44ca32"} |
유효한 문서를 만드는 것은 좋지만 그 문서를 문서 정의에 위배되는 문서로 바꾸려고 하면 어떻게 될까요? 다음 예에서는 "businessId" 속성 값이 원래 값인 15에서 수정되었는데, 이는 문서 정의에서 이 속성이 "변경 불가능"으로 표시되었기 때문에 문제가 됩니다.
|
1 2 3 4 5 6 7 8 |
curl -X PUT -u "my-user:password" -H "Content-Type: application/json" -d '{ "type": "paymentRequisition", "businessId": 99999, "invoiceRecordId": 79, "issuedAt": "2017-01-11T18:21:18-0800", "issuedByUserId": "my-user", "invoiceRecipients": "new-email@example.com" }' "https://localhost:4984/synctos-test/myDoc1?rev=1-ed7b6831f4339188eee412082d44ca32" |
응답은 오류입니다:
|
1 |
{"error":"Forbidden","reason":"Invalid paymentRequisition document: value of item "businessId" may not be modified"} |
보시다시피 synctos는 문서 수정본을 작성하려고 할 때 무엇이 잘못되었는지 쉽게 파악할 수 있도록 자세한 오류 메시지를 생성합니다. 이것은 하나의 유효성 검사 오류만 있는 간단한 예시이지만 문서에 여러 오류가 포함된 경우 응답의 오류 메시지에 추가 오류가 각각 열거됩니다.
사용자가 속해 있지 않은 채널이 필요한 작업을 수행하려고 하면 어떻게 되나요? 동기화 게이트웨이 구성에서 정의한 사용자는 '제거-결제-요건' 채널에 속하지 않으므로 앞서 만든 문서를 제거할 수 없습니다.
|
1 2 3 |
curl -X DELETE -u "my-user:password" "https://localhost:4984/synctos-test/myDoc1?rev=1-ed7b6831f4339188eee412082d44ca32" And indeed the response indicates that the user does not belong to the necessary channel: {"error":"Forbidden","reason":"missing channel access"} |
사용자 및 역할에 액세스 권한 할당, 동기화 함수의 각 단계 후 사용자 지정 작업 실행, 내장된 테스트 모듈을 사용하여 생성된 동기화 함수의 유효성 검사 등 동기화에는 훨씬 더 많은 기능이 있지만, 이 글을 통해 동기화의 기능과 문서를 종합적으로 검증하는 동기화 게이트웨이 동기화 기능을 작성하는 데 도움이 될 수 있는 방법을 맛보셨기를 바랍니다. 프로젝트 설명서를 참조하세요. GitHub 또는 npm 에서 자세한 내용을 확인하세요.