1. 개요
이 코드 랩에서는 Cloud Run에서 이벤트를 수신하는 새로운 서비스인 Eventarc에 의해 트리거되는 새로운 Cloud Run 서비스인 이미지 가비지 컬렉터를 만듭니다. 사진이 사진 버킷에서 삭제되면 서비스는 Eventarc에서 이벤트를 수신합니다. 그런 다음 썸네일 버킷에서 이미지를 삭제하고 Firestore 사진 컬렉션에서도 삭제합니다.

학습할 내용
- Cloud Run
- Cloud Storage
- Cloud Firestore
- Eventarc
2. 설정 및 요구사항
자습형 환경 설정
- Google Cloud Console에 로그인하여 새 프로젝트를 만들거나 기존 프로젝트를 재사용합니다. 아직 Gmail이나 Google Workspace 계정이 없는 경우 계정을 만들어야 합니다.



- 프로젝트 이름은 이 프로젝트 참가자의 표시 이름입니다. 이는 Google API에서 사용하지 않는 문자열이며 언제든지 업데이트할 수 있습니다.
- 프로젝트 ID는 모든 Google Cloud 프로젝트에서 고유해야 하며, 변경할 수 없습니다(설정된 후에는 변경할 수 없음). Cloud Console은 고유한 문자열을 자동으로 생성합니다. 일반적으로 신경 쓰지 않아도 됩니다. 대부분의 Codelab에서는 프로젝트 ID를 참조해야 하며(일반적으로
PROJECT_ID로 식별됨), 마음에 들지 않는 경우 임의로 다시 생성하거나 직접 지정해서 사용할 수 있는지 확인하세요. 프로젝트가 생성되면 프로젝트 ID가 '고정'됩니다. - 세 번째 값은 일부 API에서 사용하는 프로젝트 번호입니다. 이 세 가지 값에 대한 자세한 내용은 문서를 참조하세요.
- 다음으로 Cloud 리소스/API를 사용하려면 Cloud Console에서 결제를 사용 설정해야 합니다. 이 Codelab 실행에는 많은 비용이 들지 않습니다. 이 튜토리얼을 마친 후 비용이 결제되지 않도록 리소스를 종료하려면 Codelab의 끝에 있는 '삭제' 안내를 따르세요. Google Cloud 새 사용자에게는 미화 $300 상당의 무료 체험판 프로그램에 참여할 수 있는 자격이 부여됩니다.
Cloud Shell 시작
Google Cloud를 노트북에서 원격으로 실행할 수 있지만, 이 Codelab에서는 Cloud에서 실행되는 명령줄 환경인 Google Cloud Shell을 사용합니다.
GCP 콘솔에서 오른쪽 상단 툴바의 Cloud Shell 아이콘을 클릭합니다.

환경을 프로비저닝하고 연결하는 데 몇 분 정도 소요됩니다. 완료되면 다음과 같이 표시됩니다.

가상 머신에는 필요한 개발 도구가 모두 들어있습니다. 영구적인 5GB 홈 디렉토리를 제공하고 Google Cloud에서 실행되므로 네트워크 성능과 인증이 크게 개선됩니다. 이 실습의 모든 작업은 브라우저만으로 수행할 수 있습니다.
3. Eventarc 소개
Eventarc를 사용하면 다양한 소스의 이벤트를 Cloud Run 서비스에 쉽게 연결할 수 있습니다. 이벤트 수집, 전송, 보안, 승인, 오류 처리를 자동으로 처리합니다.

Google Cloud 소스 및 Cloud Pub/Sub에 게시하는 맞춤 애플리케이션에서 이벤트를 가져와 Google Cloud Run 싱크로 전송할 수 있습니다.
다양한 Google Cloud 소스의 이벤트는 Cloud 감사 로그를 통해 전송됩니다. 이러한 소스의 이벤트 전송 지연 시간과 가용성은 Cloud 감사 로그의 지연 시간과 가용성에 연결됩니다. Google Cloud 소스의 이벤트가 발생할 때마다 해당 Cloud 감사 로그 항목이 생성됩니다.
Cloud Pub/Sub에 게시하는 맞춤 애플리케이션은 원하는 형식으로 Pub/Sub 주제에 메시지를 게시할 수 있습니다.
이벤트 트리거는 어떤 싱크에 어떤 이벤트를 전송할지 지정하는 필터링 메커니즘입니다.
모든 이벤트는 서비스 간 상호 운용성을 위해 CloudEvents v1.0 형식으로 전송됩니다.
4. 시작하기 전에
API 사용 설정
Cloud Run 서비스를 트리거하려면 Eventarc 서비스가 필요합니다. 사용 설정되어 있는지 확인합니다.
gcloud services enable eventarc.googleapis.com
작업이 성공적으로 완료됩니다.
Operation "operations/acf.5c5ef4f6-f734-455d-b2f0-ee70b5a17322" finished successfully.
서비스 계정 구성
트리거에서 기본 컴퓨팅 서비스 계정이 사용됩니다. 기본 컴퓨팅 서비스 계정에 eventarc.eventReceiver 역할을 부여합니다.
PROJECT_NUMBER=$(gcloud projects describe $GOOGLE_CLOUD_PROJECT --format='value(projectNumber)')
gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
--member serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com \
--role roles/eventarc.eventReceiver
Cloud Storage 서비스 계정에 pubsub.publisher 역할을 부여합니다. Eventarc Cloud Storage 트리거에는 다음이 필요합니다.
SERVICE_ACCOUNT=$(gsutil kms serviceaccount -p $PROJECT_NUMBER)
gcloud projects add-iam-policy-binding $PROJECT_NUMBER \
--member serviceAccount:$SERVICE_ACCOUNT \
--role roles/pubsub.publisher
2021년 4월 8일 이전에 Pub/Sub 서비스 계정을 사용 설정한 경우 Pub/Sub 서비스 계정에 iam.serviceAccountTokenCreator 역할을 부여합니다.
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member serviceAccount:service-$PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com \ --role roles/iam.serviceAccountTokenCreator
5. 코드 클론
이전 코드 랩에서 아직 코드를 클론하지 않은 경우 다음을 실행하여 클론합니다.
git clone https://github.com/GoogleCloudPlatform/serverless-photosharing-workshop
그런 다음 서비스가 포함된 디렉터리로 이동할 수 있습니다.
cd serverless-photosharing-workshop/services/garbage-collector/nodejs
서비스의 파일 레이아웃은 다음과 같습니다.
services
|
├── garbage-collector
|
├── nodejs
|
├── index.js
├── package.json
폴더 안에는 다음 3개의 파일이 있습니다.
index.js에는 Node.js 코드가 포함되어 있습니다.package.json은 라이브러리 종속 항목을 정의합니다.
6. 코드 살펴보기
종속 항목
package.json 파일은 필요한 라이브러리 종속 항목을 정의합니다.
{
"name": "garbage_collector_service",
"version": "0.0.1",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"cloudevents": "^4.0.1",
"express": "^4.17.1",
"@google/events": "^3.1.0",
"@google-cloud/firestore": "^4.9.9",
"@google-cloud/storage": "^5.8.3"
}
}
Cloud Storage 내에서 이미지를 삭제하려면 Cloud Storage 라이브러리가 필요합니다. 이전에 저장한 사진 메타데이터도 삭제하기 위해 Cloud Firestore에 대한 종속 항목을 선언합니다. 또한 Eventarc에서 전송한 CloudEvents를 읽기 위해 CloudEvents SDK 및 Google Events 라이브러리를 사용합니다. Express는 JavaScript / Node 웹 프레임워크입니다. Bluebird는 프로미스를 처리하는 데 사용됩니다.
index.js
index.js 코드를 자세히 살펴보겠습니다.
const express = require('express');
const {Storage} = require('@google-cloud/storage');
const Firestore = require('@google-cloud/firestore');
const { HTTP } = require("cloudevents");
const {toStorageObjectData} = require('@google/events/cloud/storage/v1/StorageObjectData');
프로그램을 실행하는 데 필요한 다양한 종속 항목이 필요합니다. Express는 사용할 Node 웹 프레임워크이고, Bluebird는 JavaScript 프로미스를 처리하는 라이브러리이며, Storage와 Firestore는 각각 Google Cloud Storage (이미지 버킷) 및 Cloud Firestore 데이터 저장소와 함께 작동합니다. 또한 Google 이벤트 라이브러리에서 Eventarc StoreObjectData가 전송한 CloudEvent를 읽어 CloudEvent의 Cloud Storage 이벤트 본문을 읽으려면 CloudEvent가 필요합니다.
const app = express();
app.use(express.json());
app.post('/', async (req, res) => {
try {
const cloudEvent = HTTP.toEvent({ headers: req.headers, body: req.body });
console.log(cloudEvent);
/* ... */
} catch (err) {
console.log(`Error: ${err}`);
res.status(500).send(err);
}
});
위에는 Node 핸들러의 구조가 나와 있습니다. 앱이 HTTP POST 요청에 응답합니다. HTTP 요청에서 CloudEvent를 읽고 문제가 발생할 경우를 대비해 약간의 오류 처리를 수행합니다. 이제 이 구조체 내부를 살펴보겠습니다.
다음 단계는 CloudEvent 본문을 가져와 파싱하고 객체 이름을 가져오는 것입니다.
const storageObjectData = toStorageObjectData(cloudEvent.data);
console.log(storageObjectData);
const objectName = storageObjectData.name;
이미지 이름을 알면 썸네일 버킷에서 삭제할 수 있습니다.
try {
await storage.bucket(bucketThumbnails).file(objectName).delete();
console.log(`Deleted '${objectName}' from bucket '${bucketThumbnails}'.`);
}
catch(err) {
console.log(`Failed to delete '${objectName}' from bucket '${bucketThumbnails}': ${err}.`);
}
마지막 단계로 Firestore 컬렉션에서도 사진 메타데이터를 삭제합니다.
try {
const pictureStore = new Firestore().collection('pictures');
const docRef = pictureStore.doc(objectName);
await docRef.delete();
console.log(`Deleted '${objectName}' from Firestore collection 'pictures'`);
}
catch(err) {
console.log(`Failed to delete '${objectName}' from Firestore: ${err}.`);
}
res.status(200).send(`Processed '${objectName}'.`);
이제 Node 스크립트가 수신 요청을 수신 대기하도록 설정할 차례입니다. 또한 필수 환경 변수가 설정되었는지 확인합니다.
app.listen(PORT, () => {
if (!bucketThumbnails) throw new Error("BUCKET_THUMBNAILS not set");
console.log(`Started service on port ${PORT}`);
});
7. 로컬에서 테스트
클라우드에 배포하기 전에 코드가 작동하는지 로컬에서 테스트합니다.
garbage-collector/nodejs 폴더 내에서 npm 종속 항목을 설치하고 서버를 시작합니다.
export BUCKET_THUMBNAILS=thumbnails-$GOOGLE_CLOUD_PROJECT npm install; npm start
모든 것이 잘 진행되면 포트 8080에서 서버가 시작됩니다.
Started service on port 8080
종료하려면 CTRL-C을 사용합니다.
8. 빌드 및 Cloud Run에 배포
Cloud Run에 배포하기 전에 Cloud Run 리전을 지원되는 리전 중 하나로 설정하고 플랫폼을 managed로 설정합니다.
REGION=europe-west1 gcloud config set run/region $REGION gcloud config set run/platform managed
구성이 설정되었는지 확인할 수 있습니다.
gcloud config list ... [run] platform = managed region = europe-west1
Cloud Build를 사용하여 컨테이너 이미지를 수동으로 빌드하고 게시하는 대신 Cloud Run에서 Google Cloud Buildpacks를 사용하여 컨테이너 이미지를 빌드하도록 할 수도 있습니다.
다음 명령어를 실행하여 Google Cloud Buildpack을 사용하여 컨테이너 이미지를 빌드한 다음 컨테이너 이미지를 Cloud Run에 배포합니다.
SERVICE_NAME=garbage-collector-service
gcloud run deploy $SERVICE_NAME \
--source . \
--no-allow-unauthenticated \
--update-env-vars BUCKET_THUMBNAILS=$BUCKET_THUMBNAILS
–-source 플래그를 확인합니다. 이렇게 하면 Cloud Run이 Google Cloud Buildpacks를 사용하여 Dockerfile. 없이 컨테이너 이미지를 빌드하도록 플래그가 지정됩니다. --no-allow-unauthenticated 플래그는 Cloud Run 서비스를 특정 서비스 계정에서만 트리거되는 내부 서비스로 만듭니다. 나중에 run.invoker 역할이 있는 기본 Compute 서비스 계정으로 트리거를 만들어 내부 Cloud Run 서비스를 호출합니다.
9. 트리거 만들기
Eventarc에서 트리거는 어떤 서비스가 어떤 종류의 이벤트를 수신해야 하는지 정의합니다. 이 경우 서비스가 버킷에서 파일이 삭제될 때 이벤트를 수신하도록 해야 합니다.
업로드된 사진 버킷과 동일한 리전에 트리거의 위치를 설정합니다.
gcloud config set eventarc/location eu
감사 로그 트리거를 만들어 storage.objects.delete 이벤트를 필터링하고 Cloud Run 서비스로 전송합니다.
BUCKET_IMAGES=uploaded-pictures-$GOOGLE_CLOUD_PROJECT gcloud eventarc triggers create trigger-$SERVICE_NAME \ --destination-run-service=$SERVICE_NAME \ --destination-run-region=$REGION \ --event-filters="type=google.cloud.storage.object.v1.deleted" \ --event-filters="bucket=$BUCKET_IMAGES" \ --service-account=$PROJECT_NUMBER-compute@developer.gserviceaccount.com
다음 명령어를 사용하여 트리거가 생성되었는지 다시 확인할 수 있습니다.
gcloud eventarc triggers list
10. 서비스 테스트
서비스가 작동하는지 테스트하려면 uploaded-pictures 버킷으로 이동하여 사진 중 하나를 삭제합니다. 서비스 로그를 보면 thumbnails 버킷에서 관련 사진이 삭제되었고 pictures Firestore 컬렉션에서도 문서가 삭제되었음을 알 수 있습니다.

11. 정리(선택 사항)
이 시리즈의 다른 실습을 계속하지 않으려는 경우 리소스를 정리하여 비용을 절감하고 전반적으로 클라우드를 효율적으로 사용할 수 있습니다. 다음과 같이 개별적으로 리소스를 정리할 수 있습니다.
서비스 삭제:
gcloud run services delete $SERVICE_NAME -q
Eventarc 트리거를 삭제합니다.
gcloud eventarc triggers delete trigger-$SERVICE_NAME -q
또는 전체 프로젝트를 삭제할 수 있습니다.
gcloud projects delete $GOOGLE_CLOUD_PROJECT
12. 축하합니다.
축하합니다. Cloud Run에서 이벤트를 수신하는 새로운 서비스인 Eventarc에 의해 트리거되는 Cloud Run 서비스인 이미지 가비지 컬렉터를 만들었습니다. 사진이 사진 버킷에서 삭제되면 서비스는 Eventarc에서 이벤트를 수신합니다. 그런 다음 썸네일 버킷에서 이미지를 삭제하고 Firestore 사진 컬렉션에서도 삭제합니다.
학습한 내용
- Cloud Run
- Cloud Storage
- Cloud Firestore
- Eventarc