! 제품 버전을 정확하게 입력해 주세요.
제품 버전이 정확하게 기재되어 있지 않은 경우,
최신 버전을 기준으로 안내 드리므로
더욱 빠르고 명확한 안내를 위해
제품 버전을 정확하게 입력해 주세요!

Wijmo와 함께 Firestore 사용하기 > 블로그 & Tips

본문 바로가기

Wijmo와 함께 Firestore 사용하기

페이지 정보

작성자 GrapeCity 작성일 2020-05-28 00:00 조회 3,441회 댓글 0건

본문

Firestore는 Google이 새로 출시한 유연하고 확장 가능한 NoSQL 클라우드 데이터베이스입니다. Firestore는 클라이언트 측 및 서버 측 개발을 위해 데이터를 보관하고 동기화하도록 설계되었습니다. Firestore는 Firebase 및 Google 클라우드 플랫폼에서 모바일, 웹 및 서버 개발을 하기 위한 용도의 유연하고 확장 가능한 데이터베이스입니다.

Firestore는 Firebase 실시간 데이터베이스와 마찬가지로 실시간 수신기를 통해 클라이언트 응용 프로그램 전반에 걸쳐 데이터를 동기화된 상태로 유지하며 모바일 및 웹에 오프라인 지원을 제공하므로 네트워크 대기 시간 또는 인터넷 연결성에 상관없이 작동하는 반응형 응용 프로그램을 구축할 수 있습니다.

Firestore는 설정, 사용 및 확장이 매우 쉬우며, 대량 컬렉션에서도 우수한 성능을 제공합니다. 부정적인 측면은 쿼리 용량이 제한적이라는 것입니다.

Wijmo의 Firestore 클래스에서는 Firestore REST API를 사용하므로 Firestore 데이터베이스를 로드, 확인 및 편집할 수 있습니다. Firestore는 가볍고 빠르지만 오프라인 캐싱, 실시간 업데이트와 같이 Firestore 웹 클라이언트 라이브러리가 제공하는 고급 기능은 제공하지 않습니다. 이러한 기능이 필요하거나 웹 클라이언트 라이브러리를 사용하기로 이미 결정하였다면 스냅샷 클래스를 대신 사용할 수 있습니다.

Wijmo 스냅샷 클래스를 이용한 실시간 Firestore 업데이트에 대해 자세히 알아보십시오.

기존 노스윈드(Northwind) 데이터베이스를 바탕으로 한 간단한 예를 통해 Wijmo의 Firestore 클래스를 사용하는 방법에 대해 알아보겠습니다.


데이터베이스 만들기


Firestore 데이터베이스는 매우 쉽게 만들 수 있습니다.

다음과 같이 하기만 하면 됩니다.

  1. Firebase 콘솔로 이동합니다.
  2. 새 프로젝트를 만듭니다(또는 기존 프로젝트를 선택).
  3. 데이터베이스 버튼을 클릭합니다.
  4. Firestore 데이터베이스를 추가합니다.
  5. UI를 사용해 데이터베이스를 구성합니다.

아래와 같이 이 단계를 자세히 설명하는 튜토리얼과 비디오가 많이 있습니다.

샘플 프로젝트를 위해 원래 데이터베이스에서 각 표에 대해 컬렉션을 추가하여 노스윈드(Northwind) 데이터베이스를 만들었습니다.

노스윈드(Northwind) 스프레드시트에서 데이터를 복사하여 Firestore 데이터베이스에 바인딩된 FlexGrid에 붙여넣음으로써 이 컬렉션을 채웠습니다.

Google의 클라우드 셸을 사용하여 데이터를 가져올 수도 있지만, 그렇게 해도 크게 도움이 되지는 않았을 것입니다.

다음은 콘솔의 데이터베이스 스크린샷입니다.


API 키 가져오기

응용 프로그램에는 데이터베이스 액세스를 위한 API 키가 필요합니다. API 키는 호출 응용 프로그램을 식별하기 위해 API로 전달되는 고유한 코드입니다. API 키는 API가 어떻게 사용되고 있는지(예: API의 악의적인 사용 또는 남용 방지 목적으로) 추적하고 제어하기 위해 Firestore가 사용합니다.

앞서 Google API 콘솔에서 만든 API 키를 사용할 것이지만, 다음과 같은 클라우드 데이터스토어토큰 서비스 API를 키 제한 사항 목록에 추가할 것입니다.

Identity Toolkit API는 OAuth2 토큰을 Firebase ID 토큰으로 변환하는 데 필요합니다. 이에 관해서는 아래 "인증 활성화" 섹션에서 자세히 설명하겠습니다. 이 서비스 없이는 응용 프로그램이 Firestore 보안 규칙을 사용할 수 없습니다. 또한 이 서비스에서 액세스 제한 사항을 지정하여 응용 프로그램이 특정 웹 사이트, 서버 또는 응용 프로그램 유형에서만 사용되게 할 수 있습니다.


응용 프로그램에서 Firestore에 액세스하기


현재 데이터베이스와 API 키가 있으므로 Firestore 클래스를 사용하여 데이터베이스에 연결할 수 있습니다.

앞에 나온 예시에서와 같이 단순한 UI를 만들 것입니다. 이 UI를 통해 사용자는 목록에서 제품 범주를 선택할 수 있습니다. 범주를 선택하면 응용 프로그램이 제품 정보가 포함된 그리드와 제품 단가가 포함된 차트를 보여줍니다.

다음과 같이 데이터베이스에 연결된 Firestore 객체를 만드는 것부터 시작하겠습니다.

 const API_KEY = 'AIzaSyCvuXEzP57I5CQ9ifZDG2_K8M3nDa1LOPE';
 const PROJECT_ID = 'test-9c0be';
 let fsNWind = new Firestore(PROJECT_ID, API_KEY, {
     collections: [ 'Products', 'Categories', 'Suppliers' ]
 });

그다음에는 사용자가 제품 범주를 보고 선택할 수 있도록 다음과 같이 ComboBox를 추가해 보겠습니다. 

 let categoryCombo = new ComboBox('#categoryCombo', {
     placeholder: '(All Categories)',
     isRequired: false,
     displayMemberPath: 'CategoryName',
     itemsSource: fsNWind.getCollection('Categories'),
     selectedIndexChanged: (s, e) => {
         let cat = s.selectedItem;
         fsNWind.getSheet('Products').filter = (item => {
             return cat == null || cat.CategoryID == item.CategoryID;
         });
     }
 });

이것은 100% 표준 Wijmo 코드로서, 해당 데이터는 어느 데이터 소스에서도 로드할 수 있습니다.

사용자가 범주를 선택하면 콤보는 "Products" 컬렉션에 필터를 적용하여 해당 범주의 제품만 표시되게 합니다.

다음 코드는 FlexGrid에 제품을 표시하는 데 사용됩니다.

 let supplierMap = new DataMap(fsNWind.getCollection('Suppliers'),
                               'SupplierID', 'CompanyName');
 let productGrid = new FlexGrid('#productGrid', {
     ...gridOptions,
     autoGenerateColumns: false,
     columns: [
         { binding: 'ProductName', header: 'Product Name' },
         { binding: 'UnitPrice', header: 'Unit Price', format: 'n2' },
         { binding: 'QuantityPerUnit', header: 'Quantity Per Unit' },
         { binding: 'SupplierID', header: 'Supplier', dataMap: supplierMap },
         { binding: 'UnitsInStock', header: 'In Stock', format: 'n0' },
         { binding: 'UnitsOnOrder', header: 'On Order', format: 'n0' },
     ],
     itemsSource: fsNWind.getCollection('Products')
 });

위 코드 역시 100% 표준 Wijmo 코드입니다.

DataMap을 "SupplierID" 열에 적용하여 그리드가 공급자 ID 대신에 회사 이름을 표시하게 합니다. DataMap은 "Suppliers" 컬렉션에 따라 달라집니다.

끝으로 제품의 단가를 표시하기 위해 FlexChart를 추가합니다.

 let productChart = new FlexChart('#productChart', {
     chartType: 'Bar',
     axisX: { majorGrid: true, axisLine: false },
     axisY: { majorGrid: false, axisLine: false, reversed: true },
     legend: { position: 'Bottom' },
     bindingX: 'ProductName',
     series: [
         { binding: 'UnitPrice', name: 'Product Unit Prices (US$)' }
     ],
     itemsSource: fsNWind.getCollection('Products')
 });

이제 응용 프로그램이 준비되었습니다.

이 응용 프로그램은 Google Sheets에 기반을 둔 해당 버전과 UI 및 동작이 똑같습니다. 즉 사용자가 범주를 선택하거나 데이터를 정렬하면 그리드와 차트가 자동으로 업데이트됩니다.

하지만 이번에는 응용 프로그램을 실행하기 전에 인증을 활성화해야 합니다.


인증 활성화


인증을 위해 Firestore REST API는 Firebase 인증 ID 토큰 또는 Google ID OAuth 2.0 토큰을 수락합니다.

  • Firebase ID token을 사용하는 경우 Firestore는 클라우드 Firestore 보안 규칙을 사용해 요청이 승인되었는지 여부를 확인합니다. 이 옵션은 유연하고 강력한 Firestore 보안 규칙을 활용하고 Snapshot 클래스의 지원을 받는 유일한 옵션이므로 선호됩니다.
  • Google ID OAuth 2.0 token을 사용하는 경우 Firestore는 클라우드 IAM(Identity and Access Management)을 사용하여 요청이 승인되었는지 여부를 확인합니다. 이 옵션은 Firestore 보안 규칙을 우회하고 IAM 관리자가 사용자에게 부여한 인증을 사용합니다. 이것은 GoogleSheet 클래스가 사용하는 인증과 유사합니다.

이 예시에서는 Firebase ID token을 사용할 것입니다.

앞서 사용한 OAuth2 객체를 사용해도 됩니다.

 const SCOPES = [ 'https://www.googleapis.com/auth/userinfo.email' ];
 let auth = new OAuth2(API_KEY, CLIENT_ID, SCOPES);

 // button to log in/out
 let oAuthBtn = document.getElementById('auth_btn');

 // click button to log user in or out
 oAuthBtn.addEventListener('click', () => {
     if (auth.user) {
         auth.signOut();
     } else {
         auth.signIn();
     }
 });

마치려면 다음과 같이 사용자가 변경할 때 idTokenFirestore 객체에 적용하는 작업도 해야 합니다(OAuth2 토큰을 사용하려면 대신에 accessToken 속성을 설정해야 함). 

// update button/sheet state when user changes  
 auth.userChanged.addHandler(s => {  
     let user = s.user;  

     // update button caption  
     oAuthBtn.textContent = user ? 'Sign Out' : 'Sign In';  

     // update Firestore ID token  
     fsNWind.idToken = user ? s.idToken : null;  
 });

이제 응용 프로그램이 준비되었습니다.

Google Sheet 대신에 Firestore 데이터베이스를 백엔드로 사용하는 것 외에는 첫 번째 버전과 외관 및 동작이 똑같습니다.


변경 사항 커밋


사용자가 항목을 변경, 추가 또는 제거할 때마다 Firestore 클래스는 변경 사항을 데이터 스토어에 즉시 커밋합니다. 기본으로 설정된 이 동작으로 데이터 손실 가능성이 최소화됩니다.

커밋 작업을 연기하고 요구 시 적용하는 것을 선호한다면 CollectiondeferCommits 속성을 true로 설정하고 원할 때마다 commitChanges(또는 cancelChanges) 메서드를 호출하십시오.

예를 들어, 다음 코드에서는 hasPendingChanges 속성을 사용하여 Collection에 보류 중인 변경 사항과 이 변경 사항을 적용하거나 취소할 수 있는 commitChangescancelChanges 메서드가 있는지 확인하는 방법을 보여줍니다.

// get the collection and configure it  
 let collection = fs.getCollection('restaurants');  
 collection.deferCommits = true;  

 // commit/cancel changes buttons  
 let btnCommit = document.getElementById('btn-commit') as HTMLButtonElement,  
     btnCancel = document.getElementById('btn-cancel') as HTMLButtonElement;  

 // commit or cancel pending changes  
 btnCommit.addEventListener('click', () => collection.commitChanges());  
 btnCancel.addEventListener('click', () => collection.cancelChanges());  

 // enable buttons when there are pending changes  
 collection.hasPendingChangesChanged.addHandler((s, e) => {  
     btnCommit.disabled = btnCancel.disabled = !collection.hasPendingChanges;  
 });


로드할 데이터의 양 제한하기

지금까지는 전체 컬렉션을 한 번에 로드해 왔습니다. 이러한 방식은 항목이 수천 개정도 되는 비교적 소규모의 컬렉션에서는 제대로 작동합니다.

그러나 Firebase 컬렉션에 수백만 개 또는 수십억 개의 항목이 포함될 수 있으므로 데이터의 양을 제한하여 사용자가 관심 있는 것만 로드할 방법이 필요합니다. 범위를 좁혀 필요한 데이터만 가져오면 사용자에게 더 친숙해질 뿐 아니라 더 효율적이고 저렴한(클라우드 서비스가 항상 무료인 것은 아님) 응용 프로그램이 될 수 있습니다.

다음 세 가지 방법으로 Collection 개체로 로드되는 데이터의 양을 간단하게 제한할 수 있습니다.

  1. fields 속성을 사용하여 로드하려는 필드를 지정합니다. 이 옵션은 컬렉션에 많은 필드가 포함되어 있는데 몇 가지에만 관심이 있는 경우 유용할 수 있습니다. 필드의 하위 집합만 가져오는 기능은 SQL 데이터베이스, OData 소스, graphQL에서 사용할 수 있습니다.
  2. pageSize 속성을 적당한 수의 레코드로 설정하고(예를 들면 10 또는 20) pageOnServer 속성을 true로 설정해야 합니다. 이렇게 하면 Collection이 한 번에 몇 개의 레코드만 로드하게 되고, pageIndex 속성을 사용하여 한 번에 한 페이지씩 데이터를 탐색할 수 있습니다.
  3. where 메서드를 사용하여 서버 측 필터를 적용합니다. 예를 들어, 한 국가나 두 국가에서만 고객을 확인하고 싶은 경우가 있습니다.

위의 세 가지 옵션을 결합하여 동시에 사용할 수도 있습니다.

예를 들어, 아래 코드에서는 고객이 포함된 컬렉션을 로드합니다. 선택된 몇 개의 필드만 검색되고 한 번에 여섯 명의 고객만 로드됩니다.

// load the Customers collection  
 let customers = new Collection(fsNWind, 'Customers', {  
     sortDescriptions: ['CustomerID'],  
     fields: [ 'CustomerID', 'CompanyName', 'ContactName', 'City', 'Country' ],  
     pageOnServer: true,  
     pageSize: 6 // load only six customers per page  
 });

사용자가 국가를 기준으로 데이터를 필터링할 수 있게 허용해 보겠습니다. 또한 ComboBox를 사용하여 사용자가 관심 있는 국가를 선택할 수 있게 할 것입니다. 

let cmbCountries = new ComboBox('#cmbCountries', {  
     placeholder: '(Select a Country)',  
     itemsSource: 'Brazil,France,Germany,UK,USA'.split(','),  
     isRequired: false,  
     text: '',  
     textChanged: (s, e) => {  
         customers.where('Country', '==', s.text);  
     }  
 });

사용자가 국가를 선택하면 textChanged 이벤트가 시작되고, 코드는 queryFilter 속성을 업데이트하여 선택한 국가의 모든 고객을 보여줍니다.

이 데이터를 표시하기 위해 다음과 같이 CollectionViewPagerFlexGrid를 사용해 보겠습니다.

let fsCustomerPager = new CollectionViewNavigator('#fsCustomerPager', {  
     cv: customers,  
     byPage: true,  
     headerFormat: 'Page {current:n0}'  
 });  
 let fsCustomerGrid = new FlexGrid('#fsCustomerGrid', {  
     showMarquee: true,  
     formatItem: addRowHeaderIndex,  
     autoGenerateColumns: false,  
     columns: customers.fields.map(fld => {  
         return { binding: fld }  
     }),  
     itemsSource: customers  
 });

응용 프로그램은 다음과 같은 모습입니다.

현재 선택한 국가의 고객을 한 번에 여섯 명씩 보여줍니다. 사용자는 그리드 위에 있는 탐색기 컨트롤을 사용해 현재 페이지를 전환할 수 있습니다.

데이터베이스에는 현재 약 100명의 고객이 있지만, 1억 명이 있다 해도 이 응용 프로그램은 정상적으로 작동할 것입니다. 한 번에 최대 여섯 명(또는 선택한 페이지 크기)만 로드됩니다.


단순 및 복합 쿼리 수행


Firestore는 기존 데이터베이스에 비해 효율적이지만 다소 제한적인 쿼리 기능을 제공합니다.

서버 측 필터를 적용하려면 where 메서드를 사용하여 필터링할 필드, 적용할 연산자, 필터링 기준으로 사용할 값을 지정하십시오.

예를 들어 Country 필드가 "Brazil(브라질)"로 설정된 항목을 가져오려면 다음 코드를 사용할 수 있습니다.

customers.where('Country''==''Brazil');

Country 필드가 "Brazil(브라질)" 또는 "Argentina(아르헨티나)"로 설정된 항목을 가져오려면 다음 코드를 사용할 수 있습니다. 

customers.where('Country''IN', ['Brazil''Argentina');

여러 호출을 where 메서드에 연결하여 복합 필터를 만들 수 있습니다. 예를 들어 Country 필드가 "Brazil(브라질)"로 설정되어 있고 Sales 1000보다 큰 항목을 가져오려면 다음 코드를 사용할 수 있습니다. 

  customers  
     .where('Country', '==', 'Brazil')  
     .where('Sales', '>', 1000);</pre>

이 코드는 간단하고 효율적이지만 제한 사항이 있습니다. 예를 들어 복합 필터는 개별 필터를 'AND' 연산과 결합합니다. Country가 "Brazil(브라질)"로 설정되어 있거나 Sales 1000보다 큰 항목을 가져오는 쿼리는 작성할 수 없습니다.

또한 같음(==)과 범위 연산자(>, >=, <, <=)를 결합하는 경우 복합 인덱스를 만들어야 합니다. 범위 연산자는 여러 필드에 사용할 수 없습니다. 다름 또는 전체 텍스트 검색을 위한 연산자는 없습니다.

이러한 제한 사항은 서버 쿼리에만 적용됩니다. 데이터를 다운로드하는 경우 클라이언트에서 어떤 필터링 작업도 원하는 대로 수행할 수 있습니다.

Firestore 데이터베이스 쿼리에 대한 자세한 내용은 Google 문서에서 클라우드 Firestore에서 단순 및 복합 쿼리 수행하기 주제를 참조하십시오.


라이브 데모 실행



Firestore 실시간 API


이 예시에서는 지금까지 경량화 및 단순화를 위해 Firestore REST API를 사용하였습니다. 하지만 Firestore는 클라이언트 SDK에서 실시간 업데이트, 오프라인 저장소와 같은 추가 기능도 다수 제공합니다. Firestore는 둘 다 지원해 드립니다! 실시간 업데이트를 위한 Firestore Snapshot 클래스 사용에 대해 자세히 알아보십시오.

  • 페이스북으로 공유
  • 트위터로  공유
  • 링크 복사
  • 카카오톡으로 보내기

댓글목록

등록된 댓글이 없습니다.

메시어스 홈페이지를 통해 제품에 대해서 더 자세히 알아 보세요!
홈페이지 바로가기

태그1

인기글

더보기
  • 인기 게시물이 없습니다.
메시어스 홈페이지를 통해 제품에 대해서 더 자세히 알아 보세요!
홈페이지 바로가기
이메일 : sales-kor@mescius.com | 전화 : 1670-0583 | 경기도 과천시 과천대로 7길 33, 디테크타워 B동 1107호 메시어스(주) 대표자 : 허경명 | 사업자등록번호 : 123-84-00981 | 통신판매업신고번호 : 2013-경기안양-00331 ⓒ 2024 MESCIUS inc. All rights reserved.