Pic-a-Daily: 실습 6—Workflows를 사용한 조정

1. 개요

이전 실습에서는 이미지 분석 서비스에 Google Cloud Storage 트리거 Cloud 함수, 썸네일 서비스용 Pub/Sub 및 Eventarc를 통해 GCS 트리거 Cloud Run 컨테이너를 사용하여 Cloud Run에서 이미지 가비지 컬렉터 서비스를 트리거하는 Pic-a-daily 앱의 이벤트 기반 버전을 빌드했습니다. Cloud Scheduler로 트리거된 콜라주 서비스도 있었습니다.

d93345bfc235f81e.png

이 실습에서는 조정된 버전의 앱을 만듭니다. 시스템을 통해 전달되는 다양한 유형의 이벤트 대신 Workflows를 사용하여 다음과 같이 서비스를 조정하고 호출합니다.

b763efcbf5589747.png

학습할 내용

  • App Engine
  • Cloud Firestore
  • Cloud Functions
  • Cloud Run
  • 워크플로

2. 설정 및 요구사항

자습형 환경 설정

  1. Cloud 콘솔에 로그인하고 새 프로젝트를 만들거나 기존 프로젝트를 다시 사용합니다. 아직 Gmail이나 Google Workspace 계정이 없는 경우 계정을 만들어야 합니다.

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

모든 Google Cloud 프로젝트에서 고유한 이름인 프로젝트 ID를 기억하세요(위의 이름은 이미 사용되었으므로 사용할 수 없습니다). 이 ID는 나중에 이 Codelab에서 PROJECT_ID라고 부릅니다.

  1. 그런 후 Google Cloud 리소스를 사용할 수 있도록 Cloud Console에서 결제를 사용 설정해야 합니다.

이 Codelab 실행에는 많은 비용이 들지 않습니다. 이 가이드를 마친 후 비용이 결제되지 않도록 리소스 종료 방법을 알려주는 '삭제' 섹션의 안내를 따르세요. Google Cloud 신규 사용자에게는 미화$300 상당의 무료 체험판 프로그램에 참여할 수 있는 자격이 부여됩니다.

Cloud Shell 시작

Google Cloud를 노트북에서 원격으로 실행할 수 있지만, 이 Codelab에서는 Cloud에서 실행되는 명령줄 환경인 Google Cloud Shell을 사용합니다.

GCP 콘솔에서 오른쪽 상단 툴바의 Cloud Shell 아이콘을 클릭합니다.

bce75f34b2c53987.png

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

f6ef2b5f13479f3a.png

가상 머신에는 필요한 개발 도구가 모두 들어있습니다. 영구적인 5GB 홈 디렉토리를 제공하고 Google Cloud에서 실행되므로 네트워크 성능과 인증이 크게 개선됩니다. 이 실습의 모든 작업은 브라우저만으로 수행할 수 있습니다.

3. Workflows 소개

90fcd42d556e310e.jpeg

워크플로를 사용하여 일련의 서버리스 작업을 사용자가 정의한 순서대로 연결하는 서버리스 워크플로를 만들 수 있습니다. Google Cloud의 API, Cloud Functions 및 Cloud Run과 같은 서버리스 제품, 외부 API 호출을 결합하여 유연한 서버리스 애플리케이션을 만들 수 있습니다.

조정자로부터 기대할 수 있는 것처럼, Workflows를 사용하면 비즈니스 로직의 흐름을 YAML/JSON 기반 워크플로 정의 언어로 정의하고 Workflows Execution API와 Workflows UI를 제공하여 이러한 흐름을 트리거할 수 있습니다.

Google Cloud는 다음과 같은 기본 제공 및 구성 가능한 기능을 갖춘 단순한 조정자가 아닙니다.

  • 안정적인 단계 실행을 위해 단계 간 유연한 재시도 및 오류 처리
  • 글루 코드를 피하기 위해 단계 간에 JSON 파싱 및 변수 전달
  • 결정을 위한 표현식 수식을 사용하면 조건부 단계 실행이 가능합니다.
  • 재사용 가능한 모듈식 Workflows의 하위 워크플로입니다.
  • 외부 서비스 지원을 통해 Google Cloud 이상으로 서비스를 조정할 수 있습니다.
  • 보안 단계 실행을 위해 Google Cloud 및 외부 서비스에 대한 인증 지원
  • 간편한 통합을 위한 Pub/Sub, Firestore, Tasks, Secret Manager와 같은 Google Cloud 서비스에 대한 커넥터

Workflows는 완전 관리형 서버리스 제품입니다. 구성하거나 확장할 서버가 없으며 사용한 만큼만 비용을 지불하면 됩니다.

4. API 사용 설정

이 실습에서는 Cloud Functions와 Cloud Run 서비스를 Workflows와 연결합니다. App Engine, Cloud Build, Vision API 및 기타 서비스도 사용하게 됩니다.

Cloud Shell에서 필요한 모든 서비스가 사용 설정되어 있는지 확인합니다.

gcloud services enable \
  appengine.googleapis.com \
  cloudbuild.googleapis.com \
  cloudfunctions.googleapis.com \
  compute.googleapis.com \
  firestore.googleapis.com \
  run.googleapis.com \
  vision.googleapis.com \
  workflows.googleapis.com \

잠시 후 작업이 성공적으로 완료됩니다.

Operation "operations/acf.5c5ef4f6-f734-455d-b2f0-ee70b5a17322" finished successfully.

5. 코드 가져오기

이전 Codelab에서 아직 코드를 가져오지 않았다면 코드를 가져옵니다.

git clone https://github.com/GoogleCloudPlatform/serverless-photosharing-workshop

이 실습과 관련된 폴더 구조는 다음과 같습니다.

frontend
 |
workflows
 |
 ├── functions
 ├── |── trigger-workflow
 ├── |── vision-data-transform
 ├── services
 ├── |── collage
 ├── |── thumbnails
 ├── workflows.yaml

관련 폴더는 다음과 같습니다.

  • frontend에는 실습 4에서 재사용할 App Engine 프런트엔드가 포함되어 있습니다.
  • functions에는 워크플로용으로 생성된 Cloud Functions가 포함됩니다.
  • services에는 워크플로용으로 수정된 Cloud Run 서비스가 포함되어 있습니다.
  • workflows.yaml는 워크플로 정의 파일입니다.

6. Workflows YAML 살펴보기

workflows.yaml은 워크플로를 일련의 단계로 정의합니다. 자세히 살펴보겠습니다.

워크플로 시작 시 전달되는 몇 가지 매개변수가 있습니다. Workflows를 트리거하는 두 Cloud Functions에 의해 전달됩니다. 이러한 함수는 나중에 알아보겠지만 다음과 같이 Workflows가 시작됩니다.

d44a5e18aa9d4660.png

YAML에서는 이러한 매개변수가 이벤트를 트리거하는 파일 및 버킷 이름, Workflows가 호출할 일부 Cloud Functions 및 Cloud Run 서비스의 URL과 같은 init 단계의 변수에 할당되는 것을 확인할 수 있습니다.

main:
  params: [args]
  steps:
    - init:
        assign:
          - file: ${args.file}
          - bucket: ${args.bucket}
          - gsUri: ${"gs://" + bucket + "/" + file}
          - projectId: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
          - urls: ${args.urls}

다음으로 워크플로가 이벤트 유형을 확인합니다. 이벤트 유형은 object.finalize (파일이 클라우드 스토리지 버킷에 저장될 때 발생) 및 object.delete (파일이 삭제될 때 표시됨)의 두 가지로 지원됩니다. 그 외 모든 항목은 지원되지 않는 이벤트 예외를 발생시킵니다.

dd1f450983655619.png

YAML 워크플로 정의에서 파일 스토리지 이벤트 유형을 확인하는 단계는 다음과 같습니다.

    - eventTypeSwitch:
        switch:
            - condition: ${args.eventType == "google.storage.object.finalize"}
              next: imageAnalysisCall
            - condition: ${args.eventType == "google.storage.object.delete"}
              next: pictureGarbageCollectionGCS
    - eventTypeNotSupported:
        raise: ${"eventType " + args.eventType + " is not supported"}
        next: end

Workflows가 switch 명령과 다양한 조건, 그리고 이벤트가 인식되지 않을 때 오류를 발생시키는 제기 명령과 함께 switch 문과 예외 처리를 어떻게 지원하는지 확인하세요.

다음으로, imageAnalysisCall를 살펴보겠습니다. 이는 Workflows에서 Vision API를 호출하여 이미지를 분석하고, Vision API 응답 데이터를 변환하여 사진에서 인식된 항목의 라벨을 정렬하고, 주요 색상을 선택하고, 이미지가 표시해도 안전한지 확인한 후 메타데이터를 Cloud Firestore에 저장하는 일련의 호출입니다.

Vision Transform Cloud Functions (나중에 배포함)를 제외한 모든 작업이 Workflows에서 이루어집니다.

ca2ad16b9cbb436.png

YAML에서 단계가 다음과 같이 표시됩니다.

    - imageAnalysisCall:
        call: http.post
        args:
          url: https://vision.googleapis.com/v1/images:annotate
          headers:
            Content-Type: application/json
          auth:
            type: OAuth2
          body:
            requests:
            - image:
                source:
                  gcsImageUri: ${gsUri}
              features:
              - type: LABEL_DETECTION
              - type: SAFE_SEARCH_DETECTION
              - type: IMAGE_PROPERTIES
        result: imageAnalysisResponse
    - transformImageAnalysisData:
        call: http.post
        args:
          url: ${urls.VISION_DATA_TRANSFORM_URL}
          auth:
            type: OIDC
          body: ${imageAnalysisResponse.body}
        result: imageMetadata
    - checkSafety:
        switch:
          - condition: ${imageMetadata.body.safe == true}
            next: storeMetadata
        next: end
    - storeMetadata:
        call: http.request
        args:
          url: ${"https://firestore.googleapis.com/v1/projects/" + projectId + "/databases/(default)/documents/pictures/" + file + "?updateMask.fieldPaths=color&updateMask.fieldPaths=labels&updateMask.fieldPaths=created"}
          auth:
            type: OAuth2
          method: PATCH
          body:
            name: ${"projects/" + projectId + "/databases/(default)/documents/pictures/" + file}
            fields:
              color:
                stringValue: ${imageMetadata.body.color}
              created:
                timestampValue: ${imageMetadata.body.created}
              labels:
                arrayValue:
                  values: ${imageMetadata.body.labels}
        result: storeMetadataResponse

이미지를 분석한 후 다음 두 단계는 이미지의 썸네일과 최신 이미지의 콜라주를 만드는 것입니다. 2개의 Cloud Run 서비스를 배포하고 thumbnailCallcollageCall 단계에서 호출하면 됩니다.

76f9179323c3144.png

YAML의 단계:

   - thumbnailCall:
        call: http.post
        args:
          url: ${urls.THUMBNAILS_URL}
          auth:
            type: OIDC
          body:
              gcsImageUri: ${gsUri}
        result: thumbnailResponse
    - collageCall:
        call: http.get
        args:
          url: ${urls.COLLAGE_URL}
          auth:
            type: OIDC
        result: collageResponse

이 실행 브랜치는 finalizeCompleted 단계에서 각 서비스의 상태 코드를 반환하여 종료됩니다.

    - finalizeCompleted:
        return:
          imageAnalysis: ${imageAnalysisResponse.code}
          storeMetadata: ${storeMetadataResponse.code}
          thumbnail: ${thumbnailResponse.code}
          collage: ${collageResponse.code}

실행의 다른 브랜치는 사진의 고해상도 버전이 포함된 기본 저장소 버킷에서 파일이 삭제되는 경우입니다. 이 브랜치에서 썸네일이 포함된 버킷에서 이미지의 썸네일을 삭제하고 Firestore에서 메타데이터를 삭제하려고 합니다. 이 두 작업은 모두 Workflows의 HTTP 호출을 사용하여 수행됩니다.

f172379274dcb3c2.png

YAML의 단계:

    - pictureGarbageCollectionGCS:
        try:
          call: http.request
          args:
            url: ${"https://storage.googleapis.com/storage/v1/b/thumbnails-" + projectId + "/o/" + file}
            auth:
              type: OAuth2
            method: DELETE
          result: gcsDeletionResult
        except:
          as: e
          steps:
              - dummyResultInOutVar:
                  assign:
                      - gcsDeletionResult:
                          code: 200
                          body: "Workaround for empty body response"
    - pictureGarbageCollectionFirestore:
        call: http.request
        args:
          url: ${"https://firestore.googleapis.com/v1/projects/" + projectId + "/databases/(default)/documents/pictures/" + file}
          auth:
            type: OAuth2
          method: DELETE
        result: firestoreDeletionResult

삭제 브랜치는 각 단계의 결과 / 코드를 반환하여 종료됩니다.

    - deleteCompleted:
        return:
          gcsDeletion: ${gcsDeletionResult}
          firestoreDeletion: ${firestoreDeletionResult.code}

다음 단계에서는 버킷, Cloud Functions, Cloud Run 서비스, Firestore 데이터베이스 등 Workflows의 외부 종속 항목을 모두 만듭니다.

7. 버킷 만들기

이미지에는 버킷 2개가 필요합니다. 하나는 원본 고해상도 이미지를 저장하는 데, 다른 하나는 이미지의 썸네일 이미지를 저장하는 데 사용됩니다.

gsutil 도구를 사용하여 사용자가 사진을 업로드할 수 있는 균일한 액세스 권한이 있는 공개 리전 (이 경우 유럽) 버킷을 만듭니다.

export BUCKET_PICTURES=uploaded-pictures-${GOOGLE_CLOUD_PROJECT}
gsutil mb -l EU gs://${BUCKET_PICTURES}
gsutil uniformbucketlevelaccess set on gs://${BUCKET_PICTURES}
gsutil iam ch allUsers:objectViewer gs://${BUCKET_PICTURES}

썸네일을 위한 또 다른 공개 리전 버킷을 만듭니다.

export BUCKET_THUMBNAILS=thumbnails-${GOOGLE_CLOUD_PROJECT}
gsutil mb -l EU gs://${BUCKET_THUMBNAILS}
gsutil uniformbucketlevelaccess set on gs://${BUCKET_THUMBNAILS}
gsutil iam ch allUsers:objectViewer gs://${BUCKET_THUMBNAILS}

Cloud 콘솔의 Cloud Storage 섹션으로 이동하여 버킷이 만들어지고 공개되었는지 다시 한번 확인할 수 있습니다.

15063936edd72f06.png

8. Vision 데이터 변환 (Cloud 함수)

Workflows.yamlinit, eventTypeSwitch, eventTypeNotSupported 단계로 시작합니다. 이렇게 하면 버킷에서 발생하는 이벤트가 올바른 단계로 라우팅됩니다.

object.finalize 이벤트의 경우 imageAnalysisCall 단계는 Vision API를 호출하여 생성된 이미지의 메타데이터를 추출합니다. 이러한 모든 단계는 Workflows 내에서 수행됩니다.

daaed43a22d2b0d3.png

그런 다음 Vision API에서 반환된 데이터를 변환해야 Firestore에 저장할 수 있습니다. 구체적으로는 다음과 같아야 합니다.

  • 이미지에 대해 반환된 라벨을 나열합니다.
  • 이미지의 주요 색상을 가져옵니다.
  • 사진이 안전한지 확인합니다.

이 작업은 Cloud 함수의 코드로 수행되며 Workflows는 다음 함수를 호출합니다.

5e120e70c67779cd.png

코드 살펴보기

Cloud 함수는 vision-data-transform이라고 합니다. 전체 코드는 index.js에서 확인할 수 있습니다. 보시다시피 이 함수의 유일한 목적은 JSON에서 JSON으로 변환하여 사진 메타데이터를 Firestore에 편리하게 저장하는 것입니다.

Cloud Functions에 배포

다음 폴더로 이동합니다.

cd workflows/functions/vision-data-transform/nodejs

원하는 리전을 설정합니다.

export REGION=europe-west1
gcloud config set functions/region ${REGION}

다음을 사용하여 함수를 배포합니다.

export SERVICE_NAME=vision-data-transform
gcloud functions deploy ${SERVICE_NAME} \
  --source=. \
  --runtime nodejs10 \
  --entry-point=vision_data_transform \
  --trigger-http \
  --allow-unauthenticated

함수가 배포되면 Workflows transformImageAnalysisData 단계에서 이 함수를 호출하여 Vision API 데이터 변환을 수행할 수 있습니다.

9. 데이터베이스 준비

Workflows의 다음 단계는 이미지 데이터에서 이미지의 안전성을 확인한 다음, Vision API에서 반환한 사진에 대한 정보를 빠르고 완전 관리형 서버리스 클라우드 기반 NoSQL 문서 데이터베이스인 Cloud Firestore 데이터베이스에 저장하는 것입니다.

6624c616bc7cd97f.png

이 두 작업은 모두 Workflows에서 실행되지만 메타데이터 스토리지가 작동하려면 Firestore 데이터베이스를 만들어야 합니다.

먼저 Firestore 데이터베이스를 추가할 리전에 App Engine 앱을 만듭니다 (Firestore의 요구사항).

export REGION_FIRESTORE=europe-west2
gcloud app create --region=${REGION_FIRESTORE}

다음으로 동일한 리전에 Firestore 데이터베이스를 만듭니다.

gcloud firestore databases create --region=${REGION_FIRESTORE}

이 문서는 컬렉션에 프로그래매틱 방식으로 생성되며 4개의 필드를 포함합니다.

  • name (문자열): 업로드된 사진의 파일 이름으로, 문서의 키이기도 합니다.
  • labels (문자열 배열): Vision API에서 인식된 항목의 라벨
  • color (문자열): 주요 색상의 16진수 색상 코드입니다 (예: #ab12ef)는
  • created (날짜): 이 이미지의 메타데이터가 저장된 시점의 타임스탬프
  • thumbnail (불리언): 표시되고 이 사진의 미리보기 이미지가 생성된 경우 true로 표시되는 선택 필드입니다.

사용 가능한 썸네일이 있는 사진을 찾기 위해 Firestore에서 검색하고 생성 날짜를 기준으로 정렬하므로 검색 색인을 만들어야 합니다. 다음 명령어를 사용하여 색인을 만들 수 있습니다.

gcloud firestore indexes composite create --collection-group=pictures \
  --field-config field-path=thumbnail,order=descending \
  --field-config field-path=created,order=descending

색인을 만드는 데 최대 10분 정도 걸릴 수 있습니다.

색인이 생성되면 Cloud 콘솔에서 확인할 수 있습니다.

43af1f5103bf423.png

이제 Workflows storeMetadata 단계에서 이미지 메타데이터를 Firestore에 저장할 수 있습니다.

10. 썸네일 서비스 (Cloud Run)

체인의 다음 단계는 이미지의 썸네일을 만드는 것입니다. 이 작업은 Cloud Run 서비스의 코드로 완료되며 Workflows는 thumbnailCall 단계에서 이 서비스를 호출합니다.

84d987647f082b53.png

코드 살펴보기

Cloud Run 서비스의 이름은 thumbnails입니다. 전체 코드는 index.js에서 확인할 수 있습니다.

컨테이너 이미지 빌드 및 게시

Cloud Run은 컨테이너를 실행하지만 먼저 Dockerfile에 정의된 컨테이너 이미지를 빌드해야 합니다. Google Cloud Build를 사용하여 컨테이너 이미지를 빌드한 다음 Google Container Registry에 호스팅할 수 있습니다.

다음 폴더로 이동합니다.

cd workflows/services/thumbnails/nodejs

빌드:

export SERVICE_SRC=thumbnails
export SERVICE_NAME=${SERVICE_SRC}-service
gcloud builds submit \
  . \
  --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME}

1~2분 후 빌드가 성공하고 컨테이너가 Google Container Registry에 배포됩니다.

Cloud Run에 배포

필요한 변수와 구성을 설정합니다.

export BUCKET_THUMBNAILS=thumbnails-${GOOGLE_CLOUD_PROJECT}
export REGION=europe-west1
gcloud config set run/region ${REGION}
gcloud config set run/platform managed

다음 명령어를 사용하여 배포합니다.

gcloud run deploy ${SERVICE_NAME} \
    --image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME} \
    --no-allow-unauthenticated \
    --memory=1Gi \
    --update-env-vars BUCKET_THUMBNAILS=${BUCKET_THUMBNAILS}

서비스가 배포되면 Workflows thumbnailCall 단계에서 이 서비스를 호출할 수 있습니다.

11. 콜라주 서비스 (Cloud Run)

체인의 다음 단계는 가장 최근의 이미지로 콜라주를 만드는 것입니다. 이 작업은 Cloud Run 서비스의 코드로 완료되며 Workflows는 collageCall 단계에서 이 서비스를 호출합니다.

591e36149066e1ba.png

코드 살펴보기

Cloud Run 서비스의 이름은 collage입니다. 전체 코드는 index.js에서 확인할 수 있습니다.

컨테이너 이미지 빌드 및 게시

Cloud Run은 컨테이너를 실행하지만 먼저 Dockerfile에 정의된 컨테이너 이미지를 빌드해야 합니다. Google Cloud Build를 사용하여 컨테이너 이미지를 빌드한 다음 Google Container Registry에 호스팅할 수 있습니다.

다음 폴더로 이동합니다.

cd services/collage/nodejs

빌드:

export SERVICE_SRC=collage
export SERVICE_NAME=${SERVICE_SRC}-service
gcloud builds submit \
  . \
  --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME}

1~2분 후 빌드가 성공하고 컨테이너가 Google Container Registry에 배포됩니다.

Cloud Run에 배포

필요한 변수와 구성을 설정합니다.

export BUCKET_THUMBNAILS=thumbnails-${GOOGLE_CLOUD_PROJECT}
export REGION=europe-west1
gcloud config set run/region ${REGION}
gcloud config set run/platform managed

배치:

gcloud run deploy ${SERVICE_NAME} \
    --image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME} \
    --no-allow-unauthenticated \
    --memory=1Gi \
    --update-env-vars BUCKET_THUMBNAILS=${BUCKET_THUMBNAILS}

서비스가 배포되면 Cloud 콘솔의 Cloud Run 섹션에서 두 서비스가 모두 실행 중인지 확인할 수 있으며 Workflows collageCall 단계에서 이 서비스를 호출할 수 있습니다.

3ae9873f4cbbf423.png

12. Workflows 배포

Workflows의 모든 외부 종속 항목을 배포했습니다. 나머지 단계 (finalizeCompleted, pictureGarbageCollectionGCS, pictureGarbageCollectionFirestore, deleteCompleted)는 모두 Workflows 자체에서 완료할 수 있습니다.

이제 Workflows를 배포할 차례입니다.

workflows.yaml 파일이 포함된 폴더로 이동하여 다음을 사용하여 배포합니다.

export WORKFLOW_REGION=europe-west4
export WORKFLOW_NAME=picadaily-workflows
gcloud workflows deploy ${WORKFLOW_NAME} \
  --source=workflows.yaml \
  --location=${WORKFLOW_REGION}

몇 초 내로 워크플로가 배포되고 Cloud 콘솔의 Workflows 섹션에서 확인할 수 있습니다.

94a720149e5df9c5.png

원하는 경우 워크플로를 클릭하여 수정할 수 있습니다. 편집하는 동안 워크플로를 시각적으로 보기 좋게 표현할 수 있습니다.

55441b158f6027f3.png

올바른 매개변수를 사용하여 Cloud 콘솔에서 워크플로를 수동으로 실행할 수도 있습니다. 대신 다음 단계에서 Cloud Storage 이벤트에 대한 응답으로 이를 자동으로 실행합니다.

13. 워크플로 트리거 (Cloud Functions)

워크플로가 배포되고 준비되었습니다. 이제 Cloud Storage 버킷에서 파일이 생성되거나 삭제될 때 Workflows를 트리거해야 합니다. 이는 각각 storage.object.finalizestorage.object.delete 이벤트입니다.

Workflows에는 사용자가 사용할 수 있는 Workflows를 생성, 관리, 실행하기 위한 API 및 클라이언트 라이브러리가 있습니다. 이 경우 Workflows Execution API, 더 구체적으로는 Node.js 클라이언트 라이브러리를 사용하여 워크플로를 트리거합니다.

Cloud Storage 이벤트를 수신 대기하는 Cloud 함수에서 Workflows를 트리거합니다. Cloud 함수는 하나의 이벤트 유형만 리슨할 수 있으므로 생성 및 삭제 이벤트를 모두 리슨하도록 두 개의 Cloud Functions를 배포합니다.

c4d79646de729e4.png

코드 살펴보기

Cloud 함수는 trigger-workflow이라고 합니다. 전체 코드는 index.js에서 확인할 수 있습니다.

Cloud Functions에 배포

다음 폴더로 이동합니다.

cd workflows/functions/trigger-workflow/nodejs

필요한 변수와 구성을 설정합니다.

export BUCKET_PICTURES=uploaded-pictures-${GOOGLE_CLOUD_PROJECT}
export REGION=europe-west1
export WORKFLOW_NAME=picadaily-workflows
export WORKFLOW_REGION=europe-west4
export COLLAGE_URL=$(gcloud run services describe collage-service --format 'value(status.url)')
export THUMBNAILS_URL=$(gcloud run services describe thumbnails-service --format 'value(status.url)')
export VISION_DATA_TRANSFORM_URL=$(gcloud functions describe vision-data-transform --format 'value(httpsTrigger.url)')
gcloud config set functions/region ${REGION}

이벤트 완료에 응답하는 함수를 배포합니다.

export SERVICE_NAME=trigger-workflow-on-finalize
gcloud functions deploy ${SERVICE_NAME} \
  --source=. \
  --runtime nodejs10 \
  --entry-point=trigger_workflow \
  --trigger-resource=${BUCKET_PICTURES} \
  --trigger-event=google.storage.object.finalize \
  --allow-unauthenticated \
  --set-env-vars GOOGLE_CLOUD_PROJECT=${GOOGLE_CLOUD_PROJECT},WORKFLOW_REGION=${WORKFLOW_REGION},WORKFLOW_NAME=${WORKFLOW_NAME},THUMBNAILS_URL=${THUMBNAILS_URL},COLLAGE_URL=${COLLAGE_URL},VISION_DATA_TRANSFORM_URL=${VISION_DATA_TRANSFORM_URL}

삭제 이벤트에 응답하는 두 번째 함수를 배포합니다.

export SERVICE_NAME=trigger-workflow-on-delete
gcloud functions deploy ${SERVICE_NAME} \
  --source=. \
  --runtime nodejs10 \
  --entry-point=trigger_workflow \
  --trigger-resource=${BUCKET_PICTURES} \
  --trigger-event=google.storage.object.delete \
  --allow-unauthenticated \
  --set-env-vars GOOGLE_CLOUD_PROJECT=${GOOGLE_CLOUD_PROJECT},WORKFLOW_REGION=${WORKFLOW_REGION},WORKFLOW_NAME=${WORKFLOW_NAME},THUMBNAILS_URL=${THUMBNAILS_URL},COLLAGE_URL=${COLLAGE_URL},VISION_DATA_TRANSFORM_URL=${VISION_DATA_TRANSFORM_URL}

배포가 완료되면 Cloud 콘솔에서 두 함수를 모두 볼 수 있습니다.

7d60c8b7851f39f5.png

14. 프런트엔드 (App Engine)

이 단계에서는 Pic-a-daily: 실습 4—웹 프런트엔드 만들기에서 Google App Engine의 웹 프런트엔드를 만듭니다. 이 프런트엔드를 사용하면 사용자가 웹 애플리케이션에서 사진을 업로드하고 업로드된 사진과 썸네일을 둘러볼 수 있습니다.

223fb2281614d053.png

Pic-a-daily: 실습 4—웹 프런트엔드 만들기에서 App Engine에 대해 자세히 알아보고 코드 설명을 읽어보세요.

코드 살펴보기

App Engine 앱의 이름은 frontend입니다. 전체 코드는 index.js에서 확인할 수 있습니다.

App Engine에 배포

다음 폴더로 이동합니다.

cd frontend

원하는 리전을 설정하고 app.yaml의 GOOGLE_CLOUD_PROJECT도 실제 프로젝트 ID로 바꿉니다.

export REGION=europe-west1
gcloud config set compute/region ${REGION}
sed -i -e "s/GOOGLE_CLOUD_PROJECT/${GOOGLE_CLOUD_PROJECT}/" app.yaml

배치:

gcloud app deploy app.yaml -q

1~2분 후에 애플리케이션이 트래픽을 제공하고 있다는 메시지가 표시됩니다.

Beginning deployment of service [default]...
╔════════════════════════════════════════════════════════════╗
╠═ Uploading 8 files to Google Cloud Storage                ═╣
╚════════════════════════════════════════════════════════════╝
File upload done.
Updating service [default]...done.
Setting traffic split for service [default]...done.
Deployed service [default] to [https://GOOGLE_CLOUD_PROJECT.appspot.com]
You can stream logs from the command line by running:
  $ gcloud app logs tail -s default
To view your application in the web browser run:
  $ gcloud app browse

또한 Cloud 콘솔의 App Engine 섹션을 방문하여 앱이 배포되었는지 확인하고 버전 관리 및 트래픽 분할과 같은 App Engine의 기능을 살펴볼 수 있습니다.

f4bd5f4de028bd83.png

15. 워크플로 테스트

테스트하려면 앱 (https://<YOUR_PROJECT_ID>.appspot.com/) 앱의 기본 App Engine URL로 이동하면 프런트엔드 UI가 실행되고 있는 것을 확인할 수 있습니다.

1649ac060441099.png

사진을 업로드합니다. 그러면 Workflows가 트리거되고 Cloud 콘솔에서 Active 상태의 워크플로 실행을 확인할 수 있습니다.

b5a2a3d7a2bc094.png

Workflows가 완료되면 실행 ID를 클릭하고 다양한 서비스의 출력을 확인할 수 있습니다.

8959df5098c21548.png

사진 3장을 더 업로드합니다. 또한 Cloud Storage 버킷에 있는 이미지의 썸네일과 콜라주와 App Engine 프런트엔드가 업데이트된 것을 볼 수 있습니다.

d90c786ff664a5dc.png

16. 정리(선택 사항)

앱을 유지하지 않으려면 전체 프로젝트를 삭제하여 리소스를 정리하여 비용을 절감하고 전반적으로 클라우드를 효율적으로 활용할 수 있습니다.

gcloud projects delete ${GOOGLE_CLOUD_PROJECT} 

17. 축하합니다.

Workflows를 사용하여 서비스를 조정하고 호출하는 조정된 버전의 앱을 만들었습니다.

학습한 내용

  • App Engine
  • Cloud Firestore
  • Cloud Functions
  • Cloud Run
  • 워크플로