함수 관리


Firebase CLI 명령어를 사용하거나 함수 소스 코드에 런타임 옵션을 설정하면 함수를 배포, 삭제, 수정할 수 있습니다.

함수 배포

함수를 배포하려면 이 Firebase CLI 명령어를 실행합니다.

firebase deploy --only functions

기본적으로 Firebase CLI는 소스 내에서 모든 함수를 동시에 배포합니다. 프로젝트에 포함된 함수가 5개를 초과하는 경우 수정한 함수만 배포되도록 특정 함수 이름에 --only 플래그를 사용하는 것이 좋습니다. 특정 함수만 배포하면 배포 프로세스 속도가 빨라지고 배포 할당량에 도달하는 것을 방지할 수 있습니다. 예를 들면 다음과 같습니다.

firebase deploy --only functions:addMessage,functions:makeUppercase

다수의 함수를 배포하면 표준 할당량을 초과하고 HTTP 429 또는 500 오류 메시지가 표시될 수 있습니다. 이 문제를 해결하려면 10개 이하의 그룹으로 함수를 배포합니다.

사용 가능한 명령어의 전체 목록을 보려면 Firebase CLI 참조를 확인하세요.

기본적으로 Firebase CLI는 소스 코드의 functions/ 폴더를 확인합니다. 원하는 경우 코드베이스 또는 여러 파일 세트로 함수를 구성할 수 있습니다.

함수 삭제

다음과 같은 방법으로 이전에 배포한 함수를 삭제할 수 있습니다.

  • Firebase CLI에서 functions:delete를 사용하여 명시적으로 삭제
  • Google Cloud 콘솔에서 명시적으로 삭제
  • 배포 전에 소스에서 함수를 삭제하여 암시적으로 삭제

어떤 방법을 사용하든 프로덕션에서 함수를 삭제하기 전에 확인 메시지가 표시됩니다.

Firebase CLI의 명시적인 함수 삭제에서는 여러 인수와 함수 그룹을 지원하며 특정 리전에서 실행되는 함수를 지정할 수 있게 해줍니다. 확인 메시지를 재정의할 수도 있습니다.

# Delete all functions that match the specified name in all regions.
firebase functions:delete myFunction
# Delete a specified function running in a specific region.
firebase functions:delete myFunction --region us-east-1
# Delete more than one function
firebase functions:delete myFunction myOtherFunction
# Delete a specified functions group.
firebase functions:delete groupA
# Bypass the confirmation prompt.
firebase functions:delete myFunction --force

암시적인 함수 삭제에서는 firebase deploy가 소스를 파싱하고 파일에서 삭제된 함수를 프로덕션에서 삭제합니다.

함수의 이름, 리전 또는 트리거 수정

프로덕션 트래픽을 처리하는 함수의 이름을 바꾸거나 함수의 리전 또는 트리거를 변경하는 경우 수정 중에 이벤트가 손실되지 않도록 이 섹션의 단계를 수행합니다. 변경 과정에서 새 버전 및 구 버전의 함수가 동시에 실행되므로 이 단계를 수행하기 전에 먼저 멱등 함수인지 확인해야 합니다.

함수 이름 바꾸기

함수 이름을 바꾸려면 소스에서 이름을 변경한 새 버전의 함수를 만든 후 별도의 두 배포 명령어를 실행합니다. 첫 번째 명령어는 새로운 이름의 함수를 배포하고 두 번째 명령어는 이전에 배포한 버전을 삭제합니다. 예를 들어 이름을 바꾸려는 HTTP 트리거 웹훅이 있는 경우 다음과 같이 코드를 수정합니다.

Node.js

// before
const {onRequest}  = require('firebase-functions/v2/https');

exports.webhook = onRequest((req, res) => {
    res.send("Hello");
});

// after
const {onRequest}  = require('firebase-functions/v2/https');

exports.webhookNew = onRequest((req, res) => {
    res.send("Hello");
});

Python

# before
from firebase_functions import https_fn

@https_fn.on_request()
def webhook(req: https_fn.Request) -> https_fn.Response:
    return https_fn.Response("Hello world!")

# after
from firebase_functions import https_fn

@https_fn.on_request()
def webhook_new(req: https_fn.Request) -> https_fn.Response:
    return https_fn.Response("Hello world!")

다음 명령어를 실행하여 새 함수를 배포합니다.

# Deploy new function
firebase deploy --only functions:webhookNew

# Wait until deployment is done; now both functions are running

# Delete webhook
firebase functions:delete webhook

함수 리전 변경

프로덕션 트래픽을 처리하는 함수의 지정된 리전을 변경하는 경우 다음 단계를 순서대로 수행하면 이벤트 손실을 방지할 수 있습니다.

  1. 함수 이름을 바꾸고 하나 이상의 리전을 원하는 대로 변경합니다.
  2. 이름이 바뀐 함수를 배포하면 두 리전 집합에서 일시적으로 동일한 코드가 실행됩니다.
  3. 이전 함수를 삭제합니다.

예를 들어 현재 기본 함수 리전인 us-central1에 위치한 Cloud Firestore 트리거 함수가 있고, 이를 asia-northeast1로 마이그레이션하려면 먼저 소스 코드를 수정하여 함수 이름을 바꾸고 리전을 수정해야 합니다.

Node.js

// before
exports.firestoreTrigger = onDocumentCreated(
  "my-collection/{docId}",
  (event) => {},
);

// after
exports.firestoreTriggerAsia = onDocumentCreated(
  {
    document: "my-collection/{docId}",
    region: "asia-northeast1",
  },
  (event) => {},
);

업데이트된 코드는 리전과 함께 올바른 이벤트 필터(이 경우 document)를 지정해야 합니다. 자세한 내용은 Cloud Functions 위치를 참고하세요.

Python

# Before
@firestore_fn.on_document_created("my-collection/{docId}")
def firestore_trigger(event):
    pass

# After
@firestore_fn.on_document_created("my-collection/{docId}",
                                  region="asia-northeast1")
def firestore_trigger_asia(event):
    pass

다음 명령어를 실행하여 배포합니다.

firebase deploy --only functions:firestoreTriggerAsia

이제 동일한 함수 두 개가 실행됩니다. firestoreTriggerus-central1에서 실행되고 firestoreTriggerAsiaasia-northeast1에서 실행됩니다.

그런 다음 firestoreTrigger을 삭제합니다.

firebase functions:delete firestoreTrigger

이제 asia-northeast1에서 실행되는 함수 firestoreTriggerAsia 하나만 있습니다.

함수의 트리거 유형 변경

Cloud Functions for Firebase 배포를 개발하는 과정에서 여러 가지 이유로 함수의 트리거 유형을 변경해야 할 수 있습니다. 예를 들어 Firebase Realtime Database 또는 Cloud Firestore 이벤트의 한 유형을 다른 유형으로 변경할 수 있습니다.

소스 코드 변경과 firebase deploy 실행만으로는 함수의 이벤트 유형을 변경할 수 없습니다. 오류를 방지하려면 다음 절차를 따라 함수의 트리거 유형을 변경합니다.

  1. 원하는 트리거 유형의 새 함수를 포함하도록 소스 코드를 수정합니다.
  2. 함수를 배포하면 이전 함수 및 새 함수 모두가 일시적으로 실행됩니다.
  3. Firebase CLI를 사용하여 프로덕션에서 이전 함수를 명시적으로 삭제합니다.

예를 들어 객체가 삭제될 때 트리거되는 함수가 있었는데 객체 버전 관리를 사용 설정하고 대신 보관처리 이벤트를 구독하려는 경우 먼저 함수 이름을 변경하고 새 트리거 유형이 포함되도록 수정합니다.

Node.js

// before
const {onObjectDeleted} = require("firebase-functions/v2/storage");

exports.objectDeleted = onObjectDeleted((event) => {
    // ...
});

// after
const {onObjectArchived} = require("firebase-functions/v2/storage");

exports.objectArchived = onObjectArchived((event) => {
    // ...
});

Python

# before
from firebase_functions import storage_fn

@storage_fn.on_object_deleted()
def object_deleted(event):
  # ...

# after 
from firebase_functions import storage_fn

@storage_fn.on_object_archived()
def object_archived(event):
  # ...

다음 명령어를 실행하여 먼저 새 함수를 만든 후 이전 함수를 삭제합니다.

# Create new function objectArchived
firebase deploy --only functions:objectArchived

# Wait until deployment is done; now both objectDeleted and objectArchived are running

# Delete objectDeleted
firebase functions:delete objectDeleted

런타임 옵션 설정

Cloud Functions for Firebase를 사용하면 Node.js 런타임 버전과 함수별 제한 시간, 메모리 할당, 최소/최대 함수 인스턴스 수와 같은 런타임 옵션을 선택할 수 있습니다.

이러한 옵션(Node.js 버전 제외)은 함수 코드 내 구성 객체에 설정하는 것이 좋습니다. 이 RuntimeOptions 객체는 함수의 런타임 옵션에 대한 정보 소스이며 다른 메서드(예: Google Cloud 콘솔 또는 gcloud CLI)를 통해 설정된 옵션을 재정의합니다.

개발 워크플로에 Google Cloud 콘솔이나 gcloud CLI를 통해 런타임 옵션을 수동으로 설정해야 하는 경우 각 배포에서 이러한 값이 재정의되지 않게 하려면 preserveExternalChanges 옵션을 true로 설정합니다. 이 옵션을 true로 설정하면 Firebase는 코드에 설정된 런타임 옵션을 다음 우선순위에 따라 현재 배포된 함수 버전 설정과 병합합니다.

  1. 함수 코드에서 설정된 옵션: 외부 변경사항을 재정의합니다.
  2. 함수 코드에서 RESET_VALUE로 설정된 옵션: 외부 변경사항을 기본값으로 재정의합니다.
  3. 함수 코드에서 설정되지 않았지만 현재 배포된 함수에서 설정된 옵션: 배포된 함수에 지정된 옵션을 사용합니다.

코드가 더 이상 함수의 런타임 옵션에 대한 완전한 정보 소스가 아니므로 preserveExternalChanges: true 옵션을 사용하지 않는 것이 좋습니다. 사용하는 경우 Google Cloud 콘솔을 확인하거나 gcloud CLI를 사용하여 함수의 전체 구성을 봅니다.

Node.js 버전 설정

Cloud FunctionsFirebase SDK에서는 Node.js 런타임을 선택할 수 있습니다. 지원되는 Node.js 버전 중 하나에 해당하는 런타임 환경에서만 프로젝트의 모든 함수를 실행하도록 선택할 수 있습니다.

  • Node.js 22(미리보기)
  • Node.js 20
  • Node.js 18

Node.js 버전 14 및 16은 지원 중단되었으며 2025년 초에 지원 중단될 예정입니다. 이러한 지원 중단된 버전으로 배포는 사용 중지됩니다.

Node.js 버전을 설정하려면 다음 안내를 따르세요.

초기화 중에 functions/ 디렉터리에 생성된 package.json 파일의 engines 필드에 버전을 설정할 수 있습니다. 예를 들어 버전 18만 사용하려면 package.json에서 다음 줄을 수정합니다.

  "engines": {"node": "20"}

Yarn 패키지 관리자를 사용 중이거나 engines 필드에 대한 다른 특정 요구사항이 있는 경우 firebase.json에서 Cloud FunctionsFirebase SDK 런타임을 설정할 수 있습니다.

  {
    "functions": {
      "runtime": "nodejs18" // or nodejs20
    }
  }

CLI는 package.json에서 별도로 설정한 값이나 범위보다 firebase.json에 설정된 값을 우선적으로 사용합니다.

Node.js 런타임 업그레이드

Node.js 런타임을 업그레이드하려면 다음 안내를 따르세요.

  1. 프로젝트가 Blaze 요금제를 사용하는지 확인합니다.
  2. Firebase CLI v11.18.0 이상을 사용 중인지 확인합니다.
  3. 초기화 중에 functions/ 디렉터리에 생성된 package.json 파일의 engines 값을 변경합니다. 예를 들어 버전 18에서 버전 20으로 업그레이드하는 경우 항목은 다음과 같이 표시됩니다. "engines": {"node": "20"}
  4. 원하는 경우 Firebase Local Emulator Suite를 사용하여 변경사항을 테스트합니다.
  5. 모든 함수를 다시 배포합니다.

Python 버전 설정

Cloud FunctionsFirebase SDK 버전 12.0.0 이상을 사용하면 Python 런타임을 선택할 수 있습니다. 다음과 같이 firebase.json에서 런타임 버전을 설정합니다.

  {
    "functions": {
      "runtime": "python310" // or python311
    }
  }

확장 동작 제어

기본적으로 Cloud Functions for Firebase는 수신되는 요청 수를 기준으로 실행되는 인스턴스 수를 확장하므로 트래픽이 감소하면 인스턴스 수를 0개로 줄일 수 있습니다. 하지만 앱에서 지연 시간을 단축해야 하고 콜드 스타트 횟수를 제한하려면 웜 상태로 유지하고 요청을 처리할 수 있도록 최소 컨테이너 인스턴스 수를 지정하여 이러한 기본 동작을 변경할 수 있습니다.

마찬가지로 최대 횟수를 설정하여 수신되는 요청에 따른 인스턴스 확장을 제한할 수 있습니다. 이 설정을 사용하여 비용을 제어하거나 데이터베이스와 같은 백업 서비스에 대한 연결 수를 제한할 수 있습니다.

이러한 설정을 인스턴스별 동시 실행 설정(2세대의 새 기능)과 함께 사용하면 함수의 확장 동작을 제어하고 조정할 수 있습니다. 애플리케이션과 함수의 특성에 따라 가장 비용 효율적인 설정이 결정되고 최상의 성능이 도출됩니다.

트래픽이 적은 일부 앱의 경우 다중 동시 실행을 사용하지 않고 CPU 옵션을 낮추는 것이 가장 좋습니다. 콜드 스타트가 중요한 문제인 경우 동시 실행을 높게 설정하고 인스턴스를 최소로 설정하면 트래픽 급증을 처리하기 위해 항상 일련의 인스턴스가 웜 상태로 유지됩니다.

트래픽이 매우 적은 소규모 앱의 경우 동시 실행을 높게 설정하고 최대 인스턴스를 낮게 설정하면 앱이 과도한 비용 발생 없이 트래픽 버스트를 처리할 수 있습니다. 하지만 최대 인스턴스가 너무 낮게 설정되면 상한에 도달할 경우 요청이 삭제될 수 있다는 점에 유의하세요.

동시 요청 허용

Cloud Functions for Firebase(1세대)에서 각 인스턴스는 한 번에 하나의 요청을 처리할 수 있으므로 확장 동작은 최소 및 최대 인스턴스 설정으로만 지정됩니다. 인스턴스 수를 제어하는 것 외에도 Cloud Functions for Firebase(2세대)에서는 concurrency 옵션을 사용하여 각 인스턴스가 동시에 제공할 수 있는 요청 수를 제어할 수 있습니다. 동시 실행의 기본값은 80이지만 1과 1,000 사이의 정수로 설정할 수 있습니다.

동시 실행이 높게 설정된 함수는 각 인스턴스에 여유가 있을 수 있으므로 콜드 스타트 없이 트래픽 급증을 흡수할 수 있습니다. 최대 50개의 동시 요청을 처리하도록 인스턴스가 구성되었지만 현재 25개만 처리 중인 경우 새 인스턴스를 콜드 스타트할 필요 없이 25개의 추가 요청 급증을 처리할 수 있습니다. 반면에 동시 실행 설정이 1개뿐일 때 요청이 급증하면 25회의 콜드 스타트로 이어질 수 있습니다.

단순화된 이 시나리오는 동시 실행으로 잠재적인 효율성이 향상되는 것을 보여줍니다. 사실, 동시 실행으로 효율성을 최적화하고 콜드 스타트를 줄이기 위한 확장 동작은 더 복잡합니다. Cloud Functions for Firebase 2세대의 동시 실행은 Cloud Run을 기반으로 하며 Cloud Run컨테이너 인스턴스 자동 확장 규칙을 따릅니다.

Cloud Functions for Firebase(2세대)에서 더 높은 동시 실행 설정을 실험하는 경우 다음 사항에 유의하세요.

  • 동시 실행 설정이 높을수록 실제 한도에 도달할 때까지 최적의 성능을 위해 더 높은 사양의 CPU와 RAM이 필요할 수 있습니다. 예를 들어 과도한 이미지 또는 동영상 처리를 수행하는 함수에서는 CPU 및 RAM 설정이 최대화되더라도 1,000개의 동시 요청을 처리하기 위한 리소스가 부족할 수 있습니다.
  • Cloud Functions for Firebase(2세대)는 Cloud Run을 기반으로 하므로 동시 실행 최적화에 대한 Google Cloud 안내를 참고하세요.
  • 프로덕션 단계에서 다중 동시 실행으로 전환하기 전에 테스트 환경에서 다중 동시 실행을 철저히 테스트해야 합니다.

최소 인스턴스 수를 웜 상태로 유지

소스 코드에서 함수의 최소 인스턴스 수를 설정할 수 있습니다. 예를 들어 이 함수는 최소 5개의 인스턴스를 설정하여 웜 상태를 유지합니다.

Node.js

const { onCall } = require("firebase-functions/v2/https");

exports.getAutocompleteResponse = onCall(
  {
    // Keep 5 instances warm for this latency-critical function
    minInstances: 5,
  },
  (event) => {
    // Autocomplete user’s search term
  }
);

Python

@https_fn.on_call(min_instances=5)
def get_autocomplete_response(event: https_fn.CallableRequest) -> https_fn.Response:

최소 인스턴스 값을 설정할 때 고려할 사항은 다음과 같습니다.

  • Cloud Functions for Firebase에서 앱을 설정 이상으로 확장하면 이 기준점을 초과하는 인스턴스마다 콜드 스타트가 발생합니다.
  • 콜드 스타트는 트래픽이 급증하는 앱에 가장 심각한 영향을 미칩니다. 앱에 트래픽 급증이 발생하는 경우 트래픽이 증가할 때마다 콜드 스타트가 줄어들 수 있도록 값을 충분히 높게 설정하면 지연 시간이 크게 감소합니다. 트래픽이 일정한 앱에서는 콜드 스타트가 성능에 심각한 영향을 미칠 가능성이 낮습니다.
  • 프로덕션 환경에서는 최소한의 인스턴스를 설정하는 것이 합리적일 수 있지만 일반적으로 테스트 환경에서는 최소한의 인스턴스를 설정하면 안 됩니다. 테스트 프로젝트에서 0으로 축소하면서 프로덕션 프로젝트의 콜드 스타트를 줄이려면 매개변수화된 구성에서 최소 인스턴스 값을 설정하면 됩니다.

    Node.js

    const functions = require('firebase-functions/v1');
    const { defineInt, defineString } = require('firebase-functions/params');
    
    // Define some parameters
    const minInstancesConfig = defineInt('HELLO_WORLD_MININSTANCES');
    const welcomeMessage = defineString('WELCOME_MESSAGE');
    
    // To use configured parameters inside the config for a function, provide them 
    // directly. To use them at runtime, call .value() on them.
    export const helloWorld = functions.runWith({ minInstances: minInstancesConfig}).https.onRequest(
      (req, res) => {
        res.send(`${welcomeMessage.value()}! I am a function.`);
      }
    );
    

    Python

    MIN_INSTANCES = params.IntParam("HELLO_WORLD_MININSTANCES")
    WELCOME_MESSAGE = params.StringParam("WELCOME_MESSAGE")
    
    @https_fn.on_request(min_instances=MIN_INSTANCES.value())
    def get_autocomplete_response(event: https_fn.Request) -> https_fn.Response:
        return https_fn.Response(f"{WELCOME_MESSAGE.value()} I'm a function.")
    

함수의 최대 인스턴스 수 제한

함수 소스 코드에서 최대 인스턴스 값을 설정할 수 있습니다. 예를 들어 가상의 기존 데이터베이스에 부담을 주지 않도록 이 함수는 인스턴스 수 한도를 100개로 설정합니다.

Node.js

const { onMessagePublished } = require("firebase-functions/v2/pubsub");

exports.mirrorevents = onMessagePublished(
  { topic: "topic-name", maxInstances: 100 },
  (event) => {
    // Connect to legacy database
  }
);

Python

@pubsub_fn.on_message_published(topic="topic-name", max_instances=100)
def mirrorevents(event: pubsub_fn.CloudEvent):
#  Connect to legacy database

HTTP 함수를 최대 인스턴스 한도로 확장하면 새 요청이 30초 동안 큐에 추가된 후 그때까지 사용 가능한 인스턴스가 없을 경우 429 Too Many Requests 응답 코드와 함께 거부됩니다.

최대 인스턴스 설정 사용에 관한 권장사항은 최대 인스턴스 설정 권장사항을 참조하세요.

제한 시간 및 메모리 할당 설정

함수에 제한 시간 값이나 메모리 할당을 늘리는 등의 특별한 요구사항이 있는 경우가 있습니다. Google Cloud 콘솔 또는 함수 소스 코드(Firebase만 해당)에서 이러한 값을 설정할 수 있습니다.

함수 소스 코드에서 메모리 할당과 제한 시간을 설정하려면 메모리 및 제한 시간(초)의 전역 옵션을 사용하여 함수를 실행하는 가상 머신을 맞춤설정합니다. 예를 들어 이 Cloud Storage 함수는 메모리 1GiB를 사용하며 300초 후에 타임아웃됩니다.

Node.js

exports.convertLargeFile = onObjectFinalized({
  timeoutSeconds: 300,
  memory: "1GiB",
}, (event) => {
  // Do some complicated things that take a lot of memory and time
});

Python

@storage_fn.on_object_finalized(timeout_sec=300, memory=options.MemoryOption.GB_1)
def convert_large_file(event: storage_fn.CloudEvent):
# Do some complicated things that take a lot of memory and time.

제한 시간(초)의 최댓값은 540 또는 9분입니다.

Google Cloud 콘솔에서 메모리 할당 및 제한 시간을 설정하려면 다음 안내를 따르세요.

  1. Google Cloud 콘솔의 왼쪽 메뉴에서 Cloud Functions for Firebase를 선택합니다.
  2. 함수 목록에서 이름을 클릭해 함수를 선택합니다.
  3. 상단 메뉴에서 수정 아이콘을 클릭합니다.
  4. 할당 메모리라는 라벨이 지정된 드롭다운 메뉴에서 메모리 할당을 선택합니다.
  5. 더보기를 클릭해 고급 옵션을 표시하고 제한 시간 입력란에 초 단위 값을 입력합니다.
  6. 저장을 클릭하여 함수를 업데이트합니다.

CPU 기본값 재정의

메모리가 최대 2GB까지 할당되면 Cloud Functions for Firebase(2세대)의 각 함수는 1CPU로 기본 설정된 후 4GB 및 8GB 메모리가 할당되면 2CPU로 증가합니다. 다음 표에 설명된 것처럼 메모리 용량이 낮은 함수의 비용이 약간 증가할 수 있다는 점이 1세대 기본 동작과 매우 다릅니다.

할당된 RAM 버전 1 기본 CPU(분수) 버전 2 기본 CPU 밀리초당 가격 인상
128MB 1/12 1 10.5x
256MB 1/6 1 5.3x
512MB 1/3 1 2.7x
1GB 7/12 1 1.6x
2GB 1 1 1x
4GB 2 2 1x
8GB 2 2 1x
16GB 해당 사항 없음 4 해당사항 없음

2세대 함수에 1세대 동작을 사용하려면 다음과 같이 1세대 기본값을 전역 옵션으로 설정합니다.

Node.js

// Turn off Firebase defaults
setGlobalOptions({ cpu: 'gcf_gen1' });

Python

# Use 1st gen behavior
set_global_options(cpu="gcf_gen1")

CPU를 많이 사용하는 함수의 경우 2세대에서 추가 CPU를 유연하게 구성할 수 있습니다. 다음과 같이 함수별로 CPU를 늘릴 수 있습니다.

Node.js

// Boost CPU in a function:
export const analyzeImage = onObjectFinalized({ cpu: 2 }, (event) => {
  // computer vision goes here
});

Python

# Boost CPU in a function:
@storage_fn.on_object_finalized(cpu=2)
def analyze_image(event: storage_fn.CloudEvent):
# computer vision goes here