Cloud Functions를 프로젝트에 통합하면 코드가 확장되어 여러 독립 함수를 포함할 수 있습니다. 단일 파일에 넣기에는 함수가 너무 많거나 팀마다 다른 함수 그룹을 배포하면 한 팀이 다른 팀의 함수를 덮어쓰거나 실수로 삭제할 위험이 있습니다. Cloud Functions는 함수를 더 쉽게 탐색하고 유지관리할 수 있도록 코드를 구성하는 다양한 방식을 제공합니다.
코드베이스에서 함수 구성
firebase.json
에서 함수 구성 객체의 codebase
속성을 사용하여 단일 저장소 monorepo 설정 내에 있는 여러 저장소나 하위 패키지에서 대규모 함수 컬렉션을 관리할 수 있습니다.
# firebase.json
"functions": {
"codebase": "my-codebase"
# NOTE: Codebase must be less than 63 characters and can contain only
# lowercase letters, numeric characters, underscores, and dashes.
}
codebase
속성은 Firebase CLI v10.7.1 이상에서 지원됩니다.
여러 저장소 관리
codebase
속성을 사용하면 여러 저장소를 간단하게 관리할 수 있습니다. 같은 Firebase 프로젝트에 함수를 배포하는 저장소가 두 개 있는 경우를 살펴보겠습니다.
$ tree .
├── repoA
│ ├── firebase.json
│ └── functions
│ ├── index.js
│ └── package.json
└── repoB
├── firebase.json
└── functions
├── index.js
└── package.json
코드베이스 주석이 없으면 Firebase CLI에서 배포 시 다른 저장소에 정의된 함수를 삭제하라는 메시지가 표시되었을 것입니다.
$ (cd repoA && firebase deploy --only functions)
...
i functions: preparing functions directory for uploading...
✔ functions: functions folder uploaded successfully
The following functions are found in your project but do not exist in your local source code:
fn1FromRepoB
fn2FromRepoB
...
? Would you like to proceed with deletion? Selecting no will continue the rest of the deployments. (y/N)
각 프로젝트 저장소에 있는 firebase.json
의 함수 구성 섹션에 고유한 코드베이스 주석을 추가하면 이 문제를 방지할 수 있습니다.
# repoA/firebase.json
"functions": {
"codebase": "repo-a"
}
# repoB/firebase.json
"functions": {
"codebase": "repo-b"
}
코드베이스 주석을 사용하면 전용 저장소 외부에 정의된 함수를 삭제하라는 메시지가 Firebase CLI에 더 이상 표시되지 않습니다.
$ (cd repoA && firebase deploy --only functions)
...
i functions: preparing functions directory for uploading...
✔ functions: functions folder uploaded successfully
# Gleefully ignores functions from repoB
i functions: creating Node.js 16 function fnFromRepoA (us-central1)...
✔ Deploy Complete!
여러 소스 패키지 관리(monorepo)
codebase
속성을 사용하면 단일 저장소의 여러 소스 패키지를 간단하게 관리할 수 있습니다. 함수 정의가 여러 하위 패키지에 걸쳐 있는 Firebase 프로젝트 디렉터리가 있는 경우를 살펴보겠습니다.
$ tree .
├── firebase.json
├── teamA
│ ├── index.js
│ └── package.json
└── teamB
├── index.js
└── package.json
이 설정은 다음 사용 사례에 적합합니다.
- monorepo가 설정되어 있고 서로 다른 팀이 격리된 패키지에서 자체 함수 정의를 관리하고 있습니다.
- 외부 종속 항목이 많고 초기화가 장기 실행되는 함수를 지연 시간에 민감한 다른 함수와 격리하려고 합니다.
이와 같은 monrepo 설정을 지원하려면 firebase.json
에서 함수 구성을 여러 개 정의합니다.
"functions": [
{
"source": "teamA",
"codebase": "team-a"
},
{
"source": "teamB",
"codebase": "team-b"
},
]
이 구성을 통해 Firebase CLI는 단일 배포 명령어로 모든 패키지의 함수를 배포합니다.
$ firebase deploy --only functions
i deploying functions
i functions: preparing codebase team-a for deployment
i functions: preparing codebase team-b for deployment
i functions: creating Node.js 16 function team-a:helloATeam(us-central1)...
i functions: creating Node.js 16 function team-b:helloBTeam(us-central1)...
...
특정 코드베이스를 배포할 수도 있습니다.
$ firebase deploy --only functions:team-b
i deploying functions
i functions: preparing codebase team-b for deployment
i functions: updating Node.js 16 function team-b:helloBTeam(us-central1)...
...
여러 파일에서 함수 작성
Cloud Functions를 시작할 때는 처음 몇 가지 함수를 파일 하나에 포함할 수 있습니다.
index.js
const functions = require('firebase-functions/v1');
exports.foo = functions.https.onRequest((request, response) => {
// ...
});
exports.bar = functions.https.onRequest((request, response) => {
// ...
});
main.py
from firebase_functions import https_fn
@https_fn.on_request()
def foo(req: https_fn.Request) -> https_fn.Response:
return https_fn.Response("Hello foo!")
@https_fn.on_request()
def bar(req: https_fn.Request) -> https_fn.Response:
return https_fn.Response("Hello bar!")
하지만 이렇게 하면 함수 수가 늘어날 때 관리하기가 어려워질 수 있습니다. 대신 각 함수의 모든 논리를 자체 파일에 저장하고 소스 파일을 내보내기 목록으로 사용하는 것이 좋습니다.
Node.js
foo.js
const functions = require('firebase-functions/v1'); exports.foo = functions.https.onRequest((request, response) => { // ... });
bar.js
const functions = require('firebase-functions/v1'); exports.bar = functions.https.onRequest((request, response) => { // ... });
index.js
const foo = require('./foo'); const bar = require('./bar'); exports.foo = foo.foo; exports.bar = bar.bar;
Python
foo.py
from firebase_functions import https_fn
@https_fn.on_request()
def foo(req: https_fn.Request) -> https_fn.Response:
return https_fn.Response("Hello foo!")
bar.py
from firebase_functions import https_fn
@https_fn.on_request()
def bar(req: https_fn.Request) -> https_fn.Response:
return https_fn.Response("Hello foo!")
main.py
from fn_impl.foo import *
from fn_impl.bar import *
이 설정에서는 다음과 같은 프로젝트 디렉터리 구조를 가정합니다.
my-project
├── firebase.json
└── functions
├── fn_impl
│ ├── __init__.py
│ ├── foo.py
│ └── bar.py
├── main.py
└── requirements.txt
fn_impl
: 어떤 이름이라도 가능함
__init__.py
: 필수사항이지만 비어 있을 수 있음
함수 그룹화
대부분의 프로젝트에서 함수를 함께 배포되고 관리되는 논리적 그룹으로 구분할 수 있습니다. 예를 들어 측정항목 보고에 사용되는 함수 그룹이 있을 수 있습니다.
metrics.js
const functions = require('firebase-functions/v1'); exports.usageStats = functions.https.onRequest((request, response) => { // ... }); exports.nightlyReport = functions.https.onRequest((request, response) => { // ... });
index.js
파일로 내보낼 때 이러한 함수를 그룹 하나에 포함할 수 있습니다.
index.js
// Export both functions from metrics.js in the "metrics" group: // - metrics-usageStats // - metrics-nightlyReport exports.metrics = require('./metrics');
배포 시 함수 이름은 함수가 속한 그룹 이름으로 시작되므로 이 예시에서 함수 이름은 metrics-usageStats
및 metrics-nightlyReport
입니다.
함수 배포 시 작업을 단일 그룹으로 제한할 수 있습니다.
firebase deploy --only functions:metrics
다음 단계
Cloud Functions에 관해 자세히 알아보려면 다음을 참조하세요.