Google Cloud Storage 트리거

Cloud Functions는 이벤트 기반 함수를 사용하여 Cloud 인프라의 이벤트를 처리합니다. 예를 들어 Cloud Functions는 Google Cloud Storage에서 보내는 변경 알림에 응답할 수 있습니다. 객체 생성, 삭제, 보관, 메타데이터 업데이트와 같이 버킷 내의 다양한 이벤트에 대한 응답으로 트리거되도록 해당 알림을 구성할 수 있습니다.

이벤트 유형

Cloud Functions에서 사용되는 Cloud Storage 이벤트는 Google Cloud Storage용 Cloud Pub/Sub 알림을 기반으로 하며 Cloud Storage JSON API 형식으로 제공됩니다.

Storage 트리거 함수는 4가지 트리거 유형을 지원합니다. 이러한 트리거 유형 값은 함수를 배포할 때 함수를 트리거할 Cloud Storage 이벤트를 지정하는 데 사용됩니다.

샘플 함수 코드

다음 샘플 함수는 이벤트가 발생할 때 관련 데이터를 로깅합니다.

함수를 배포할 때 트리거 유형을 지정합니다. 예를 들어 아래 배포 예시에서는 google.storage.object.finalize 트리거 유형을 지정하여 객체가 생성될 때마다 함수를 사용하여 로깅합니다.

이 코드 실행에 대한 전체 튜토리얼은 Cloud Storage 튜토리얼을 참조하세요.

Node.js

 
/**
 * Generic background Cloud Function to be triggered by Cloud Storage.
 *
 * @param {object} file The Cloud Storage file metadata.
 * @param {object} context The event metadata.
 */
exports.helloGCS = (file, context) => {
  console.log(`  Event: ${context.eventId}`);
  console.log(`  Event Type: ${context.eventType}`);
  console.log(`  Bucket: ${file.bucket}`);
  console.log(`  File: ${file.name}`);
  console.log(`  Metageneration: ${file.metageneration}`);
  console.log(`  Created: ${file.timeCreated}`);
  console.log(`  Updated: ${file.updated}`);
};

Python

 
def hello_gcs(event, context):
    """Background Cloud Function to be triggered by Cloud Storage.
       This generic function logs relevant data when a file is changed.

    Args:
        event (dict):  The dictionary with data specific to this type of event.
                       The `data` field contains a description of the event in
                       the Cloud Storage `object` format described here:
                       https://cloud.google.com/storage/docs/json_api/v1/objects#resource
        context (google.cloud.functions.Context): Metadata of triggering event.
    Returns:
        None; the output is written to Stackdriver Logging
    """

    print('Event ID: {}'.format(context.event_id))
    print('Event type: {}'.format(context.event_type))
    print('Bucket: {}'.format(event['bucket']))
    print('File: {}'.format(event['name']))
    print('Metageneration: {}'.format(event['metageneration']))
    print('Created: {}'.format(event['timeCreated']))
    print('Updated: {}'.format(event['updated']))

Go

 

// Package helloworld provides a set of Cloud Functions samples.
package helloworld

import (
	"context"
	"fmt"
	"log"
	"time"

	"cloud.google.com/go/functions/metadata"
)

// GCSEvent is the payload of a GCS event.
type GCSEvent struct {
	Kind                    string                 `json:"kind"`
	ID                      string                 `json:"id"`
	SelfLink                string                 `json:"selfLink"`
	Name                    string                 `json:"name"`
	Bucket                  string                 `json:"bucket"`
	Generation              string                 `json:"generation"`
	Metageneration          string                 `json:"metageneration"`
	ContentType             string                 `json:"contentType"`
	TimeCreated             time.Time              `json:"timeCreated"`
	Updated                 time.Time              `json:"updated"`
	TemporaryHold           bool                   `json:"temporaryHold"`
	EventBasedHold          bool                   `json:"eventBasedHold"`
	RetentionExpirationTime time.Time              `json:"retentionExpirationTime"`
	StorageClass            string                 `json:"storageClass"`
	TimeStorageClassUpdated time.Time              `json:"timeStorageClassUpdated"`
	Size                    string                 `json:"size"`
	MD5Hash                 string                 `json:"md5Hash"`
	MediaLink               string                 `json:"mediaLink"`
	ContentEncoding         string                 `json:"contentEncoding"`
	ContentDisposition      string                 `json:"contentDisposition"`
	CacheControl            string                 `json:"cacheControl"`
	Metadata                map[string]interface{} `json:"metadata"`
	CRC32C                  string                 `json:"crc32c"`
	ComponentCount          int                    `json:"componentCount"`
	Etag                    string                 `json:"etag"`
	CustomerEncryption      struct {
		EncryptionAlgorithm string `json:"encryptionAlgorithm"`
		KeySha256           string `json:"keySha256"`
	}
	KMSKeyName    string `json:"kmsKeyName"`
	ResourceState string `json:"resourceState"`
}

// HelloGCS consumes a GCS event.
func HelloGCS(ctx context.Context, e GCSEvent) error {
	meta, err := metadata.FromContext(ctx)
	if err != nil {
		return fmt.Errorf("metadata.FromContext: %v", err)
	}
	log.Printf("Event ID: %v\n", meta.EventID)
	log.Printf("Event type: %v\n", meta.EventType)
	log.Printf("Bucket: %v\n", e.Bucket)
	log.Printf("File: %v\n", e.Name)
	log.Printf("Metageneration: %v\n", e.Metageneration)
	log.Printf("Created: %v\n", e.TimeCreated)
	log.Printf("Updated: %v\n", e.Updated)
	return nil
}

자바

import com.google.cloud.functions.BackgroundFunction;
import com.google.cloud.functions.Context;
import functions.eventpojos.GcsEvent;
import java.util.logging.Logger;

public class HelloGcs implements BackgroundFunction<GcsEvent> {
  private static final Logger logger = Logger.getLogger(HelloGcs.class.getName());

  @Override
  public void accept(GcsEvent event, Context context) {
    logger.info("Event: " + context.eventId());
    logger.info("Event Type: " + context.eventType());
    logger.info("Bucket: " + event.getBucket());
    logger.info("File: " + event.getName());
    logger.info("Metageneration: " + event.getMetageneration());
    logger.info("Created: " + event.getTimeCreated());
    logger.info("Updated: " + event.getUpdated());
  }
}

C#

using CloudNative.CloudEvents;
using Google.Cloud.Functions.Framework;
using Google.Events.Protobuf.Cloud.Storage.V1;
using Microsoft.Extensions.Logging;
using System.Threading;
using System.Threading.Tasks;

namespace HelloGcs
{
    public class Function : ICloudEventFunction<StorageObjectData>
    {
        private readonly ILogger _logger;

        public Function(ILogger<Function> logger) =>
            _logger = logger;

        public Task HandleAsync(CloudEvent cloudEvent, StorageObjectData data, CancellationToken cancellationToken)
        {
            _logger.LogInformation("Event: {event}", cloudEvent.Id);
            _logger.LogInformation("Event Type: {type}", cloudEvent.Type);
            _logger.LogInformation("Bucket: {bucket}", data.Bucket);
            _logger.LogInformation("File: {file}", data.Name);
            _logger.LogInformation("Metageneration: {metageneration}", data.Metageneration);
            _logger.LogInformation("Created: {created:s}", data.TimeCreated?.ToDateTimeOffset());
            _logger.LogInformation("Updated: {updated:s}", data.Updated?.ToDateTimeOffset());
            return Task.CompletedTask;
        }
    }
}

Ruby

require "functions_framework"

FunctionsFramework.cloud_event "hello_gcs" do |event|
  # The event parameter is a CloudEvents::Event::V1 object.
  # See https://cloudevents.github.io/sdk-ruby/latest/CloudEvents/Event/V1.html
  payload = event.data

  logger.info "Event: #{event.id}"
  logger.info "Event Type: #{event.type}"
  logger.info "Bucket: #{payload['bucket']}"
  logger.info "File: #{payload['name']}"
  logger.info "Metageneration: #{payload['metageneration']}"
  logger.info "Created: #{payload['timeCreated']}"
  logger.info "Updated: #{payload['updated']}"
end

PHP


use Google\CloudFunctions\CloudEvent;

function helloGCS(CloudEvent $cloudevent)
{
    $log = fopen(getenv('LOGGER_OUTPUT') ?: 'php://stderr', 'wb');
    $data = $cloudevent->getData();
    fwrite($log, 'Event: ' . $cloudevent->getId() . PHP_EOL);
    fwrite($log, 'Event Type: ' . $cloudevent->getType() . PHP_EOL);
    fwrite($log, 'Bucket: ' . $data['bucket'] . PHP_EOL);
    fwrite($log, 'File: ' . $data['name'] . PHP_EOL);
    fwrite($log, 'Metageneration: ' . $data['metageneration'] . PHP_EOL);
    fwrite($log, 'Created: ' . $data['timeCreated'] . PHP_EOL);
    fwrite($log, 'Updated: ' . $data['updated'] . PHP_EOL);
}

배포 시 트리거 유형 지정

다음 gcloud 명령어는 object.finalize 트리거로 함수를 배포합니다.

Node.js

gcloud functions deploy helloGCS \
--runtime nodejs14 \
--trigger-resource YOUR_TRIGGER_BUCKET_NAME \
--trigger-event google.storage.object.finalize
--runtime 플래그에 다음 값을 사용하여 원하는 Node.js 버전을 지정할 수 있습니다.
  • nodejs16(미리보기)
  • nodejs14(권장)
  • nodejs12
  • nodejs10

Python

gcloud functions deploy hello_gcs \
--runtime python39 \
--trigger-resource YOUR_TRIGGER_BUCKET_NAME \
--trigger-event google.storage.object.finalize
--runtime 플래그에 다음 값을 사용하여 선호하는 Python 버전을 지정할 수 있습니다.
  • python39(권장)
  • python38
  • python37

Go

gcloud functions deploy HelloGCS \
--runtime go113 \
--trigger-resource YOUR_TRIGGER_BUCKET_NAME \
--trigger-event google.storage.object.finalize
--runtime 플래그에 다음 값을 사용하여 원하는 Go 버전을 지정할 수 있습니다.
  • go116(미리보기)
  • go113(권장)
  • go111

자바

gcloud functions deploy java-gcs-function \
--entry-point functions.HelloGcs \
--runtime java11 \
--memory 512MB \
--trigger-resource YOUR_TRIGGER_BUCKET_NAME \
--trigger-event google.storage.object.finalize

C#

gcloud functions deploy csharp-gcs-function \
--entry-point HelloGcs.Function \
--runtime dotnet3 \
--trigger-resource YOUR_TRIGGER_BUCKET_NAME \
--trigger-event google.storage.object.finalize

Ruby

gcloud functions deploy hello_gcs --runtime ruby27 \
--trigger-resource YOUR_TRIGGER_BUCKET_NAME \
--trigger-event google.storage.object.finalize
다음 값을 사용하여 --runtime 플래그에 원하는 Ruby 버전을 지정할 수 있습니다.
  • ruby27(권장)
  • ruby26

PHP

gcloud functions deploy helloGCS --runtime php74 \
--trigger-resource YOUR_TRIGGER_BUCKET_NAME \
--trigger-event google.storage.object.finalize

여기서 YOUR_TRIGGER_BUCKET_NAME은 함수가 모니터링할 Cloud Storage 버킷 이름입니다.

객체 완료

트리거 유형 값: google.storage.object.finalize

이 이벤트는 버킷에서 새로운 객체를 만들거나 기존 객체를 덮어쓰고 해당 객체의 새로운 세대를 만들면 전송됩니다.

객체 삭제

트리거 유형 값: google.storage.object.delete

이 이벤트는 객체가 영구적으로 삭제될 때 전송됩니다. 버킷의 객체 버전 관리 설정에 따라 다음과 같은 결과가 발생합니다.

  • 버전 관리 버킷의 경우 버전이 영구적으로 삭제될 때에만 전송됩니다(객체를 보관처리할 때는 전송되지 않음).

  • 버전 관리 버킷이 아닌 경우 객체가 삭제되거나 덮어쓰여질 때 전송됩니다.

객체 보관처리

트리거 유형 값: google.storage.object.archive

이 이벤트는 객체의 서비스 중인 버전이 보관처리되거나 삭제될 때 전송됩니다.

이 이벤트는 버전 관리 버킷인 경우에만 전송됩니다.

객체 메타데이터 업데이트

트리거 유형 값: google.storage.object.metadataUpdate

이 이벤트는 기존 객체의 메타데이터가 변경될 때 전송됩니다.

이벤트 구조

스토리지 이벤트 데이터는 Cloud Storageobject 형식으로 제공됩니다.

이벤트 전송 메커니즘

이벤트는 Cloud Storage의 Pub/Sub 알림을 사용하여 전송됩니다.

알림 한도

특정 이벤트에 트리거되는 알림 구성은 10개까지 사용할 수 있습니다. 동일한 버킷에 알림을 너무 많이 설정하면 버킷의 알림 한도가 초과되어 다음과 같은 오류가 표시되면서 함수를 만들 수 없게 됩니다.

Cloud Storage bucket ...: Pub/Sub notification limit reached

한도에 도달하면 알림 삭제와 같은 구제 조치를 취할 때까지 함수를 만들 수 없습니다.

Cloud Storage의 할당량 및 요청 한도에 대해 자세히 알아보세요.

권한

알림을 수신할 프로젝트에 대한 충분한 권한이 있어야 합니다. 다음 작업도 함께 수행해야 합니다.

  1. Cloud Storage 버킷을 포함하고 있는 프로젝트와 연관된 서비스 에이전트의 이메일 주소를 확인합니다.

  2. 이전 단계에서 가져온 이메일 주소를 사용하여 관련된 Pub/Sub 주제의 IAM 역할 pubsub.publisher를 서비스 계정에 부여합니다.

Cloud Storage용 Pub/Sub 알림 구성에 대해 자세히 알아보기

기존 Cloud Storage 트리거

아래의 gcloud 명령어는 특정 버킷의 기존 객체 변경 알림에 의해 트리거되는 함수를 배포합니다. 일반적으로 Cloud Pub/Sub 알림은 객체 변경 알림보다 사용이 더욱 쉽고 유연하며 강력합니다. 그러나 이러한 기존 알림은 이미 해당 이벤트를 사용하는 기존 함수에서 사용할 수 있습니다.

gcloud functions deploy YOUR_FUNCTION_NAME \
--trigger-resource YOUR_TRIGGER_BUCKET_NAME \
--trigger-event providers/cloud.storage/eventTypes/object.change \
FLAGS...
인수 설명
--trigger-resource NAME 함수가 변경 여부를 감시하는 Cloud Storage 버킷의 이름입니다.
--trigger-event NAME 함수가 수신할 이벤트 유형 이름입니다. 이 경우에는 기존 object.change 이벤트입니다.
FLAGS... 배포 시 --runtime과 같이 추가 플래그를 지정해야 합니다. 전체 참조를 보려면 gcloud functions deploy 문서를 참조하세요.

다음 단계

Cloud Storage에 의해 트리거되는 이벤트 기반 함수를 구현하는 방법은 Cloud Storage 튜토리얼을 참조하세요.