Cloud Storage에 있는 파일과 폴더의 업로드, 업데이트 또는 삭제에 대한 응답으로 함수를 트리거할 수 있습니다.
이 페이지의 예시는 Cloud Storage에 이미지 파일이 업로드되면 트리거되는 샘플 함수를 기반으로 한 것입니다. 이 샘플 함수는 이벤트 속성에 액세스하는 방법, 파일을 Cloud Functions 인스턴스에 다운로드하는 방법 및 Cloud Storage 이벤트 처리에 관한 기타 기본사항을 다룹니다.
전체 샘플을 빌드하려면 Firebase Admin SDK 및 이미지 처리 도구의 종속 항목도 추가합니다.
Node.js
const{initializeApp}=require("firebase-admin/app");const{getStorage}=require("firebase-admin/storage");constlogger=require("firebase-functions/logger");constpath=require("path");// library for image resizingconstsharp=require("sharp");initializeApp();
다음 패턴을 사용하여 함수의 범위를 특정 Cloud Storage 버킷으로 설정하고 원하는 옵션을 설정합니다.
Node.js
// scope handler to a specific bucket, using storage options parameterexports.archivedopts=onObjectArchived({bucket:"myBucket"},(event)=>{//…});
Python
# Scope handler to a specific bucket using storage options parameter@storage_fn.on_object_archived(bucket="myBucket")defarchived_bucket(event:storage_fn.CloudEvent[storage_fn.StorageObjectData]):# ...
위치가 일치하지 않으면 배포가 실패할 수 있습니다. 또한 Cloud Storage 버킷 위치와 함수 위치 사이의 거리로 인해 상당한 네트워크 지연 시간이 발생할 수 있습니다. 이러한 상황을 방지하려면 다음 중 한 가지 방식으로 버킷/트리거 위치와 일치하도록 함수 위치를 지정합니다.
함수 위치가 트리거 위치와 동일합니다.
함수 위치가 트리거 위치 내에 있습니다(트리거 리전이 이중/멀티 리전인 경우).
트리거 리전이 us-central1로 설정되어 있으면 함수가 모든 위치에 있을 수 있습니다.
Cloud Storage 이벤트 처리
Cloud Storage 이벤트에 응답하는 다음 핸들러를 사용할 수 있습니다.
Node.js
onObjectArchived: 버킷에서 객체 버전 관리를 사용 설정한 경우에만 전송됩니다.
이 이벤트는 객체를 보관처리했거나 이름이 동일한 객체를 업로드하여 덮어씀으로써 객체의 서비스 중인 버전이 보관처리 버전이 되었음을 나타냅니다.
onObjectDeleted: 객체가 영구 삭제되면 전송됩니다. 여기에는 덮어썼거나 버킷 수명 주기 구성에 따라 삭제된 객체가 포함됩니다.
객체 버전 관리를 사용 설정한 버킷에서는 객체를 보관처리(onArchive 참조)할 때 storage.objects.delete 메서드를 통해 보관처리했더라도 이 이벤트가 전송되지 않습니다.
onObjectFinalized: 버킷에서 새 객체나 기존 객체의 새 세대를 만들면 전송됩니다. 여기에는 기존 객체 복사나 재작성이 포함됩니다. 실패한 업로드는 이 이벤트를 트리거하지 않습니다.
onMetadataUpdated: 기존 객체의 메타데이터가 변경되면 전송됩니다.
Python
on_object_archived: 버킷에서 객체 버전 관리를 사용 설정한 경우에만 전송됩니다.
이 이벤트는 객체를 보관처리했거나 이름이 동일한 객체를 업로드하여 덮어씀으로써 객체의 서비스 중인 버전이 보관처리 버전이 되었음을 나타냅니다.
on_object_deleted: 객체가 영구 삭제되면 전송됩니다. 여기에는 덮어썼거나 버킷 수명 주기 구성에 따라 삭제된 객체가 포함됩니다.
객체 버전 관리를 사용 설정한 버킷에서는 객체를 보관처리(onArchive 참조)할 때 storage.objects.delete 메서드를 통해 보관처리했더라도 이 이벤트가 전송되지 않습니다.
on_object_finalized: 버킷에서 새 객체나 기존 객체의 새 세대를 만들면 전송됩니다. 여기에는 기존 객체 복사나 재작성이 포함됩니다. 실패한 업로드는 이 이벤트를 트리거하지 않습니다.
on_metadata_updated: 기존 객체의 메타데이터가 변경되면 전송됩니다.
Cloud Storage 객체 속성에 액세스
Cloud Functions는 업데이트된 파일의 객체 크기 및 콘텐츠 유형과 같은 여러 Cloud Storage 객체 속성을 노출합니다. 객체의 메타데이터가 변경될 때마다 metageneration 속성이 증가합니다. 새 객체의 경우 metageneration 값이 1입니다.
Node.js
constfileBucket=event.data.bucket;// Storage bucket containing the file.constfilePath=event.data.name;// File path in the bucket.constcontentType=event.data.contentType;// File content type.
썸네일 이미지 생성 샘플에서는 이러한 속성 중 일부를 사용하여 함수가 다음과 같은 값을 반환하는 종료 사례를 감지합니다.
Node.js
// Exit if this is triggered on a file that is not an image.if(!contentType.startsWith("image/")){returnlogger.log("This is not an image.");}// Exit if the image is already a thumbnail.constfileName=path.basename(filePath);if(fileName.startsWith("thumb_")){returnlogger.log("Already a Thumbnail.");}
# Exit if this is triggered on a file that is not an image.ifnotcontent_typeornotcontent_type.startswith("image/"):print(f"This is not an image. ({content_type})")return# Exit if the image is already a thumbnail.iffile_path.name.startswith("thumb_"):print("Already a thumbnail.")return
간혹 Cloud Storage에서 파일을 다운로드할 필요가 없는 경우도 있습니다. 하지만 Cloud Storage에 저장된 파일로 썸네일 이미지를 생성하는 것과 같은 집중적인 작업을 수행하려면 함수 인스턴스(즉, 코드를 실행하는 가상 머신)에 파일을 다운로드해야 합니다.
Cloud Functions를 Node.js용 sharp, Python용 Pillow와 같은 이미지 처리 프로그램과 함께 사용하면 그래픽 이미지 파일을 조작할 수 있습니다. 다음은 업로드된 이미지 파일의 썸네일 이미지를 만드는 방법의 예시입니다.
Node.js
/** * When an image is uploaded in the Storage bucket, * generate a thumbnail automatically using sharp. */exports.generateThumbnail=onObjectFinalized({cpu:2},async(event)=>{constfileBucket=event.data.bucket;// Storage bucket containing the file.constfilePath=event.data.name;// File path in the bucket.constcontentType=event.data.contentType;// File content type.// Exit if this is triggered on a file that is not an image.if(!contentType.startsWith("image/")){returnlogger.log("This is not an image.");}// Exit if the image is already a thumbnail.constfileName=path.basename(filePath);if(fileName.startsWith("thumb_")){returnlogger.log("Already a Thumbnail.");}// Download file into memory from bucket.constbucket=getStorage().bucket(fileBucket);constdownloadResponse=awaitbucket.file(filePath).download();constimageBuffer=downloadResponse[0];logger.log("Image downloaded!");// Generate a thumbnail using sharp.constthumbnailBuffer=awaitsharp(imageBuffer).resize({width:200,height:200,withoutEnlargement:true,}).toBuffer();logger.log("Thumbnail created");// Prefix 'thumb_' to file name.constthumbFileName=`thumb_${fileName}`;constthumbFilePath=path.join(path.dirname(filePath),thumbFileName);// Upload the thumbnail.constmetadata={contentType:contentType};awaitbucket.file(thumbFilePath).save(thumbnailBuffer,{metadata:metadata,});returnlogger.log("Thumbnail uploaded!");});
Cloud Functions 인스턴스의 임시 디렉터리에 파일을 다운로드합니다. 이 위치에서 필요에 따라 파일을 처리한 다음 Cloud Storage에 업로드할 수 있습니다. 비동기
작업을 수행하는 경우 콜백에서 JavaScript 프로미스를 반환해야
합니다.
Python
@storage_fn.on_object_finalized()defgeneratethumbnail(event:storage_fn.CloudEvent[storage_fn.StorageObjectData]):"""When an image is uploaded in the Storage bucket, generate a thumbnail automatically using Pillow."""bucket_name=event.data.bucketfile_path=pathlib.PurePath(event.data.name)content_type=event.data.content_type# Exit if this is triggered on a file that is not an image.ifnotcontent_typeornotcontent_type.startswith("image/"):print(f"This is not an image. ({content_type})")return# Exit if the image is already a thumbnail.iffile_path.name.startswith("thumb_"):print("Already a thumbnail.")returnbucket=storage.bucket(bucket_name)image_blob=bucket.blob(str(file_path))image_bytes=image_blob.download_as_bytes()image=Image.open(io.BytesIO(image_bytes))image.thumbnail((200,200))thumbnail_io=io.BytesIO()image.save(thumbnail_io,format="png")thumbnail_path=file_path.parent/pathlib.PurePath(f"thumb_{file_path.stem}.png")thumbnail_blob=bucket.blob(str(thumbnail_path))thumbnail_blob.upload_from_string(thumbnail_io.getvalue(),content_type="image/png")
[null,null,["최종 업데이트: 2025-08-20(UTC)"],[],[],null,["\u003cbr /\u003e\n\n2nd gen 1st gen \n\nYou can trigger a function in response to the uploading, updating, or\ndeleting of files and folders in Cloud Storage.\n\nExamples in this page are based on a sample function that triggers when image\nfiles are uploaded to Cloud Storage. This sample function demonstrates\nhow to access event attributes, how to download a file to a Cloud Functions\ninstance, and other fundamentals of handling Cloud Storage events.\n\nFor more examples of use cases, see\n[What can I do with Cloud Functions?](/docs/functions/use-cases)\n\nTrigger a function on Cloud Storage changes\n\nUse [`functions.storage`](/docs/reference/functions/firebase-functions.storage)\nto create a function that handles\nCloud Storage events. Depending on whether you want to scope your\nfunction to a specific Cloud Storage bucket or use the default\nbucket, use one of the following:\n\n- [`functions.storage.object()`](/docs/reference/functions/firebase-functions.storage#storageobject) to listen for object changes on the default Cloud Storage bucket.\n- [`functions.storage.bucket('bucketName').object()`](/docs/reference/functions/firebase-functions.storage#storagebucket) to listen for object changes on a specific bucket.\n\nFor example, the thumbnail generator sample is scoped to the default bucket for\nthe project:\n\n\u003cbr /\u003e\n\n```gdscript\nexports.firstGenGenerateThumbnail = functions.storage.object().onFinalize(async (object) =\u003e {\n // ...\n});\n```\n\n\u003cbr /\u003e\n\n| **Important:** Distance between the location of a Cloud Storage bucket and the location of the function can create significant network latency. To optimize performance, consider specifying the [function location](/docs/functions/locations) where applicable.\n\nCloud Storage supports these events:\n\n- `onArchive` Only sent when a bucket has enabled [object versioning](https://cloud.google.com/storage/docs/object-versioning). This event indicates that the live version of an object has become an archived version, either because it was archived or because it was overwritten by the upload of an object of the same name.\n- `onDelete` Sent when an object has been permanently deleted. This includes objects that are overwritten or are deleted as part of the bucket's [lifecycle configuration](https://cloud.google.com/storage/docs/lifecycle). For buckets with [object versioning](https://cloud.google.com/storage/docs/object-versioning) enabled, this is not sent when an object is archived (see `onArchive`), even if archival occurs via the `storage.objects.delete` method.\n- `onFinalize` Sent when a new object (or a new generation of an existing object) is successfully created in the bucket. This includes copying or rewriting an existing object. A failed upload does not trigger this event.\n- `onMetadataUpdate` Sent when the metadata of an existing object changes.\n\nSet the event within the `on` event handler as shown above for `onFinalize`.\n\nAccess Cloud Storage object attributes\n\nCloud Functions exposes a number of Cloud Storage object attributes such\nas\n[`size`](/docs/reference/functions/firebase-functions.storage#storageobjectmetadatasize)\nand\n[`contentType`](/docs/reference/functions/firebase-functions.storage.objectmetadata#storageobjectmetadatacontenttype)\nfor the file updated. The\n['metageneration'](/docs/reference/functions/firebase-functions.storage.objectmetadata#storageobjectmetadatametageneration)\nattribute is incremented whenever there's a change to the\nobject's metadata. For new objects, the `metageneration` value is `1`.\n\n\u003cbr /\u003e\n\n```gdscript\nconst fileBucket = object.bucket; // The Storage bucket that contains the file.\nconst filePath = object.name; // File path in the bucket.\nconst contentType = object.contentType; // File content type.https://github.com/firebase/functions-samples/blob/c4fde45b65fab584715e786ce3264a6932d996ec/Node-1st-gen/quickstarts/thumbnails/functions/index.js#L37-L39\n```\n\n\u003cbr /\u003e\n\nThe thumbnail generation sample uses some of these attributes to detect exit\ncases in which the function returns: \n\n```gdscript\n// Exit if this is triggered on a file that is not an image.\nif (!contentType.startsWith('image/')) {\n return functions.logger.log('This is not an image.');\n}\n\n// Get the file name.\nconst fileName = path.basename(filePath);\n// Exit if the image is already a thumbnail.\nif (fileName.startsWith('thumb_')) {\n return functions.logger.log('Already a Thumbnail.');\n}https://github.com/firebase/functions-samples/blob/c4fde45b65fab584715e786ce3264a6932d996ec/Node-1st-gen/quickstarts/thumbnails/functions/index.js#L43-L53\n```\n\nDownload, transform, and upload a file\n\nFor some cases, it may not be necessary to download files from\nCloud Storage. However, to perform intensive tasks such as generating a\nthumbnail image from a file stored in Cloud Storage, you need to download\nfiles to the functions instance---that is, the virtual machine that runs\nyour code.\n\nTo easily download and re-upload objects to Cloud Storage, install the\n[Google Cloud Storage\npackage](//www.npmjs.com/package/@google-cloud/storage) using\n`npm install --save @google-cloud/storage`, and import it. To use JavaScript\npromises to handle external processes like the thumbnail processing tasks in the\nsample, also import `child-process-promise`:\n\n\u003cbr /\u003e\n\n```gdscript\nconst functions = require('firebase-functions/v1');\nconst admin = require('firebase-admin');\nadmin.initializeApp()\nconst path = require('path');\n\n//library for resizing images\nconst sharp = require('sharp');https://github.com/firebase/functions-samples/blob/c4fde45b65fab584715e786ce3264a6932d996ec/Node-1st-gen/quickstarts/thumbnails/functions/index.js#L19-L25\n```\n\n\u003cbr /\u003e\n\nUse `gcs.bucket.file(filePath).download` to download a file to a temporary\ndirectory on your Cloud Functions instance. In this location, you can\nprocess the file as needed and then upload to Cloud Storage. When\nperforming asynchronous tasks, make sure you return a JavaScript promise in your\ncallback.\n\nExample: image transformation\n\nUsing Cloud Functions together with image-processing programs like\n[`sharp`](https://sharp.pixelplumbing.com/), you can perform\nmanipulations on graphical image files. The following is an example of how to\ncreate a thumbnail image for an uploaded image file:\n\n\u003cbr /\u003e\n\n```gdscript\n// Download file from bucket.\nconst bucket = admin.storage().bucket(fileBucket);\nconst metadata = {\n contentType: contentType,\n};\nconst downloadResponse = await bucket.file(filePath).download();\nconst imageBuffer = downloadResponse[0];\nfunctions.logger.log(\"Image downloaded!\");\n\n// Generate a thumbnail using sharp.\nconst thumbnailBuffer = await sharp(imageBuffer).resize({\n width: 200,\n height: 200,\n withoutEnlargement: true,\n}).toBuffer();\nfunctions.logger.log(\"Thumbnail created\");\n\n// Upload the thumbnail with a 'thumb_' prefix.\nconst thumbFileName = `thumb_${fileName}`;\nconst thumbFilePath = path.join(path.dirname(filePath), thumbFileName);\nawait bucket.file(thumbFilePath).save(thumbnailBuffer, {\n metadata: metadata,\n});\nreturn functions.logger.log(\"Thumbnail uploaded!\");https://github.com/firebase/functions-samples/blob/c4fde45b65fab584715e786ce3264a6932d996ec/Node-1st-gen/quickstarts/thumbnails/functions/index.js#L57-L80\n```\n\n\u003cbr /\u003e\n\nThis code creates a\n200x200 thumbnail for the image saved in a temporary directory, then uploads it\nback to Cloud Storage.\n\nExplore more examples\n\nMore examples of common media transformation functions including\n[transcoding images](https://github.com/firebase/functions-samples/tree/main/Node-1st-gen/convert-images),\n[moderating content](https://github.com/firebase/functions-samples/tree/main/Node-1st-gen/moderate-images),\n[extracting EXIF metadata](https://github.com/firebase/functions-samples/tree/main/Node-1st-gen/exif-images).\nThe [full list of examples](https://github.com/firebase/functions-samples) is\navailable on GitHub."]]