1. 시작하기 전에
Firebase 확장 프로그램은 HTTP 요청 또는 다른 Firebase 및 Firebase 클라우드 메시징, Cloud Firestore, Pub/Sub와 같은 Google 제품의 트리거 이벤트에 대한 응답으로 특정 태스크 또는 태스크 세트를 수행합니다.
빌드할 항목
이 Codelab에서는 geohashing을 위한 Firebase 확장 프로그램을 빌드합니다. 배포된 후 확장 프로그램은 Firestore 이벤트에 대한 응답으로 또는 호출 가능한 함수 호출을 통해 X 및 Y 좌표를 지오해시로 변환합니다. 이는 데이터를 저장하기 위해 모든 대상 플랫폼에 geofire 라이브러리를 구현하는 대안으로 사용할 수 있으므로 시간을 절약할 수 있습니다.
학습 내용
- 기존 Cloud Functions 코드를 배포 가능한 Firebase 확장 프로그램으로 변환하는 방법
extension.yaml
파일 설정 방법- 확장 프로그램에 민감한 문자열 (API 키)을 저장하는 방법
- 확장 프로그램 개발자가 필요에 맞게 확장 프로그램을 구성할 수 있도록 허용하는 방법
- 확장 프로그램 테스트 및 배포 방법
필요한 사항
- Firebase CLI (설치 및 로그인)
- Google 계정(예: Gmail 계정)
- Node.js 및
npm
- 원하는 개발 환경
2. 설정
코드 가져오기
이 확장 프로그램에 필요한 모든 항목은 GitHub 저장소에 있습니다. 시작하려면 코드를 가져와 선호하는 개발 환경에서 엽니다.
- 다운로드한 ZIP 파일의 압축을 해제합니다.
- 필요한 종속 항목을 설치하려면
functions
디렉터리에서 터미널을 열고npm install
명령어를 실행합니다.
Firebase 설정
이 Codelab에서는 Firebase 에뮬레이터를 사용하는 것이 좋습니다. 실제 Firebase 프로젝트로 확장 프로그램 개발을 사용해 보려면 Firebase 프로젝트 만들기를 참고하세요. 이 Codelab에서는 Cloud Functions를 사용하므로 에뮬레이터가 아닌 실제 Firebase 프로젝트를 사용하는 경우 Blaze 요금제로 업그레이드해야 합니다.
건너뛰고 싶으신가요?
Codelab의 완료된 버전을 다운로드할 수 있습니다. 진행 중에 문제가 발생하거나 완성된 확장 프로그램의 모양을 보려면 GitHub 저장소의 codelab-end
브랜치를 확인하거나 완성된 ZIP을 다운로드하세요.
3. 코드 검토
- ZIP 파일에서
index.ts
파일을 엽니다. 안에 두 개의 Cloud Functions 선언이 포함된 것을 볼 수 있습니다.
이러한 함수의 기능은 무엇인가요?
이 데모 함수는 지오해싱에 사용됩니다. 좌표 쌍을 가져와서 Firestore의 지역 쿼리에 최적화된 형식으로 변환합니다. 이 함수는 확장 프로그램에서 민감한 데이터 유형을 처리하는 방법을 자세히 알아볼 수 있도록 API 호출 사용을 시뮬레이션합니다. 자세한 내용은 Firestore의 데이터에서 지역 쿼리 실행에 대한 문서를 참조하세요.
함수 상수
상수는 index.ts
파일 상단에서 초기에 선언됩니다. 이러한 상수 중 일부는 확장 프로그램의 정의된 트리거에서 참조됩니다.
index.ts
import {firestore} from "firebase-functions";
import {initializeApp} from "firebase-admin/app";
import {GeoHashService, ResultStatusCode} from "./fake-geohash-service";
import {onCall} from "firebase-functions/v1/https";
import {fieldValueExists} from "./utils";
const documentPath = "users/{uid}";
const xField = "xv";
const yField = "yv";
const apiKey = "1234567890";
const outputField = "hash";
initializeApp();
const service = new GeoHashService(apiKey);
Firestore 트리거
index.ts
파일의 첫 번째 함수는 다음과 같습니다.
index.ts
export const locationUpdate = firestore.document(documentPath)
.onWrite((change) => {
// item deleted
if (change.after == null) {
return 0;
}
// double check that both values exist for computation
if (
!fieldValueExists(change.after.data(), xField) ||
!fieldValueExists(change.after.data(), yField)
) {
return 0;
}
const x: number = change.after.data()![xField];
const y: number = change.after.data()![yField];
const hash = service.convertToHash(x, y);
// This is to check whether the hash value has changed. If
// it hasn't, you don't want to write to the document again as it
// would create a recursive write loop.
if (fieldValueExists(change.after.data(), outputField)
&& change.after.data()![outputField] == hash) {
return 0;
}
return change.after.ref
.update(
{
[outputField]: hash.hash,
}
);
});
이 함수는 Firestore 트리거입니다. 데이터베이스에서 쓰기 이벤트가 발생하면 함수는 xv
필드와 yv
필드를 검색하여 해당 이벤트에 반응하고, 두 필드가 모두 있으면 geohash를 계산하여 지정된 문서 출력 위치에 출력을 씁니다. 입력 문서는 users/{uid}
상수로 정의됩니다. 즉, 이 함수는 users/
컬렉션에 작성된 모든 문서를 읽은 다음 해당 문서의 지오해시를 처리합니다. 그런 다음 동일한 문서의 해시 필드에 해시를 출력합니다.
호출 가능 함수
index.ts
파일의 다음 함수는 다음과 같습니다.
index.ts
export const callableHash = onCall((data, context) => {
if (context.auth == undefined) {
return {error: "Only authorized users are allowed to call this endpoint"};
}
const x = data[xField];
const y = data[yField];
if (x == undefined || y == undefined) {
return {error: "Either x or y parameter was not declared"};
}
const result = service.convertToHash(x, y);
if (result.status != ResultStatusCode.ok) {
return {error: `Something went wrong ${result.message}`};
}
return {result: result.hash};
});
onCall
함수를 확인합니다. 이 함수가 클라이언트 애플리케이션 코드 내에서 호출할 수 있는 호출 가능한 함수임을 나타냅니다. 이 호출 가능한 함수는 x
및 y
매개변수를 사용하고 geohash를 반환합니다. 이 함수는 이 Codelab에서 직접 호출되지 않지만 여기서는 Firebase 확장 프로그램에서 구성할 항목의 예로 포함되어 있습니다.
4. extension.yaml 파일 설정
이제 확장 프로그램의 Cloud Functions 코드가 무엇을 하는지 알았으므로 배포할 수 있도록 패키징할 준비가 되었습니다. 모든 Firebase 확장 프로그램에는 확장 프로그램의 기능과 작동 방식을 설명하는 extension.yaml
파일이 함께 제공됩니다.
extension.yaml
파일에는 확장 프로그램에 대한 초기 메타데이터가 필요합니다. 다음 단계를 통해 모든 필드의 의미와 필드가 필요한 이유를 이해할 수 있습니다.
- 앞서 다운로드한 프로젝트의 루트 디렉터리에
extension.yaml
파일을 만듭니다. 먼저 다음을 추가합니다.
name: geohash-ext
version: 0.0.1
specVersion: v1beta # Firebase Extensions specification version (do not edit)
확장 프로그램의 이름은 확장 프로그램의 인스턴스 ID의 기반으로 사용됩니다. 사용자는 확장 프로그램의 인스턴스를 여러 개 설치할 수 있으며 각 인스턴스에는 고유한 ID가 있습니다. 그러면 Firebase에서 인스턴스 ID를 사용하여 확장 프로그램의 서비스 계정 이름과 확장 프로그램별 리소스를 생성합니다. 버전 번호는 확장 프로그램의 버전을 나타냅니다. 이는 시맨틱 버전 관리를 따라야 하며 확장 프로그램의 기능이 변경될 때마다 업데이트해야 합니다. 확장 프로그램 사양 버전은 따라야 할 Firebase Extensions 사양을 결정하는 데 사용됩니다. 이 경우 v1beta
가 사용됩니다.
- YAML 파일에 사용자 친화적인 세부정보를 추가합니다.
...
displayName: Latitude and longitude to GeoHash converter
description: A converter for changing your Latitude and longitude coordinates to geohashes.
표시 이름은 개발자가 확장 프로그램과 상호작용할 때 확장 프로그램의 이름을 잘 나타내는 표현입니다. 설명은 확장 프로그램의 기능에 대한 간략한 개요를 제공합니다. 확장 프로그램이 extensions.dev에 배포되면 다음과 같이 표시됩니다.
- 확장 프로그램에서 코드의 라이선스를 지정합니다.
...
license: Apache-2.0 # The license you want for the extension
- 확장 프로그램을 누가 제작했는지, 그리고 확장 프로그램을 설치하는 데 결제가 필요한지 여부를 표시하세요.
...
author:
authorName: AUTHOR_NAME
url: https://github.com/Firebase
billingRequired: true
author
섹션은 확장 프로그램에 문제가 있거나 확장 프로그램에 대해 자세한 정보를 원하는 경우 사용자에게 연락해야 할 대상을 알려주는 데 사용됩니다. billingRequired
는 필수 매개변수이며 모든 확장 프로그램이 Blaze 요금제가 필요한 Cloud Functions를 사용하므로 true
로 설정해야 합니다.
여기에는 extension.yaml
파일에서 이 확장 프로그램을 식별하는 데 필요한 최소 필드 수가 포함됩니다. 확장 프로그램에서 지정할 수 있는 기타 식별 정보에 관한 자세한 내용은 문서를 참고하세요.
5. Cloud Functions 코드를 확장 프로그램 리소스로 변환
확장 프로그램 리소스는 확장 프로그램을 설치하는 동안 Firebase가 프로젝트에 만드는 항목입니다. 그러면 확장 프로그램이 이러한 리소스를 소유하며 해당 리소스에서 작동하는 특정 서비스 계정을 갖게 됩니다. 이 프로젝트에서 이러한 리소스는 Cloud Functions이며 extension.yaml
파일에서 정의해야 합니다. 확장 프로그램이 함수 폴더의 코드에서 자동으로 리소스를 생성하지 않기 때문입니다. Cloud Functions가 리소스로 명시적으로 선언되지 않은 경우 확장 프로그램을 배포할 때 배포할 수 없습니다.
사용자 정의 배포 위치
- 사용자가 이 확장 프로그램을 배포할 위치를 지정하고 최종 사용자와 더 가까운 곳으로 확장 프로그램을 호스팅하는 것이 더 나은지 아니면 데이터베이스와 가까운 위치에 호스팅하는 것이 더 나은지 결정할 수 있도록 허용합니다.
extension.yaml
파일에 위치를 선택하는 옵션을 포함합니다.
extension.yaml에서 실행됩니다.
이제 함수 리소스의 구성을 작성할 준비가 되었습니다.
extension.yaml
파일에서locationUpdate
함수의 리소스 객체를 만듭니다. 다음을extension.yaml
파일에 추가합니다.
resources:
- name: locationUpdate
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${PROJECT_ID}/databases/(default)/documents/users/{uid}
프로젝트의 index.ts
파일에 정의된 함수 이름으로 name
를 정의합니다. 배포되는 함수의 type
를 지정합니다. 지금은 항상 firebaseextensions.v1beta.function
여야 합니다. 그런 다음 이 함수의 properties
를 정의합니다. 정의하는 첫 번째 속성은 이 함수와 연결된 eventTrigger
입니다. 확장 프로그램에서 현재 지원하는 항목을 미러링하려면 확장 프로그램용 Cloud Functions 작성 문서에 있는 providers/cloud.firestore/eventTypes/document.write
의 eventType
를 사용합니다. resource
를 문서의 위치로 정의합니다. 현재 목표는 코드에 있는 항목을 미러링하는 것이므로 문서 경로는 기본 데이터베이스 위치가 앞에 있는 users/{uid}
를 리슨합니다.
- 확장 프로그램에는 Firestore 데이터베이스에 대한 읽기 및 쓰기 권한이 필요합니다.
extension.yaml
파일의 맨 끝에 개발자의 Firebase 프로젝트에서 데이터베이스 작업을 위해 확장 프로그램이 액세스해야 하는 IAM 역할을 지정합니다.
roles:
- role: datastore.user
reason: Allows the extension to read / write to your Firestore instance.
datastore.user
역할은 확장 프로그램에 지원되는 IAM 역할 목록에서 가져옵니다. 확장 프로그램이 읽고 쓰게 되므로 datastore.user
역할이 적합합니다.
- 호출 가능한 함수도 추가해야 합니다.
extension.yaml
파일의 리소스 속성 아래에 새 리소스를 만듭니다. 다음 속성은 호출 가능한 함수에만 해당됩니다.
- name: callableHash
type: firebaseextensions.v1beta.function
properties:
httpsTrigger: {}
이전 리소스에서는 eventTrigger
를 사용했지만 여기서는 호출 가능 함수와 HTTPS 함수를 모두 다루는 httpsTrigger
을 사용합니다.
코드 확인
extension.yaml
가 index.ts
파일의 코드에서 실행한 모든 작업과 일치하도록 하려면 많은 구성이 필요했습니다. 이 시점에서 완성된 extension.yaml
파일은 다음과 같습니다.
extension.yaml에서 실행됩니다.
name: geohash-ext
version: 0.0.1
specVersion: v1beta # Firebase Extensions specification version (do not edit)
displayName: Latitude and Longitude to GeoHash converter
description: A converter for changing your Latitude and Longitude coordinates to geohashes.
license: Apache-2.0 # The license you want for the extension
author:
authorName: Sparky
url: https://github.com/Firebase
billingRequired: true
resources:
- name: locationUpdate
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${PROJECT_ID}/databases/(default)/documents/users/{uid}
- name: callableHash
type: firebaseextensions.v1beta.function
properties:
httpsTrigger: {}
roles:
- role: datastore.user
reason: Allows the extension to read / write to your Firestore instance.
상태 확인
이제 확장 프로그램의 초기 기능 부분이 설정되었으므로 Firebase 에뮬레이터를 사용하여 실제로 사용해 볼 수 있습니다.
- 아직 호출하지 않았다면 다운로드한 확장 프로그램 프로젝트의 함수 폴더에서
npm run build
를 호출합니다. - 호스트 시스템에 새 디렉터리를 만들고
firebase init
를 사용하여 이 디렉터리를 Firebase 프로젝트에 연결합니다.
cd .. mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
This command creates a `firebase.json` file in the directory. In the following steps, you push the configuration specified in this file to Firebase.
- 동일한 디렉터리에서
firebase ext:install
를 실행합니다./path/to/extension
을extension.yaml
파일이 포함된 디렉터리의 절대 경로로 바꿉니다.
firebase ext:install /path/to/extension
This command does two things:
- 확장 프로그램 인스턴스의 구성을 지정하라는 메시지가 표시되고 인스턴스의 구성 정보가 포함된
*.env
파일이 생성됩니다. firebase.json
의extensions
섹션에 확장 프로그램 인스턴스를 추가합니다. 인스턴스 ID를 확장 프로그램 버전에 매핑하는 역할을 합니다.- 프로젝트를 로컬에 배포하므로 Google Cloud Secret Manager 대신 로컬 파일을 사용하겠다고 지정할 수 있습니다.
- 새 구성으로 Firebase 에뮬레이터를 시작합니다.
firebase emulators:start
emulators:start
를 실행한 후 에뮬레이터의 WebView에서 Firestore 탭으로 이동합니다.xv
숫자 필드와yv
숫자 필드가 있는 문서를users
컬렉션에 추가합니다.
- 확장 프로그램을 설치하면 확장 프로그램이 문서에
hash
라는 새 필드를 만듭니다.
충돌을 방지하기 위해 정리하기
- 테스트가 완료되면 확장 프로그램을 제거합니다. 확장 프로그램 코드를 업데이트할 예정이므로 나중에 현재 확장 프로그램과 충돌하지 않도록 합니다.
확장 프로그램을 사용하면 동일한 확장 프로그램의 여러 버전을 한 번에 설치할 수 있으므로 제거하면 이전에 설치된 확장 프로그램과 충돌이 발생하지 않습니다.
firebase ext:uninstall geohash-ext
현재 솔루션은 작동하지만, 프로젝트 시작 부분에서 언급했듯이, 서비스와의 통신을 시뮬레이션하는 하드 코딩된 API 키가 있습니다. 원래 제공된 API 키 대신 최종 사용자의 API 키를 사용하는 방법은 무엇인가요? 자세히 알아보려면 계속 읽어보세요.
6. 확장 프로그램을 사용자가 구성할 수 있도록 만들기
이 Codelab의 이 시점에서는 이미 작성한 함수의 주관적인 설정과 함께 사용하도록 구성된 확장 프로그램이 있습니다. 하지만 사용자가 데카르트 평면의 위치를 나타내는 필드에 y 및 x 대신 위도와 경도를 사용하려는 경우 어떻게 해야 하나요? 또한 최종 사용자가 제공된 API 키를 사용하도록 하는 대신 자신의 API 키를 제공하도록 하려면 어떻게 해야 할까요? 해당 API의 할당량이 빠르게 초과될 수 있습니다. 여기에서는 매개변수를 설정하고 사용합니다.
extension.yaml
파일에 기본 매개변수를 정의합니다.
개발자가 맞춤 구성을 보유할 가능성이 있는 항목부터 변환하세요. 첫 번째는 XFIELD
및 YFIELD
매개변수입니다.
extension.yaml
파일에서XFIELD
및YFIELD
필드 매개변수를 사용하는 다음 코드를 추가합니다. 이러한 매개변수는 이전에 정의된params
YAML 속성 내에 있습니다.
extension.yaml
params:
- param: XFIELD
label: The X Field Name
description: >-
The X Field is also known as the **longitude** value. What does
your Firestore instance refer to as the X value or the longitude
value. If no value is specified, the extension searches for
field 'xv'.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
default: xv
required: false
immutable: false
example: xv
- param: YFIELD
label: The Y Field Name
description: >-
The Y Field is also known as the **latitude** value. What does
your Firestore instance refer to as the Y value or the latitude
value. If no value is specified, the extension searches for
field 'yv'.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
default: yv
required: false
immutable: false
example: yv
- param는 확장 프로그램 제작자가 볼 수 있는 방식으로 매개변수의 이름을 지정합니다. 나중에 매개변수 값을 지정할 때 이 값을 사용합니다.
- label은 개발자가 매개변수의 기능을 알 수 있도록 사람이 읽을 수 있는 식별자입니다.
- description은 값에 대한 자세한 설명을 제공합니다. 마크다운을 지원하므로 추가 문서에 연결하거나 개발자에게 중요한 단어를 강조 표시할 수 있습니다.
- type은 사용자가 매개변수 값을 설정하는 방법에 관한 입력 메커니즘을 정의합니다.
string
,select
,multiSelect
,selectResource
,secret
등 다양한 유형이 있습니다. 각 옵션에 관한 자세한 내용은 문서를 참고하세요. - validationRegex는 개발자 항목을 특정 정규식 값으로 제한합니다 (이 예에서는 여기에 있는 간단한 필드 이름 가이드라인을 기반으로 함). 만약 실패하면...
- validationErrorMessage는 개발자에게 실패 값을 알립니다.
- default는 개발자가 텍스트를 입력하지 않은 경우의 값입니다.
- required는 개발자가 텍스트를 입력할 필요가 없음을 의미합니다.
- 변경 불가능을 사용하면 개발자가 이 확장 프로그램을 업데이트하고 이 값을 변경할 수 있습니다. 이 경우 개발자는 요구사항이 변경될 때 필드 이름을 변경할 수 있어야 합니다.
- 예는 유효한 입력이 어떤 모습일지에 대한 아이디어를 제공합니다.
이해하기에 많은 내용이었습니다.
- 특수 매개변수를 추가하기 전에
extension.yaml
파일에 세 가지 매개변수를 더 추가해야 합니다.
- param: INPUTPATH
label: The input document to listen to for changes
description: >-
This is the document where you write an x and y value to. Once
that document has received a value, it notifies the extension to
calculate a geohash and store that in an output document in a certain
field. This accepts function [wildcard parameters](https://firebase.google.com/docs/functions/firestore-events#wildcards-parameters)
type: string
validationRegex: ^[^/]+(/[^/]*/[^/]*)*/[^/]+$
validationErrorMessage: >-
This must point to a document path, not a collection path from the root
of the database. It must also not start or end with a '/' character.
required: true
immutable: false
example: users/{uid}
- param: OUTPUTFIELD
label: Geohash field
description: >-
This specifies the field in the output document to store the geohash in.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
required: false
default: hash
immutable: false
example: hash
민감한 매개변수 정의
이제 사용자가 지정한 API 키를 관리해야 합니다. 이는 함수에 일반 텍스트로 저장해서는 안 되는 민감한 문자열입니다. 대신 이 값을 Cloud Secret Manager에 저장하세요. 이는 암호화된 보안 비밀을 저장하고 실수로 유출되는 것을 방지하는 클라우드의 특별한 위치입니다. 이 경우 개발자가 이 서비스 사용 요금을 지불해야 하지만 API 키에 추가 보안 레이어를 추가하고 허위 활동을 제한할 수 있습니다. 사용자 문서에서는 개발자에게 유료 서비스임을 알려주므로 결제 시 예상치 못한 문제가 발생하지 않습니다. 전반적으로 사용은 위에 언급된 다른 문자열 리소스와 유사합니다. 유일한 차이점은 secret
라고 하는 유형입니다.
extension.yaml
파일에서 다음 코드를 추가합니다.
extension.yaml
- param: APIKEY
label: GeohashService API Key
description: >-
Your geohash service API Key. Since this is a demo, and not a real
service, you can use : 1234567890.
type: secret
required: true
immutable: false
resource
속성을 업데이트하여 매개변수 사용
앞서 언급했듯이 리소스 (함수가 아님)는 리소스가 관찰되는 방식을 정의하므로 새 매개변수를 사용하려면 locationUpdate
리소스를 업데이트해야 합니다.
extension.yaml
파일에서 다음 코드를 추가합니다.
extension.yaml
## Change from this
- name: locationUpdate
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${PROJECT_ID}/databases/(default)/documents/users/{uid}]
## To this
- name: locationUpdate
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${PROJECT_ID}/databases/(default)/documents/${INPUTPATH}
extension.yaml
파일을 확인합니다.
extension.yaml
파일을 검토합니다. 다음과 같이 나타납니다.
extension.yaml에서 실행됩니다.
name: geohash-ext
version: 0.0.1
specVersion: v1beta # Firebase Extensions specification version (do not edit)
displayName: Latitude and Longitude to GeoHash converter
description: A converter for changing your Latitude and Longitude coordinates to geohashes.
license: Apache-2.0 # The license you want to use for the extension
author:
authorName: Sparky
url: https://github.com/Firebase
billingRequired: true
params:
- param: XFIELD
label: The X Field Name
description: >-
The X Field is also known as the **longitude** value. What does
your Firestore instance refer to as the X value or the longitude
value. If you don't provide a value for this field, the extension will use 'xv' as the default value.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
default: xv
required: false
immutable: false
example: xv
- param: YFIELD
label: The Y Field Name
description: >-
The Y Field is also known as the **latitude** value. What does
your Firestore instance refer to as the Y value or the latitude
Value. If you don't provide a value for this field, the extension will use 'yv' as the default value.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
default: yv
required: false
immutable: false
example: yv
- param: INPUTPATH
label: The input document to listen to for changes
description: >-
This is the document where you write an x and y value to. Once
that document has been modified, it notifies the extension to
compute a geohash and store that in an output document in a certain
field. This accepts function [wildcard parameters](https://firebase.google.com/docs/functions/firestore-events#wildcards-parameters)
type: string
validationRegex: ^[^/]+(/[^/]*/[^/]*)*/[^/]+$
validationErrorMessage: >-
This must point to a document path, not a collection path from the root
of the database. It must also not start or end with a '/' character.
required: true
immutable: false
example: users/{uid}
- param: OUTPUTFIELD
label: Geohash field
description: >-
This specifies the field in the output document to store the geohash in.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
required: false
default: hash
immutable: false
example: hash
- param: APIKEY
label: GeohashService API Key
description: >-
Your geohash service API Key. Since this is a demo, and not a real
service, you can use : 1234567890.
type: secret
required: true
immutable: false
resources:
- name: locationUpdate
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${PROJECT_ID}/databases/(default)/documents/${INPUTPATH}
- name: callableHash
type: firebaseextensions.v1beta.function
properties:
httpsTrigger: {}
roles:
- role: datastore.user
reason: Allows the extension to read / write to your Firestore instance.
코드에서 매개변수에 액세스하기
이제 모든 매개변수가 extension.yaml
파일에 구성되었으므로 index.ts
파일에 추가합니다.
index.ts
파일에서 기본값을process.env.PARAMETER_NAME
로 바꿉니다. 그러면 적절한 매개변수 값이 가져와서 개발자의 Firebase 프로젝트에 배포된 함수 코드에 채워집니다.
index.ts
// Replace this:
const documentPath = "users/{uid}";
const xField = "xv";
const yField = "yv";
const apiKey = "1234567890";
const outputField = "hash";
// with this:
const documentPath = process.env.INPUTPATH!; // this value is ignored since its read from the resource
const xField = process.env.XFIELD!;
const yField = process.env.YFIELD!;
const apiKey = process.env.APIKEY!;
const outputField = process.env.OUTPUTFIELD!;
일반적으로 환경 변수 값으로 null 검사를 실행해야 하지만 이 경우에는 매개변수 값이 올바르게 복사되었다고 가정합니다. 이제 코드가 확장 프로그램 매개변수와 호환되도록 구성되었습니다.
7. 사용자 문서 만들기
에뮬레이터 또는 Firebase Extensions Marketplace에서 코드를 테스트하기 전에 개발자가 확장 프로그램 사용 시 얻을 수 있는 이점을 알 수 있도록 확장 프로그램을 문서화해야 합니다.
- 먼저 기능, 설치 기본 요건, 잠재적인 결제 관련 사항을 설명하는 데 사용되는
PREINSTALL.md
파일을 만듭니다.
PREINSTALL.md
Use this extension to automatically convert documents with a latitude and
longitude to a geohash in your database. Additionally, this extension includes a callable function that allows users to make one-time calls
to convert an x,y coordinate into a geohash.
Geohashing is supported for latitudes between 90 and -90 and longitudes
between 180 and -180.
#### Third Party API Key
This extension uses a fictitious third-party API for calculating the
geohash. You need to supply your own API keys. (Since it's fictitious,
you can use 1234567890 as an API key).
#### Additional setup
Before installing this extension, make sure that you've [set up a Cloud
Firestore database](https://firebase.google.com/docs/firestore/quickstart) in your Firebase project.
After installing this extension, you'll need to:
- Update your client code to point to the callable geohash function if you
want to perform arbitrary geohashes.
Detailed information for these post-installation tasks are provided after
you install this extension.
#### Billing
To install an extension, your project must be on the [Blaze (pay as you
go) plan](https://firebase.google.com/pricing)
- This extension uses other Firebase and Google Cloud Platform services,
which have associated charges if you exceed the service's no-cost tier:
- Cloud Firestore
- Cloud Functions (Node.js 16+ runtime. [See
FAQs](https://firebase.google.com/support/faq#extensions-pricing))
- [Cloud Secret Manager](https://cloud.google.com/secret-manager/pricing)
- 이 프로젝트의
README.md
작성 시간을 절약하려면 다음과 같은 편의 메서드를 사용하세요.
firebase ext:info . --markdown > README.md
이렇게 하면 PREINSTALL.md
파일의 콘텐츠와 extension.yaml
파일의 확장 프로그램에 관한 추가 세부정보가 결합됩니다.
마지막으로 방금 설치된 확장 프로그램에 관한 추가 세부정보를 확장 프로그램 개발자에게 알립니다. 개발자는 설치를 완료한 후 몇 가지 추가 안내와 정보를 받을 수 있으며 여기에서 클라이언트 코드 설정과 같은 자세한 설치 후 작업을 확인할 수도 있습니다.
POSTINSTALL.md
파일을 만든 후 다음과 같은 설치 후 정보를 포함합니다.
POSTINSTALL.md
Congratulations on installing the geohash extension!
#### Function information
* **Firestore Trigger** - ${function:locationUpdate.name} was installed
and is invoked when both an x field (${param:XFIELD}) and y field
(${param:YFIELD}) contain a value.
* **Callable Trigger** - ${function:callableHash.name} was installed and
can be invoked by writing the following client code:
```javascript
import { getFunctions, httpsCallable } from "firebase/functions";
const functions = getFunctions();
const geoHash = httpsCallable(functions, '${function:callableHash.name}');
geoHash({ ${param:XFIELD}: -122.0840, ${param:YFIELD}: 37.4221 })
.then((result) => {
// Read result of the Cloud Function.
/** @type {any} */
const data = result.data;
const error = data.error;
if (error != null) {
console.error(`callable error : ${error}`);
}
const result = data.result;
console.log(result);
});
모니터링
설치된 확장 프로그램의 상태, 사용량, 로그를 확인하는 등 활동을 모니터링하는 것이 좋습니다.
The output rendering looks something like this when it's deployed:
<img src="img/82b54a5c6ca34b3c.png" alt="A preview of the latitude and longitude geohash converter extension in the firebase console" width="957.00" />
## Test the extension with the full configuration
Duration: 03:00
It's time to make sure that the user-configurable extension is working the way it is intended.
* Change into the functions folder and ensure that the latest compiled version of the extensions exists. In the extensions project functions directory, call:
```console
npm run build
이렇게 하면 함수가 다시 컴파일되어 최신 소스 코드를 에뮬레이터 또는 Firebase에 직접 배포할 때 확장 프로그램과 함께 배포할 수 있습니다.
다음으로 확장 프로그램을 테스트할 새 디렉터리를 만듭니다. 확장 프로그램은 기존 함수에서 개발되었으므로 확장 프로그램이 구성된 폴더에서 함수 및 Firebase 규칙도 함께 배포하려고 시도하므로 테스트하지 마세요.
Firebase 에뮬레이터로 설치 및 테스트
- 호스트 시스템에 새 디렉터리를 만들고
firebase init
를 사용하여 이 디렉터리를 Firebase 프로젝트에 연결합니다.
mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
- 이 디렉터리에서
firebase ext:install
를 실행하여 확장 프로그램을 설치합니다./path/to/extension
를extension.yaml
파일이 포함된 디렉터리의 절대 경로로 바꿉니다. 이렇게 하면 확장 프로그램의 설치 프로세스가 시작되고 구성을 Firebase 또는 에뮬레이터에 푸시하기 전에 구성이 포함된.env
파일이 생성됩니다.
firebase ext:install /path/to/extension
- 프로젝트를 로컬로 배포하므로 Google Cloud Secret Manager가 아닌 로컬 파일을 사용하도록 지정하세요.
- 로컬 에뮬레이터 도구 모음을 시작합니다.
firebase emulators:start
실제 Firebase 프로젝트로 설치 및 테스트
실제 Firebase 프로젝트에서 확장 프로그램을 설치할 수 있습니다. 테스트할 때는 테스트 프로젝트를 사용하는 것이 좋습니다. 확장 프로그램의 엔드 투 엔드 흐름을 테스트하려는 경우 또는 Firebase 에뮬레이터 도구 모음에서 확장 프로그램의 트리거를 아직 지원하지 않는 경우 이 테스트 워크플로를 사용하세요(Extensions 에뮬레이터 옵션 참고). 에뮬레이터는 현재 Cloud Firestore, 실시간 데이터베이스, Pub/Sub에서 HTTP 요청에 의해 트리거되는 함수와 백그라운드 이벤트에 의해 트리거되는 함수를 지원합니다.
- 호스트 시스템에 새 디렉터리를 만들고
firebase init
를 사용하여 해당 디렉터리를 Firebase 프로젝트에 연결합니다.
cd .. mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
- 그런 다음 이 디렉터리에서
firebase ext:install
를 실행하여 확장 프로그램을 설치합니다./path/to/extension
를extension.yaml
파일이 포함된 디렉터리의 절대 경로로 바꿉니다. 이렇게 하면 확장 프로그램의 설치 프로세스가 시작되고 구성을 Firebase 또는 에뮬레이터에 푸시하기 전에 구성이 포함된.env
파일이 생성됩니다.
firebase ext:install /path/to/extension
- Firebase에 직접 배포하고 Google Cloud Secret Manager를 사용하려면 확장 프로그램을 설치하기 전에 Secret Manager API를 활성화해야 합니다.
- Firebase 프로젝트에 배포합니다.
firebase deploy
확장 프로그램 테스트
firebase deploy
또는firebase emulators:start
를 실행한 후 Firebase Console 또는 에뮬레이터의 WebView의 Firestore 탭으로 이동합니다.x
필드와y
필드로 지정된 컬렉션에 문서를 추가합니다. 이 경우 업데이트된 문서는u/{uid}
에 있으며x
필드는xv
이고y
필드는yv
입니다.
- 확장 프로그램을 성공적으로 설치한 경우 두 필드를 저장한 후 확장 프로그램에서 문서에
hash
라는 새 필드를 만듭니다.
8. 수고하셨습니다.
첫 번째 Cloud 함수를 Firebase 확장 프로그램으로 변환했습니다.
개발자가 확장 프로그램 배포 방법을 선택할 수 있도록 extension.yaml
파일을 추가하고 구성했습니다. 그런 다음 확장 프로그램 개발자가 확장 프로그램을 설정하기 전에 해야 할 일과 확장 프로그램을 성공적으로 설치한 후에 취해야 할 단계에 관한 안내를 제공하는 사용자 문서를 작성했습니다.
이제 Firebase 함수를 배포 가능한 Firebase 확장 프로그램으로 변환하는 데 필요한 주요 단계를 알게 되었습니다.