로컬 함수 개발

Cloud Run Functions는 타겟 배포 환경 외부에서 함수를 실행하는 여러 가지 방법을 지원합니다. 이는 반복 개발과 배포 전에 함수를 테스트하려는 경우에 특히 유용합니다.

함수를 배포하지 않고 실행할 수 있는 기능으로 로컬 테스트, 데이터 지역 제한 규정 준수, 멀티 클라우드 배포를 단순화할 수 있습니다.

  • 데이터 지역 제한: 조직의 데이터 지역 규칙을 위반하지 않도록 프로덕션 데이터에 액세스하지 않고 로컬에서 함수를 테스트합니다.

  • 멀티 클라우드 배포: 멀티 클라우드 함수 배포는 안정성이 중요한 환경에서 다운타임 위험을 완화하기 위해 확립된 패턴입니다. 함수를 Cloud Run Functions 외의 환경에 배포하는 것만으로도 애플리케이션에 예상치 못한 다운타임이 발생할 위험이 줄어듭니다.

함수 프레임워크를 사용하여 로컬에서 함수 개발

함수 프레임워크를 사용하여 로컬에서 함수를 개발하고 테스트할 수 있습니다. 로컬에서 함수를 개발하면 함수 컨테이너를 다시 빌드하지 않고도 코드를 테스트할 수 있습니다. 이렇게 하면 시간을 절약하고 함수를 더 쉽게 테스트할 수 있습니다.

Cloud Run은 오픈소스 함수 프레임워크 라이브러리를 사용하여 배포된 함수를 영구 HTTP 애플리케이션으로 래핑합니다.

함수 프레임워크는 로컬 머신, 온프레미스 서버, Compute Engine을 포함하여 언어 자체를 지원하는 다른 플랫폼에서도 실행할 수 있습니다.

종속 항목 설치

함수 디렉터리에서 다음 언어에 맞는 Functions 프레임워크 라이브러리를 설치합니다.

Node.js

npm install --save-dev @google-cloud/functions-framework

Python

pip3 install functions-framework

Go

go install github.com/GoogleCloudPlatform/functions-framework-go/funcframework

자바

Maven

Maven을 사용하는 경우 pom.xml 파일에 다음을 추가합니다.

<dependency>
  <groupId>com.google.cloud.functions</groupId>
  <artifactId>functions-framework-api</artifactId>
  <version>1.1.0</version>
  <scope>provided</scope>
</dependency>

Gradle

Gradle을 사용하는 경우 build.gradle 파일에 다음을 추가합니다.

dependencies {
  // Every function needs this dependency to get the Functions Framework API.
  compileOnly 'com.google.cloud.functions:functions-framework-api:1.1.0'

  // To run function locally using Functions Framework's local invoker
  invoker 'com.google.cloud.functions.invoker:java-function-invoker:1.3.1'
}

자세한 내용은 자바 Functions 프레임워크 라이브러리를 참조하세요.

C#

다음 명령어는 .NET 템플릿을 사용하여 새 .NET 함수 코드베이스를 생성하고 .NET Functions 프레임워크 라이브러리를 종속 항목으로 추가합니다.

# HTTP functions
dotnet new gcf-http

# CloudEvent functions
dotnet new gcf-event

Ruby

Ruby에서 함수 프레임워크를 Cloud Run에 배포하기 위해 함수의 종속 항목에 추가해야 합니다.

bundle add functions_framework

PHP

composer require google/cloud-functions-framework

Functions 프레임워크 구성

Functions 프레임워크를 사용하여 함수를 실행하기 전에 먼저 실행할 함수의 유형과 이름을 모두 지정해야 합니다. 이러한 속성은 명령줄 인터페이스(CLI) 플래그 또는 환경 변수로 지정할 수 있습니다.

지원되는 함수 유형

Functions 프레임워크는 Cloud Run Functions에서 지원하는 두 가지 유형의 함수를 모두 지원합니다. 모든 언어 런타임은 httpcloudevent 서명 유형을 모두 지원합니다.

함수 유형 서명 유형 설명 런타임 지원
HTTP 트리거 함수 http HTTP 요청을 수신하고 응답하는 함수입니다. 모든 런타임
CloudEvent 함수 cloudevent 업계 표준 이벤트 형식 모든 런타임

실행할 함수 지정

Functions 프레임워크를 사용하여 함수를 실행하기 전에 먼저 코드 내에서 실행할 함수를 지정해야 합니다. 대부분의 언어에서는 다음 표에 나온 대로 대상 함수의 메서드 이름을 지정하면 됩니다. Java.NET 런타임에는 이 규칙에 대한 예외가 있습니다.

언어별 안내

각 언어에서 지원하는 구성 옵션 목록은 다음 표를 참고하세요.

Node.js

CLI 인수 환경 변수 설명
--port PORT 요청을 리슨할 포트입니다. (기본값: 8080)
--target FUNCTION_TARGET 호출하기 위해 export한 함수의 이름입니다. (기본값: function)
--signature-type FUNCTION_SIGNATURE_TYPE 함수에서 사용되는 서명 유형으로, http(기본값) 또는 cloudevent일 수 있습니다.

Python

CLI 인수 환경 변수 설명
--port PORT 요청을 리슨할 포트입니다. (기본값: 8080)
--target FUNCTION_TARGET 호출하기 위해 export한 함수의 이름입니다. (기본값: function)
--signature-type FUNCTION_SIGNATURE_TYPE 함수에서 사용되는 서명 유형으로, http(기본값) 또는 cloudevent일 수 있습니다.

Go

환경 변수 설명
PORT 요청을 리슨할 포트입니다. (기본값: 8080)

자바

인수 이름 환경 변수 설명
run.port PORT 요청을 리슨할 포트입니다. (기본값: 8080)
run.functionTarget FUNCTION_TARGET 호출하기 위해 export한 함수의 이름입니다. (기본값: function)

C#

CLI 인수 환경 변수 설명
--port PORT 요청을 리슨할 포트입니다. (기본값: 8080)
--target(또는 인수만) FUNCTION_TARGET 호출할 함수의 classname입니다. (기본값: function)

Ruby

CLI 인수 환경 변수 설명
--port PORT 요청을 리슨할 포트입니다. (기본값: 8080)
--target FUNCTION_TARGET 호출하기 위해 export한 함수의 이름입니다. (기본값: function)

PHP

환경 변수 설명
FUNCTION_TARGET 호출할 함수의 이름입니다. (기본값: function)
FUNCTION_SIGNATURE_TYPE 함수에서 사용되는 서명 유형으로, http(기본값) 또는 cloudevent일 수 있습니다.

Functions 프레임워크를 구성하고 실행하려면 다음 안내를 따르세요.

Node.js

Node.js Functions 프레임워크를 사용하면 함수의 이름과 서명 유형을 명령줄 인수 또는 환경 변수로 지정할 수 있습니다.

아래 예시와 같이 필요한 CLI 인수로 start 스크립트를 추가하여 package.json 빌드 파일에서 이러한 값을 지정할 수도 있습니다.

"scripts": {
"start": "npx functions-framework --target=YOUR_FUNCTION_NAME [--signature-type=YOUR_SIGNATURE_TYPE]"
}

환경 변수를 사용하여 동일한 작업을 할 수도 있습니다.

"scripts": {
"start": "FUNCTION_TARGET=YOUR_FUNCTION_NAME FUNCTION_SIGNATURE_TYPE=YOUR_SIGNATURE_TYPE npx functions-framework"
}

지원되는 함수 유형과 같이 YOUR_FUNCTION_NAME을 함수의 메서드 이름으로, YOUR_SIGNATURE_TYPE (해당하는 경우)을 함수의 서명 유형으로 바꿉니다.

Python

Python Functions 프레임워크를 사용하면 함수의 이름과 서명 유형을 명령줄 인수 또는 환경 변수로 지정할 수 있습니다. 프레임워크를 실행할 때 명령줄 인수를 지정해야 합니다.

Go

Go Functions 프레임워크는 funcframework.RegisterHTTPFunctionContext을 사용하여 함수 대상 및 서명 유형을 지정합니다.

자바

자바 Functions 프레임워크는 세 가지 다른 소스의 구성 데이터를 가장 구체적인 데이터부터 순서대로 허용합니다.

  • 명령줄 인수
  • 빌드 파일
  • 환경 변수

명령줄 인수

Maven

mvn 명령어에 다음 명령줄 인터페이스(CLI)를 추가하여 실행할 함수를 지정할 수 있습니다.

-Drun.functionTarget=YOUR_FUNCTION_NAME

다음 CLI 플래그도 유사한 방법으로 추가하여 대상 포트를 지정할 수도 있습니다.

-Drun.port=12345

Gradle

Gradle의 CLI 플래그는 Maven의 플래그와 거의 동일합니다. Gradle이 유일하게 변경하는 사항은 다음 예와 같이 각 플래그의 선행 -D-P로 바꾸는 것입니다.

# Maven version

-Drun.functionTarget=...

# Gradle version

-Prun.functionTarget=...

빌드 파일

프로젝트의 빌드 파일에서 실행할 함수를 지정할 수도 있습니다. Maven 및 Gradle에는 유사한 CLI 플래그가 있지만 빌드 파일 절은 크게 다릅니다.

Maven

Maven 빌드 파일의 이름은 pom.xml으로 지정됩니다. 이 파일에 다음 절을 추가하여 대상 함수를 지정합니다.

<plugin>
  <groupId>com.google.cloud.functions</groupId>
  <artifactId>function-maven-plugin</artifactId>
  <version>0.11.0</version>
  <configuration>
    <functionTarget>functions.HelloWorld</functionTarget>
  </configuration>
</plugin>

<functionTarget>을 함수의 클래스 이름으로 바꿉니다. 예를 들어 클래스 이름이 HelloCloudFunctions인 패키지 functions의 함수는 functions.HelloCloudFunctions라는 클래스 이름을 가집니다. 이는 상위 빌드 파일(pom.xml 또는 build.gradle)을 기준으로 합니다.

Gradle

Gradle 빌드 파일의 이름은 build.gradle로 지정됩니다. 이 파일에 다음 절을 추가하여 대상 함수를 지정합니다.

// Register a "runFunction" task to run the function locally
tasks.register("runFunction", JavaExec) {
  main = 'com.google.cloud.functions.invoker.runner.Invoker'
  classpath(configurations.invoker)
  inputs.files(configurations.runtimeClasspath, sourceSets.main.output)
  args(
    '--target', project.findProperty('run.functionTarget') ?: '',
    '--port', project.findProperty('run.port') ?: 8080
  )
  doFirst {
    args('--classpath', files(configurations.runtimeClasspath, sourceSets.main.output).asPath)
  }
}

C#

dotnet new와 앞에서 지정한 템플릿 중 하나를 사용하여 프로젝트를 만들면 .NET Functions 프레임워크가 함수를 자동으로 감지합니다.

프로젝트에 여러 함수가 포함된 경우 특정 함수를 실행하는 방법은 프레임워크 실행 섹션을 참조하세요.

Ruby

Ruby Functions 프레임워크를 사용하면 함수의 이름과 서명 유형을 명령줄 인수 또는 환경 변수로 지정할 수 있습니다. 프레임워크를 실행할 때 명령줄 인수를 지정해야 합니다.

PHP

PHP Functions 프레임워크를 사용하면 환경 변수를 명령줄 인수로 지정할 수 있습니다.

아래 예시와 같이 start 스크립트를 추가하여 composer.json 빌드 파일에서 이러한 값을 지정할 수도 있습니다.

"scripts": {
 "start": [
     "Composer\\Config::disableProcessTimeout",
     "FUNCTION_TARGET=YOUR_FUNCTION_NAME php -S localhost:${PORT:-8080} vendor/bin/router.php"
].
}

YOUR_FUNCTION_NAME을 함수의 이름으로 바꾸고 YOUR_SIGNATURE_TYPE (해당하는 경우, 여기에 표시된 예에는 포함되지 않음)을 바꿉니다.

함수 실행

Functions 프레임워크를 사용하여 함수를 실행하려면 다음 명령어를 사용합니다. PORT 값을 명시적으로 지정한 경우를 제외하고 기본적으로 localhost:8080에서 함수에 액세스할 수 있습니다.

Node.js

npm start

Python

명령줄 인수를 사용합니다.

functions-framework --target=YOUR_FUNCTION_NAME

환경 변수를 사용합니다.

FUNCTION_TARGET=YOUR_FUNCTION_NAME functions-framework

YOUR_FUNCTION_NAME을 함수의 메서드 이름으로 바꿉니다.

Go

먼저 Go용 함수 프레임워크 사이트에 설명된 대로 cmd/main.go 파일을 만듭니다.

cd cmd
go build
./cmd

환경 변수를 사용합니다.

cd cmd
go build
PORT=8080 ./cmd

자바

Maven

다음 명령어를 사용하여 pom.xml에 지정된 함수를 실행합니다.

mvn function:run

다음 명령어를 사용하여 명령줄 인수에 지정된 함수를 실행합니다.

mvn function:run -Drun.functionTarget=YOUR_FUNCTION_NAME

다음 명령어를 사용하여 환경 변수로 지정된 함수를 실행합니다.

FUNCTION_TARGET=YOUR_FUNCTION_NAME mvn function:run

YOUR_FUNCTION_NAME을 함수의 클래스 이름으로 바꿉니다.

Gradle

다음 명령어를 사용하여 build.gradle에 지정된 함수를 실행합니다.

./gradlew runFunction

다음 명령어를 사용하여 명령줄 인수에 지정된 함수를 실행합니다.

./gradlew runFunction -Prun.functionTarget=YOUR_FUNCTION_NAME

다음 명령어를 사용하여 환경 변수로 지정된 함수를 실행합니다.

FUNCTION_TARGET=YOUR_FUNCTION_NAME ./gradlew runFunction

YOUR_FUNCTION_NAME을 함수의 클래스 이름으로 바꿉니다.

C#

현재 .NET 프로젝트에 정확히 하나의 함수가 있으면 다음 명령어를 사용하여 함수를 실행합니다. 이는 템플릿으로 만든 프로젝트의 기본 구조입니다.

dotnet run

.NET 프로젝트에 여러 함수가 포함된 경우 다음 명령어를 사용하여 특정 함수를 실행합니다. YOUR_FUNCTION_CLASSNAME을 함수의 클래스 이름(네임스페이스 포함)으로 바꿉니다.

dotnet run YOUR_FUNCTION_CLASSNAME

여러 함수를 동시에 실행하려면 여러 Functions 프레임워크 인스턴스를 실행해야 합니다. 여러 프레임워크 인스턴스 실행할 때 충돌을 방지하려면 각 인스턴스가 다른 PORT 값을 사용해야 합니다. 다음 명령어를 PORT 값이 8080인 함수를 실행하는 방법을 보여줍니다.

명령줄 인수를 사용합니다.

dotnet run --target YOUR_FUNCTION_CLASSNAME --port 8080

환경 변수를 사용합니다.

FUNCTION_TARGET=YOUR_FUNCTION_CLASSNAME PORT=8080 dotnet run

Ruby

명령줄 인수를 사용합니다.

bundle exec functions-framework-ruby --target YOUR_FUNCTION_NAME

환경 변수를 사용합니다.

FUNCTION_TARGET=YOUR_FUNCTION_NAME bundle exec functions-framework-ruby

YOUR_FUNCTION_NAME을 함수의 메서드 이름으로 바꿉니다.

PHP

export FUNCTION_TARGET=YOUR_FUNCTION_NAME
php -S localhost:8080 vendor/bin/router.php

YOUR_FUNCTION_NAME을 함수의 이름으로 바꿉니다.

로컬에서 실행 중인 함수 호출

이 섹션의 연습에서는 Functions 프레임워크를 사용하여 localhost에서 로컬 실행 함수를 설정했다고 가정합니다.

로컬 제공 프로세스를 사용하여 라우팅된 HTTP 요청을 보내 로컬에서 실행되는 함수를 트리거할 수 있습니다.

HTTP 함수

개발 환경에서 HTTP 함수를 테스트하면 일반적으로 localhost:8080에서 요청을 리슨합니다. 이 인터페이스는 함수가 실행 중인 머신이나 VM에서만 액세스할 수 있습니다. 다른 시스템에서 보낸 요청은 도달할 수 없습니다. 이러한 이유로 함수가 실행 중인 동일한 시스템에서 HTTP 요청을 실행해야 합니다. 다음 예시에서 함수가 8080 이외의 포트에서 리슨하는 경우 예시의 8080을 함수의 포트 번호로 바꿉니다.

Cloud Shell로 HTTP 함수 테스트

Cloud Shell을 사용하여 함수를 빌드하고 테스트하는 경우 Cloud Shell 터미널 창에서 로컬로 함수를 시작한 후 다음과 같이 브라우저나 curl 인스턴스에서 HTTP 트리거 요청을 실행합니다.

브라우저

Cloud Shell 툴바에서 웹 미리보기 버튼 아이콘을 클릭하고 포트 8080 또는 포트 변경을 선택하여 다른 포트를 선택합니다. 그러면 올바른 시스템에서 브라우저 창이 열리고 표시된 포트에 GET 요청이 실행됩니다.

Curl

HTTP 요청 형식을 제어하거나 서식이 없는 응답을 보려면 curl을 사용합니다.

  1. Cloud Shell 메뉴 바에서 + 아이콘을 클릭하여 함수가 실행되는 동일한 시스템에서 새 터미널 창을 엽니다.
  2. 해당 창에서 curl 명령어를 실행하여 함수를 트리거합니다. 예를 들면 다음과 같습니다.

    curl localhost:8080
    

데스크톱 서버에서 HTTP 함수 테스트

로컬 데스크톱 시스템에서 함수를 빌드하고 실행하는 경우 먼저 함수를 로컬에서 시작한 후 다음과 같이 브라우저나 curl 인스턴스에서 HTTP 트리거 요청을 실행합니다.

브라우저

새 브라우저 창이나 탭을 열고 브라우저 주소 표시줄에 http://localhost:8080을 입력합니다. 그러면 데스크톱 서버에서 localhost:8080에 대한 브라우저 창이 열리고 함수가 트리거됩니다.

Curl

로컬 데스크톱에서 새 터미널 창을 연 다음 해당 창에서 curl 명령어를 실행하여 함수를 트리거합니다. 예를 들면 다음과 같습니다.

 curl localhost:8080

이렇게 하면 지정된 curl 명령어가 실행되어 함수를 트리거하고 형식이 지정되지 않은 응답을 표시합니다.

CloudEvent 함수

curl을 사용하여 샘플 이벤트를 CloudEvent 함수로 보낼 수 있습니다. 다음 curl 요청은 localhost:8080에서 실행되는 CloudEvent 함수에 Pub/SubCloud Storage 샘플 이벤트를 전송하는 방법을 보여줍니다.

Pub/Sub

curl localhost:8080 \
  -X POST \
  -H "Content-Type: application/json" \
  -H "ce-id: 123451234512345" \
  -H "ce-specversion: 1.0" \
  -H "ce-time: 2020-01-02T12:34:56.789Z" \
  -H "ce-type: google.cloud.pubsub.topic.v1.messagePublished" \
  -H "ce-source: //pubsub.googleapis.com/projects/MY-PROJECT/topics/MY-TOPIC" \
  -d '{
        "message": {
          "data": "d29ybGQ=",
          "attributes": {
             "attr1":"attr1-value"
          }
        },
        "subscription": "projects/MY-PROJECT/subscriptions/MY-SUB"
      }'
    

Cloud Storage

curl localhost:8080 \
  -X POST \
  -H "Content-Type: application/json" \
  -H "ce-id: 123451234512345" \
  -H "ce-specversion: 1.0" \
  -H "ce-time: 2020-01-02T12:34:56.789Z" \
  -H "ce-type: google.cloud.storage.object.v1.finalized" \
  -H "ce-source: //storage.googleapis.com/projects/_/buckets/MY-BUCKET-NAME" \
  -H "ce-subject: objects/MY_FILE.txt" \
  -d '{
        "bucket": "MY_BUCKET",
        "contentType": "text/plain",
        "kind": "storage#object",
        "md5Hash": "...",
        "metageneration": "1",
        "name": "MY_FILE.txt",
        "size": "352",
        "storageClass": "MULTI_REGIONAL",
        "timeCreated": "2020-04-23T07:38:57.230Z",
        "timeStorageClassUpdated": "2020-04-23T07:38:57.230Z",
        "updated": "2020-04-23T07:38:57.230Z"
      }'