이 Codelab 정보
1. 개요
이 Codelab에서는 Cloud Scheduler가 일정한 간격으로 트리거하는 새로운 Cloud Run 서비스인 콜라주 서비스를 만듭니다. 서비스는 업로드된 최신 사진을 가져와서 해당 사진의 콜라주를 만듭니다. Cloud Firestore에서 최근 사진 목록을 찾은 다음 Cloud Storage에서 실제 사진 파일을 다운로드합니다.
학습할 내용
- Cloud Run
- Cloud Scheduler
- Cloud Storage
- Cloud Firestore
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. API 사용 설정
Cloud Run 서비스를 정기적으로 트리거하려면 Cloud Scheduler가 필요합니다. 사용 설정되어 있는지 확인합니다.
gcloud services enable cloudscheduler.googleapis.com
작업이 성공적으로 완료됩니다.
Operation "operations/acf.5c5ef4f6-f734-455d-b2f0-ee70b5a17322" finished successfully.
4. 코드 클론
이전 Codelab에서 아직 클론하지 않았다면 코드를 클론합니다.
git clone https://github.com/GoogleCloudPlatform/serverless-photosharing-workshop
그런 다음 서비스가 포함된 디렉터리로 이동하면 됩니다.
cd serverless-photosharing-workshop/services/collage/nodejs
서비스의 파일 레이아웃은 다음과 같습니다.
services | ├── collage | ├── nodejs | ├── Dockerfile ├── index.js ├── package.json
폴더 안에는 3개의 파일이 있습니다.
index.js
에는 Node.js 코드가 포함됩니다.package.json
는 라이브러리 종속 항목을 정의합니다.Dockerfile
는 컨테이너 이미지를 정의합니다.
5. 코드 살펴보기
종속 항목
package.json
파일은 필요한 라이브러리 종속 항목을 정의합니다.
{
"name": "collage_service",
"version": "0.0.1",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"bluebird": "^3.7.2",
"express": "^4.17.1",
"imagemagick": "^0.1.3",
"@google-cloud/firestore": "^4.9.9",
"@google-cloud/storage": "^5.8.3"
}
}
Cloud Storage 라이브러리를 사용하여 Cloud Storage 내에서 이미지 파일을 읽고 저장합니다. Cloud Firestore에 대한 종속 항목을 선언하여 이전에 저장한 사진 메타데이터를 가져옵니다. Express는 JavaScript / Node 웹 프레임워크입니다. Bluebird는 Promise 처리에 사용되고 imagemagick은 이미지 조작을 위한 라이브러리입니다.
Dockerfile
Dockerfile
는 애플리케이션의 컨테이너 이미지를 정의합니다.
FROM node:14-slim
# installing Imagemagick
RUN set -ex; \
apt-get -y update; \
apt-get -y install imagemagick; \
rm -rf /var/lib/apt/lists/*
WORKDIR /picadaily/services/collage
COPY package*.json ./
RUN npm install --production
COPY . .
CMD [ "npm", "start" ]
밝은 Node 14 기본 이미지를 사용하고 있습니다. imagemagick 라이브러리를 설치하는 중입니다. 그런 다음 코드에 필요한 NPM 모듈을 설치하고 npm start로 노드 코드를 실행합니다.
index.js
index.js
코드를 자세히 살펴보겠습니다.
const express = require('express');
const imageMagick = require('imagemagick');
const Promise = require("bluebird");
const path = require('path');
const {Storage} = require('@google-cloud/storage');
const Firestore = require('@google-cloud/firestore');
프로그램을 실행하는 데 필요한 다양한 종속 항목이 필요합니다. Express는 사용할 노드 웹 프레임워크이고, ImageMagick은 이미지 조작을 위한 라이브러리, Bluebird는 JavaScript 프로미스를 처리하는 라이브러리, Path는 파일 및 디렉터리 경로를 처리하는 데 사용되며, Storage 및 Firestore는 각각 Google Cloud Storage (이미지 버킷) 및 Cloud Firestore Datastore와 함께 작동합니다.
const app = express();
app.get('/', async (req, res) => {
try {
console.log('Collage request');
/* ... */
} catch (err) {
console.log(`Error: creating the collage: ${err}`);
console.error(err);
res.status(500).send(err);
}
});
위에는 앱이 HTTP GET 요청에 응답하는 Node 핸들러 구조가 있습니다. 문제가 발생할 경우에 대비하여 약간의 오류 처리를 진행합니다. 이제 이 구조 안에 무엇이 있는지 살펴보겠습니다.
const thumbnailFiles = [];
const pictureStore = new Firestore().collection('pictures');
const snapshot = await pictureStore
.where('thumbnail', '==', true)
.orderBy('created', 'desc')
.limit(4).get();
if (snapshot.empty) {
console.log('Empty collection, no collage to make');
res.status(204).send("No collage created.");
} else {
/* ... */
}
Google의 콜라주 서비스에는 썸네일이 생성된 사진이 4장 이상 필요하므로 먼저 사진 4장을 업로드해야 합니다.
Cloud Firerstore에 저장된 메타데이터에서 사용자가 업로드한 최신 사진 4장을 검색합니다. 결과 컬렉션이 비어 있는지 확인한 다음 코드의 else 브랜치에서 계속 진행합니다.
파일 이름 목록을 수집해 보겠습니다.
snapshot.forEach(doc => {
thumbnailFiles.push(doc.id);
});
console.log(`Picture file names: ${JSON.stringify(thumbnailFiles)}`);
이러한 각 파일을 썸네일 버킷에서 다운로드하겠습니다. 이 파일의 이름은 배포 시 설정한 환경 변수에서 가져옵니다.
const thumbBucket = storage.bucket(process.env.BUCKET_THUMBNAILS);
await Promise.all(thumbnailFiles.map(async fileName => {
const filePath = path.resolve('/tmp', fileName);
await thumbBucket.file(fileName).download({
destination: filePath
});
}));
console.log('Downloaded all thumbnails');
최신 썸네일이 업로드되면 ImageMagick 라이브러리를 사용하여 미리보기 이미지 그림으로 구성된 4x4 그리드를 생성합니다. Bluebird 라이브러리와 Promise 구현을 사용하여 콜백 기반 코드를 async
/ await
친화적인 코드로 변환한 다음 이미지 콜라주를 만드는 프로미스를 기다립니다.
const collagePath = path.resolve('/tmp', 'collage.png');
const thumbnailPaths = thumbnailFiles.map(f => path.resolve('/tmp', f));
const convert = Promise.promisify(im.convert);
await convert([
'(', ...thumbnailPaths.slice(0, 2), '+append', ')',
'(', ...thumbnailPaths.slice(2), '+append', ')',
'-size', '400x400', 'xc:none', '-background', 'none', '-append',
collagePath]);
console.log("Created local collage picture");
콜라주 사진이 임시 폴더의 로컬 디스크에 저장되었으므로 이제 Cloud Storage에 업로드한 다음 성공적인 응답 (상태 코드 2xx)을 반환해야 합니다.
await thumbBucket.upload(collagePath);
console.log("Uploaded collage to Cloud Storage bucket ${process.env.BUCKET_THUMBNAILS}");
res.status(204).send("Collage created.");
이제 노드 스크립트가 수신 요청을 리슨하도록 해보겠습니다.
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Started collage service on port ${PORT}`);
});
소스 파일의 끝부분에는 Express가 실제로 8080 기본 포트에서 웹 애플리케이션을 시작하도록 하는 안내가 있습니다.
6. 로컬에서 테스트
클라우드에 배포하기 전에 로컬에서 코드를 테스트하여 작동하는지 확인합니다.
collage/nodejs
폴더 내에 npm 종속 항목을 설치하고 서버를 시작합니다.
npm install; npm start
모든 것이 잘 진행되었다면 포트 8080에서 서버를 시작합니다.
Started collage service on port 8080
종료하려면 CTRL-C
을(를) 사용하세요.
7. 빌드 후 Cloud Run에 배포
Cloud Run에 배포하기 전에 Cloud Run 리전을 지원되는 리전 중 하나로 설정하고 플랫폼을 managed
으로 설정합니다.
gcloud config set run/region europe-west1 gcloud config set run/platform managed
다음 명령어로 구성이 설정되었는지 확인할 수 있습니다.
gcloud config list ... [run] platform = managed region = europe-west1
Cloud Build를 사용하여 컨테이너 이미지를 수동으로 빌드하고 게시하는 대신, Cloud Run에 의존하여 Google Cloud 빌드팩을 사용하여 컨테이너 이미지를 빌드할 수도 있습니다.
다음 명령어를 실행하여 컨테이너 이미지를 빌드합니다.
BUCKET_THUMBNAILS=thumbnails-$GOOGLE_CLOUD_PROJECT SERVICE_NAME=collage-service gcloud run deploy $SERVICE_NAME \ --source . \ --no-allow-unauthenticated \ --update-env-vars BUCKET_THUMBNAILS=$BUCKET_THUMBNAILS
–-source
플래그를 확인합니다. Cloud Run의 소스 기반 배포 입니다. Dockerfile
가 소스 코드 디렉터리에 있으면 업로드된 소스 코드는 해당 Dockerfile
를 사용하여 빌드됩니다. 소스 코드 디렉터리에 Dockerfile
가 없으면 Google Cloud 빌드팩이 사용 중인 언어를 자동으로 감지하고 코드의 종속 항목을 가져와 Google에서 관리하는 보안 기본 이미지를 사용하여 프로덕션에 즉시 사용 가능한 컨테이너 이미지를 만듭니다. 그러면 Google Cloud 빌드팩을 사용하여 Dockerfile
에 정의된 컨테이너 이미지를 빌드하도록 Cloud Run이 플래그됩니다.
또한 소스 기반 배포는 빌드된 컨테이너를 저장하는 데 Artifact Registry를 사용합니다. Artifact Registry는 Google Container Registry의 최신 버전입니다. 프로젝트에 API가 아직 사용 설정되어 있지 않으면 CLI에 API를 사용 설정하라는 메시지가 표시되고 배포할 리전에 이름이 cloud-run-source-deploy
인 저장소가 생성됩니다.
--no-allow-unauthenticated
플래그는 Cloud Run 서비스를 특정 서비스 계정에 의해서만 트리거되는 내부 서비스로 만듭니다.
8. Cloud Scheduler 설정
이제 Cloud Run 서비스가 준비되고 배포되었으므로 1분마다 서비스를 호출하는 정기 일정을 만듭니다.
서비스 계정을 만듭니다.
SERVICE_ACCOUNT=collage-scheduler-sa gcloud iam service-accounts create $SERVICE_ACCOUNT \ --display-name "Collage Scheduler Service Account"
서비스 계정에 Cloud Run 서비스를 호출할 수 있는 권한을 부여합니다.
gcloud run services add-iam-policy-binding $SERVICE_NAME \ --member=serviceAccount:$SERVICE_ACCOUNT@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \ --role=roles/run.invoker
1분마다 실행할 Cloud Scheduler 작업을 만듭니다.
SERVICE_URL=$(gcloud run services describe $SERVICE_NAME --format 'value(status.url)') gcloud scheduler jobs create http $SERVICE_NAME-job --schedule "* * * * *" \ --http-method=GET \ --location=europe-west1 \ --uri=$SERVICE_URL \ --oidc-service-account-email=$SERVICE_ACCOUNT@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \ --oidc-token-audience=$SERVICE_URL
Cloud 콘솔의 Cloud Scheduler 섹션으로 이동하여 설정되어 있고 Cloud Run 서비스 URL을 가리키는지 확인할 수 있습니다.
9. 서비스 테스트
설정이 작동하는지 테스트하려면 thumbnails
버킷에서 콜라주 이미지 (collage.png
)를 확인합니다. 또한 다음과 같이 서비스 로그를 확인할 수도 있습니다.
10. 정리(선택 사항)
이 시리즈의 다른 실습을 계속하지 않으려는 경우 리소스를 삭제하여 비용을 절감하고 전반적으로 클라우드를 잘 활용할 수 있습니다. 다음과 같이 리소스를 개별적으로 삭제할 수 있습니다.
서비스 삭제:
gcloud run services delete $SERVICE_NAME -q
Cloud Scheduler 작업을 삭제합니다.
gcloud scheduler jobs delete $SERVICE_NAME-job -q
또는 전체 프로젝트를 삭제할 수 있습니다.
gcloud projects delete $GOOGLE_CLOUD_PROJECT
11. 축하합니다.
축하합니다. 예약된 서비스를 만들었습니다. Pub/Sub 주제에 대해 1분마다 메시지를 푸시하는 Cloud Scheduler 덕분에 Cloud Run 콜라주 서비스가 호출되고 사진을 함께 추가하여 결과를 만들 수 있습니다.
학습한 내용
- Cloud Run
- Cloud Scheduler
- Cloud Storage
- Cloud Firestore