저는 최근에 카우치베이스 밋업 캘리포니아 마운틴뷰에서 네이티브스크립트, 앵귤러 및 NoSQL 개발을 주제로 한 세미나를 개최했습니다. 특별한 게스트와 함께, TJ VanToll 에서 모바일 애플리케이션 개발과 그 방법에 대해 논의했습니다. 카우치베이스 를 포함할 수 있으며, NoSQL 스토리지 및 데이터 동기화를 위해 포함할 수 있습니다.
행사 참여율이 높았고, 많은 분들의 요청에 따라 Couchbase 프로젝트를 가능하게 하는 데 사용된 코드를 공유하고 검토하고 싶었습니다.
컴퓨터에 NativeScript CLI와 Xcode 또는 Android SDK가 설치 및 구성되어 있다고 가정하면 명령 프롬프트 또는 터미널에서 새 프로젝트를 만들 수 있습니다:
1 |
tns create couchbase-project --ng |
그리고 --ng
플래그를 사용하면 Core 프로젝트가 아닌 Angular 프로젝트를 생성하고 있음을 나타냅니다.
우리가 만드는 프로젝트는 두 개의 페이지와 데이터 서비스로 구성됩니다.
애플리케이션 내에서 데이터베이스에 저장된 동영상 목록을 표시하고 해당 데이터베이스에 동영상을 추가할 수 있습니다. 이 모든 것은 데이터 서비스를 통해 관리됩니다. 카우치베이스 동기화 게이트웨이를 사용하면 동기화를 수행할 수 있습니다.
새 NativeScript 프로젝트에 다음 디렉터리와 파일을 추가합니다:
1 2 3 4 5 6 7 8 |
mkdir -p app/components/create mkdir -p 앱/컴포넌트/목록 mkdir -p app/providers 터치 앱/컴포넌트/create/create.component.ts 터치 앱/컴포넌트/create/create.component.html 터치 앱/컴포넌트/목록/목록.component.ts 터치 앱/컴포넌트/목록/목록.component.html 앱/공급자/데이터베이스.service.ts를 터치합니다. |
Angular 개발에서 각 컴포넌트에는 TypeScript 및 HTML 파일이 있습니다. 각 서비스에는 TypeScript 파일만 있습니다.
로컬에 설치된 Couchbase Lite 데이터베이스와의 상호 작용을 처리할 데이터 서비스를 설계하는 것부터 시작해 보겠습니다. 프로젝트의 앱/공급자/데이터베이스.service.ts 파일을 열고 다음을 포함하세요:
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 |
"@angular/core"에서 { 인젝터블, 이벤트이미터 }를 가져옵니다; "nativescript-couchbase"에서 { Couchbase }를 가져옵니다; @Injectable() 데이터베이스 서비스 클래스 내보내기 { 비공개 데이터베이스: 임의; private pushReplicator: any; private pullReplicator: any; 프라이빗 리스너입니다: 이벤트이미터 = 새로운 이벤트이미터(); public constructor() { this.database = 새 카우치베이스("movie-db"); this.database.createView("movies", "1", function(document, emitter) { if(document.type == "movie") { emitter.emit(document._id, document); } }); } public query(viewName: 문자열): Array { this.database.executeQuery(viewName)를 반환합니다; } public startReplication(게이트웨이: 문자열, 버킷: 문자열) { this.pushReplicator = this.database.createPushReplication("http://" + 게이트웨이 + ":4984/" + 버킷); this.pullReplicator = this.database.createPullReplication("http://" + 게이트웨이 + ":4984/" + 버킷); this.pushReplicator.setContinuous(true); this.pullReplicator.setContinuous(true); this.database.addDatabaseChangeListener(changes => { 이.리스너.emit(변경사항); }); this.pushReplicator.start(); this.pullReplicator.start(); } public getDatabase() { this.database를 반환합니다; } public getChangeListener() { 이.리스너를 반환합니다; } } |
위의 서비스에는 많은 일이 일어나고 있으므로 이를 세분화해야 합니다.
모든 컴포넌트 종속성을 가져오고 변수를 정의한 후, 우리는 생성자
메서드를 사용합니다:
1 2 3 4 5 6 7 8 |
public constructor() { this.database = 새 카우치베이스("movie-db"); this.database.createView("movies", "1", function(document, emitter) { if(document.type == "movie") { emitter.emit(document._id, document); } }); } |
에서 생성자
메서드를 사용하여 Couchbase NoSQL 데이터베이스를 생성하고 열고 데이터 쿼리에 사용할 보기를 만듭니다. 이 보기 로직은 쿼리 시 이름이 유형
와 같은 영화
. 이 조건과 일치하지 않는 다른 문서는 결과에 포함되지 않습니다.
1 2 3 |
public query(viewName: 문자열): Array { this.database.executeQuery(viewName)를 반환합니다; } |
뷰를 쿼리할 때 화면에 표시하도록 선택할 수 있는 결과 배열을 받게 됩니다. 이 작업은 적절한 컴포넌트에서 수행할 것입니다.
Couchbase의 강력하고 놀라운 기능을 활용하기 위해 애플리케이션 내에서 복제/동기화 기능을 지원하고자 합니다. 애플리케이션 내에서 시작 복제
메서드를 사용하면 다음과 같습니다:
1 2 3 4 5 6 7 8 9 10 11 |
public startReplication(게이트웨이: 문자열, 버킷: 문자열) { this.pushReplicator = this.database.createPushReplication("http://" + 게이트웨이 + ":4984/" + 버킷); this.pullReplicator = this.database.createPullReplication("http://" + 게이트웨이 + ":4984/" + 버킷); this.pushReplicator.setContinuous(true); this.pullReplicator.setContinuous(true); this.database.addDatabaseChangeListener(changes => { 이.리스너.emit(변경사항); }); this.pushReplicator.start(); this.pullReplicator.start(); } |
카우치베이스 동기화 게이트웨이 인스턴스에 대한 정보를 제공하면 양방향으로 데이터를 지속적으로 복제할 수 있습니다. 모바일 애플리케이션은 원격 데이터를 읽지 않으므로 로컬 데이터가 변경되면 변경 리스너를 설정합니다. 이러한 변경 사항은 Angular 이미터를 통해 방출됩니다.
이 데이터 서비스를 각 컴포넌트에 주입하려면 프로젝트의 @NgModule
블록을 클릭합니다. 프로젝트의 앱/앱.모듈.ts 파일을 열고 다음과 같이 만듭니다:
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 |
"@angular/core"에서 { NgModule, NO_ERRORS_SCHEMA }를 가져옵니다; "nativescript-angular/nativescript.module"에서 { NativeScriptModule }을 가져옵니다; "nativescript-angular/forms"에서 { NativeScriptFormsModule }을 가져옵니다; "./app.routing"에서 { AppRoutingModule }을 가져옵니다; "./app.component"에서 { AppComponent }를 가져옵니다; "./components/list/list.component"에서 { ListComponent }를 가져옵니다; "./components/create/create.component"에서 { CreateComponent }를 가져옵니다; "./providers/database.service"에서 { DatabaseService }를 가져옵니다; @NgModule({ 부트스트랩: [ 앱 컴포넌트 ], 수입: [ NativeScriptModule, NativeScriptFormsModule, 앱 라우팅 모듈 ], 선언: [ 앱 컴포넌트, ListComponent, 컴포넌트 생성 ], 공급자: [데이터베이스 서비스], 스키마: [ no_errors_schema ] }) 내보내기 클래스 AppModule { } |
이 서비스는 가져와서 공급자
배열의 @NgModule
블록을 추가했습니다. 한발 앞서서 저희가 만들고 있는 각 컴포넌트도 가져왔습니다.
이제 데이터베이스에 새 동영상을 추가하는 컴포넌트로 이동해 보겠습니다. 프로젝트의 앱/컴포넌트/컴포넌트 만들기/컴포넌트 만들기.ts 파일을 열고 다음 TypeScript 코드를 포함합니다:
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 |
"@angular/core"에서 { Component }를 가져옵니다; "@angular/common"에서 { Location }을 가져옵니다; "../../providers/database.service"에서 { DatabaseService }를 가져옵니다; 컴포넌트({ moduleId: module.id, 선택기: "ns-create", templateUrl: "create.component.html", }) CreateComponent 클래스 내보내기 { 비공개 데이터베이스: 임의; 공개 의견: 모든; public constructor(private location: Location, private couchbase: DatabaseService) { this.database = this.couchbase.getDatabase(); this.input = { "title": "", "장르": "", "type": "영화" } } public save() { if(this.input.title && this.input.genre) { this.database.createDocument(this.input); this.location.back(); } } } |
위 코드에서 우리는 데이터베이스 서비스
와 함께 이전에 생성된 Angular 위치
서비스. 서비스 사용 데이터베이스 서비스
를 사용하여 데이터베이스 인스턴스를 가져와서 입력
이 반대할 때 저장
메서드가 호출됩니다. 메서드의 입력
객체가 UI의 양식에 바인딩됩니다.
이 컴포넌트에 대한 UI는 프로젝트의 앱/컴포넌트/컴포넌트 만들기/컴포넌트 만들기.html file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<ActionBar title="{N} Couchbase Example"> <ActionItem text="Save" ios.position="right" (tap)="save()"></ActionItem> </ActionBar> <StackLayout class="form"> <StackLayout class="input-field"> <TextField class="input" [(ngModel)]="input.title"></TextField> <StackLayout class="hr-light"></StackLayout> </StackLayout> <StackLayout class="input-field"> 레이블>레이블> <TextField class="input" [(ngModel)]="input.genre"></TextField> <StackLayout class="hr-light"></StackLayout> </StackLayout> </StackLayout> |
위의 XML에서 두 개의 텍스트 필드
태그는 입력
변수를 통해 ngModel
속성을 사용합니다.
네이티브 스크립트 애플리케이션의 마지막 부분은 데이터베이스에 있는 동영상을 나열하는 것입니다. 프로젝트의 앱/컴포넌트/목록/목록.component.ts 파일을 열고 다음 TypeScript 코드를 포함합니다:
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 |
"@angular/core"에서 { Component, NgZone, OnInit }을 가져옵니다; "@angular/common"에서 { Location }을 가져옵니다; "플랫폼"에서 { isAndroid }를 가져옵니다; "../../providers/database.service"에서 { DatabaseService }를 가져옵니다; 컴포넌트({ moduleId: module.id, 선택기: "ns-list", templateUrl: "list.component.html", }) 내보내기 클래스 ListComponent는 OnInit을 구현합니다. 공개 영화: 배열; 공개 생성자(비공개 위치: 위치, 개인 영역: NgZone, 비공개 카우치베이스: DatabaseService) { this.movies = []; } public ngOnInit() { this.location.subscribe(() => { this.movies = this.couchbase.query("movies"); }); this.movies = this.couchbase.query("movies"); this.couchbase.startReplication(isAndroid ? "10.0.2.2" : "localhost", "movie-db"); this.couchbase.getChangeListener().subscribe(data => {}) for (let i = 0; i < data.length; i++) { let documentId = data[i].getDocumentId(); let document = this.couchbase.getDatabase().getDocument(documentId); this.zone.run(() => { this.movies.push(document); }); } }); } } |
다시 말하지만, 우리는 데이터베이스 서비스
, 위치
및 NgZone
서비스를 구성 요소의 생성자
메서드를 사용합니다.
에 데이터를 로드하는 것은 결코 좋은 생각이 아닙니다. 생성자
메서드를 사용하므로 ngOnInit
메서드를 대신 사용합니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public ngOnInit() { this.location.subscribe(() => { this.movies = this.couchbase.query("movies"); }); this.movies = this.couchbase.query("movies"); this.couchbase.startReplication(isAndroid ? "10.0.2.2" : "localhost", "movie-db"); this.couchbase.getChangeListener().subscribe(data => {}) for (let i = 0; i < data.length; i++) { let documentId = data[i].getDocumentId(); let document = this.couchbase.getDatabase().getDocument(documentId); this.zone.run(() => { this.movies.push(document); }); } }); } |
몇 가지 일이 일어나고 있습니다. ngOnInit
메서드를 사용할 수 있습니다. 데이터베이스에서 데이터를 로드하고 싶지만 두 가지 방법으로 로드해야 합니다. 애플리케이션이 열릴 때 데이터를 로드해야 하고, 생성 화면에서 뒤로 이동할 때 데이터를 로드해야 합니다.
왜냐하면 ngOnInit
메서드가 뒤로 탐색할 때 트리거되지 않으므로 위치 이벤트를 구독해야 합니다. 두 시나리오 모두에서 생성한 뷰를 쿼리합니다.
동기화 지원이 필요하기 때문에 시작 복제
서비스에 접속하여 동기화 게이트웨이 정보를 전달합니다. 로컬에서 테스트하는 경우 Android 및 iOS에 적합한 호스트 정보를 제공해야 합니다.
변경 사항을 수신하는 동안 들어오는 모든 데이터를 ID로 조회하여 목록에 추가해야 합니다.
동영상을 나열하기 위한 컴포넌트와 페어링되는 UI는 다음에서 찾을 수 있습니다. 앱/컴포넌트/목록/목록.component.html file:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<ActionBar title="{N} Couchbase Example"> <ActionItem text="Add" ios.position="right" [nsRouterLink]="['/create']"></ActionItem> </ActionBar> <그리드 레이아웃 <ListView [items]="movies" class="list-group"> <ng-template let-movie="item"> <StackLayout class="list-group-item"> </StackLayout> </ng-template> </ListView> </GridLayout> |
위의 XML에는 간단한 ListView
여기서 각 행에는 Couchbase에 저장하고 있는 객체의 정보가 들어 있습니다.
네이티브 스크립트 애플리케이션을 마무리하려면 탐색을 담당하는 라우팅 파일을 수정해야 합니다. 프로젝트의 앱/앱.라우팅.ts 파일을 열고 다음 TypeScript를 포함합니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
"@angular/core"에서 { NgModule }을 가져옵니다; "nativescript-angular/router"에서 { NativeScriptRouterModule }을 가져옵니다; "@angular/router"에서 { Routes }를 가져옵니다; "./components/list/list.component"에서 { ListComponent }를 가져옵니다; "./components/create/create.component"에서 { CreateComponent }를 가져옵니다; const 경로: Routes = [ { 경로: "", redirectTo: "/list", pathMatch: "full" }, { 경로: "목록", 컴포넌트: ListComponent }, { 경로: "create", component: CreateComponent } ]; @NgModule({ 임포트: [NativeScriptRouterModule.forRoot(routes)], 내보내기: [네이티브스크립트 라우터 모듈] }) 내보내기 클래스 AppRoutingModule { } |
위 코드에서는 두 컴포넌트만 가져와서 애플리케이션 내에서 가능한 경로로 나열하고 있습니다. Angular 애플리케이션에서 NativeScript를 사용한 라우팅에 대한 자세한 내용은 이전 글에서 확인할 수 있습니다, Angular 라우터로 네이티브스크립트 앱 탐색하기.
우리 프로젝트는 네이티브스크립트뿐만 아니라 별도의 엔티티인 동기화 게이트웨이로 구성되어 있다는 것을 기억하세요. 동기화 작동 방식에 대한 구성 파일을 정의해야 합니다.
라는 파일을 만듭니다, 동기화 게이트웨이-config.json 를 클릭하고 다음을 포함합니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
{ "log":["CRUD+", "REST+", "Changes+", "Attach+"], "데이터베이스": { "movie-db": { "서버":"월러스:데이터", "sync":` 함수 (문서) { 채널(doc.channels); } `, "users": { "GUEST": { "disabled": false, "admin_channels": ["*"] } } } } } |
카우치베이스 동기화 게이트웨이를 시작할 때 위의 구성을 사용해야 합니다. 이는 데이터 동기화를 통해 수행할 수 있는 작업의 기본적인 예시일 뿐입니다.
결론
저는 개인적으로 네이티브 스크립트 는 모바일 개발을 위한 훌륭한 기술입니다. 커뮤니티에서 지원하는 네이티브스크립트용 카우치베이스 플러그인을 사용하면 애플리케이션 내에 NoSQL 및 데이터 동기화 지원을 포함할 수 있습니다.
현재 등록되어 있지 않은 경우 카우치베이스 실리콘밸리 그룹에 속해 있고 마운틴뷰 지역에 계신다면 잠시 시간을 내어 등록하는 것이 좋습니다. NativeScript를 사용한 Couchbase가 실제로 작동하는 모습을 더 자세히 보고 싶으시다면 제가 작성한 이전 글을 살펴보시기 바랍니다. 여기.
카우치베이스 라이트에 대한 자세한 내용은 다음을 참조하세요. 카우치베이스 개발자 포털.