Cloud Functions용 Data Connect 트리거

Cloud Functions for Firebase를 사용하면 Firebase Data Connect의 이벤트를 처리할 수 있습니다. Cloud Functions를 사용하면 Data Connect 서비스에서 변이 실행과 같은 이벤트에 대한 응답으로 서버 측 코드를 실행할 수 있습니다. 이를 통해 자체 서버를 배포하지 않고도 사용자 정의 로직을 추가할 수 있습니다.

일반 사용 사례

  • 데이터 동기화: 변형이 발생한 후 다른 시스템(예: Cloud Firestore, BigQuery 또는 외부 API)과 데이터를 복제하거나 동기화합니다.

  • 비동기 워크플로: 데이터베이스 변경 후 이미지 처리 또는 데이터 집계와 같은 장기 실행 프로세스를 시작합니다.

  • 사용자 참여: 계정 생성과 같은 애플리케이션의 특정 변이 이벤트 후 사용자에게 이메일 또는 Cloud Messaging 알림을 보냅니다.

Data Connect 변형에 대한 함수 트리거

onMutationExecuted 이벤트 핸들러를 사용하여 Data Connect 변형이 실행될 때마다 함수를 트리거할 수 있습니다. 이 트리거는 변이가 실행될 때 발생합니다.

기본 변형 이벤트 함수

다음은 Data Connect 서비스에서 실행된 모든 변이의 세부정보를 로깅하는 기본 예시 함수입니다.

Node.js

import { onMutationExecuted } from "firebase-functions/dataconnect";
import { logger } from "firebase-functions";

export const logMutation = onMutationExecuted(
  {
    /* Trigger on all mutations, spanning all services and connectors
       in us-central1 */
  },
  (event) => {
    logger.info("A mutation was executed!", {
      data: event.data,
    });
  }
);

Python

from firebase_functions import dataconnect_fn, logger

@dataconnect_fn.on_mutation_executed()
def log_mutation(event: dataconnect_fn.Event):
  logger.info("A mutation was executed!", event.data)

프로젝트의 모든 변형을 기반으로 트리거하는 경우 트리거 핸들러에서 변형을 실행하면 안 됩니다. 그렇지 않으면 무한 루프가 발생합니다. 이벤트 트리거에서 변형을 실행하려면 아래에 설명된 필터링 옵션을 사용하고 변형이 자체적으로 트리거되지 않도록 주의하세요.

함수 위치 설정

이벤트가 함수를 트리거하려면 함수 위치Data Connect 서비스 위치와 일치해야 합니다. 기본적으로 함수 영역은 us-central1입니다.

Node.js

import { onMutationExecuted } from "firebase-functions/dataconnect";

export const onMutationRegionOption = onMutationExecuted(
  {
    region: "europe-west1"  // Set if Data Connect service location is not us-central1
  },
  (event) => { /* ... */ }
);

Python

@dataconnect_fn.on_mutation_executed(
  region="europe-west1"  # Set if Data Connect service location is not us-central1
)
def mutation_executed_handler_region_option(event: dataconnect_fn.Event):
  pass

이벤트 필터링

onMutationExecuted 핸들러는 특정 속성을 기반으로 이벤트를 필터링하는 옵션으로 구성할 수 있습니다. 특정 변이에 대해서만 함수를 트리거하려는 경우에 유용합니다.

service, connector, operation로 필터링할 수 있습니다.

Node.js

import { onMutationExecuted } from "firebase-functions/dataconnect";
import { logger } from "firebase-functions";

// Trigger this function only for the CreateUser mutation
// in the users connector of the myAppService service.
export const onUserCreate = onMutationExecuted(
  {
    service: "myAppService",
    connector: "users",
    operation: "CreateUser",
  },
  (event) => {
    logger.info("A new user was created!", event.data);
    // Add logic here: for example, sending a welcome email.
  }
);

Python

from firebase_functions import dataconnect_fn, logger

@dataconnect_fn.on_mutation_executed(
  service="myAppService",
  connector="users",
  operation="CreateUser"
):
def on_user_create(event: dataconnect_fn.Event):
  logger.info("A new user was created!", event.data)

와일드카드와 캡처 그룹

와일드카드와 캡처 그룹을 사용하여 여러 값에 대한 트리거를 필터링할 수 있습니다. 캡처된 그룹은 event.params에서 사용할 수 있습니다. 자세한 내용은 경로 패턴 이해를 참조하세요.

예를 들면 다음과 같습니다.

Node.js

import { onMutationExecuted } from "firebase-functions/dataconnect";

// Trigger on all operations that match the pattern `User*`, on any service and
// connector.
export const onMutationWildcards = onMutationExecuted(
  {
    operation: "User*",
  },
  (event) => {}
);

// Trigger on all operations that match the pattern `User*`, on any service and
// connector. Capture the operation name in the variable `op`.
export const onMutationCaptureWildcards = onMutationExecuted(
  {
    operation: "{op=User*}",
  },
  (event) => {
    // `event.params.op` contains the operation name.
  }
);

// Trigger on all operations on the service `myAppService`. Capture the
// operation name in the variable `operation`.
export const onMutationCaptures = onMutationExecuted(
  {
    service: "myAppService",
    operation: "{operation}",
  },
  (event) => {
    // `event.params.operation` contains the operation name.
  }
);

Python

from firebase_functions import dataconnect_fn

# Trigger on all operations that match the pattern `User*`, on any service and
# connector.
@dataconnect_fn.on_mutation_executed(
  operation="User*"
)
def on_mutation_wildcards(event: dataconnect_fn.Event):
  pass

# Trigger on all operations that match the pattern `User*`, on any service and
# connector. Capture the operation name in the variable `op`.
@dataconnect_fn.on_mutation_executed(
  operation="{op=User*}"
)
def on_mutation_capture_wildcards(event: dataconnect_fn.Event):
  # `event.params["op"]` contains the operation name.
  pass

# Trigger on all operations on the service `myAppService`. Capture the
# operation name in the variable `operation`.
@dataconnect_fn.on_mutation_executed(
  service="myAppService",
  operation="{operation}"
)
def on_mutation_captures(event: dataconnect_fn.Event):
  # `event.params["operation"]` contains the operation name.
  pass

사용자 인증 정보에 액세스

이벤트를 트리거한 주체에 대한 사용자 인증 정보에 액세스할 수 있습니다. 인증 컨텍스트에서 사용할 수 있는 데이터에 관한 자세한 내용은 인증 컨텍스트를 참고하세요.

다음 예시는 인증 정보를 검색하는 방법을 보여줍니다.

Node.js

import { onMutationExecuted } from "firebase-functions/dataconnect";

export const onMutation = onMutationExecuted(
  { operation: "MyMutation" },
  (event) => {
    // mutationExecuted event provides authType and authId:
    // event.authType
    // event.authId
  }
);

Python

from firebase_functions import dataconnect_fn

@dataconnect_fn.on_mutation_executed(operation="MyMutation")
def mutation_executed_handler(event: dataconnect_fn.Event):
  # mutationExecuted event provides auth_type and auth_id, which are accessed as follows
  # event.auth_type
  # event.auth_id
  pass

인증 유형과 인증 ID는 다음과 같이 채워집니다.

돌연변이는 다음에 의해 시작되었습니다. authtype authid
인증된 최종 사용자 app_user Firebase 인증 토큰 UID
인증되지 않은 최종 사용자 unauthenticated 비어 있음
최종 사용자를 사칭하는 Admin SDK app_user 사칭된 사용자의 Firebase 인증 토큰 UID
인증되지 않은 요청을 가장하는 Admin SDK unauthenticated 비어 있음
모든 권한이 있는 Admin SDK admin 비어 있음

이벤트 데이터 액세스

함수에 전달된 CloudEvent 객체에는 함수를 트리거한 이벤트에 관한 정보가 포함됩니다.

이벤트 속성

속성 유형 설명
id string 이벤트에 대한 고유 식별자입니다.
source string 이벤트를 생성한 커넥터 리소스 (예: //firebasedataconnect.googleapis.com/projects/*/locations/*/services/*/connectors/*).
specversion string CloudEvents 사양 버전 (예: "1.0").
type string 이벤트 유형: google.firebase.dataconnect.connector.v1.mutationExecuted.
time string 이벤트가 생성된 시간의 타임스탬프 (ISO 8601 형식)입니다.
subject string (선택사항) 작업 이름과 같은 이벤트 컨텍스트에 대한 추가 정보입니다.
params object 캡처된 경로 패턴의 지도입니다.
authType string 이벤트를 트리거한 주체의 유형을 나타내는 열거형입니다.
authId string 이벤트를 트리거한 주체의 고유 식별자입니다.
data MutationEventData Data Connect 이벤트의 페이로드. 다음 섹션을 참조하세요.

데이터 페이로드

MutationEventData 객체에는 Data Connect 이벤트의 페이로드가 포함됩니다.

{
  // ...
  "authType": // ...
  "data": {
    "payload": {
      "variables": {
        "userId": "user123",
        "updateData": {
          "displayName": "New Name"
        }
      },
      "data": {
        "updateUser": {
          "id": "user123",
          "displayName": "New Name",
          "email": "user@example.com"
        }
      },
      "errors": []
    }
  }
}
  • payload.variables: 뮤테이션에 전달된 변수를 포함하는 객체입니다.
  • payload.data: 뮤테이션에 의해 반환된 데이터가 포함된 객체입니다.
  • payload.errors: 뮤테이션 실행 중 발생한 오류의 배열입니다. 변이가 성공한 경우 이 배열은 비어 있습니다.

변형 변수와 반환된 데이터에 액세스하는 방법은 다음과 같습니다.

Node.js

import { onMutationExecuted } from "firebase-functions/dataconnect";
import { logger } from "firebase-functions";

export const processNewUserData = onMutationExecuted(
  {
    "service": "myAppService",
    "connector": "users",
    "operation": "CreateUser",
  },
  (event) => {
    // The variables passed to the mutation
    const mutationVariables = event.data.payload.variables;

    // The data returned by the mutation
    const returnedData = event.data.payload.data;

    logger.info("Processing mutation with variables:", mutationVariables);
    logger.info("Mutation returned:", returnedData);

    // ... your custom logic here
  }
);

Python

from firebase_functions import dataconnect_fn, logger

@dataconnect_fn.on_mutation_executed(
  service="myAppService",
  connector="users",
  operation="CreateUser"
):
def process_new_user_data(event: dataconnect_fn.Event):
  # The variables passed to the mutation
  mutation_vars = event.data.payload.variables
  # The data returned by the mutation
  returned_data = event.data.payload.data

  logger.info("Processing mutation with variables:", mutationVariables)
  logger.info("Mutation returned", returnedData)

  # ... your custom logic here

Cloud Firestore 또는 Realtime Database와 같은 다른 데이터베이스 트리거와 달리 Data Connect 이벤트는 데이터의 '이전' 스냅샷을 제공하지 않습니다. Data Connect는 기본 데이터베이스에 대한 요청을 프록시하므로 데이터의 "이전" 스냅샷을 트랜잭션 방식으로 얻을 수 없습니다. 대신, 뮤테이션에 전송된 인수와 뮤테이션에서 반환된 데이터에 접근할 수 있습니다.

이로 인해 "이전"과 "이후" 스냅샷을 비교하는 전략을 사용하여 이벤트 트리거가 동일한 이벤트를 트리거하는 무한 루프를 피할 수 없습니다. 돌연변이 이벤트에 의해 트리거된 함수에서 돌연변이를 수행해야 하는 경우 이벤트 필터를 활용하고 간접적으로라도 어떤 돌연변이도 자체적으로 트리거되지 않도록 주의하세요.