Java 배포 옵션

자바 함수를 배포하는 데는 2가지 방법이 있습니다.

소스에서 배포

함수의 소스 코드가 Maven 프로젝트의 일반적인 위치에 있어야 합니다(src/main/java). 이 문서의 샘플 함수는 src/main/java에 직접 위치하며 .java 소스 파일에는 패키지 선언이 없습니다. 중요한 코드의 경우 패키지를 도입할 가능성이 높습니다. 패키지가 com.example이면 계층 구조는 다음과 같습니다.

myfunction/
├─ pom.xml
├─ src
    ├─main
        ├─ java
            ├─ com
                ├─ example
                    ├─ MyFunction.java

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

gcloud functions deploy $name --trigger-http \
    --entry-point $function_class --runtime java21

각 항목의 의미는 다음과 같습니다.

  • $name은 배포되고 있는 함수의 이름이 되는 임의의 설명이 포함된 이름입니다. $name에는 문자, 숫자, 밑줄, 하이픈만 포함할 수 있습니다.
  • $function_class는 클래스의 정규화된 이름입니다(예: com.example.MyFunction 또는 패키지를 사용하지 않는 경우 간단히 MyFunction).

다음 명령어를 사용하여 이벤트 기반 함수를 배포합니다.

gcloud functions deploy $name --no-gen2 --entry-point $function_class \
    --trigger-resource $resource_name \
    --trigger-event $event_name \
    --runtime java21

각 항목의 의미는 다음과 같습니다.

  • $name은 배포되고 있는 함수의 이름이 되는 임의의 설명이 포함된 이름입니다.
  • $function_class는 클래스의 정규화된 이름입니다(예: com.example.MyFunction 또는 패키지를 사용하지 않는 경우 간단히 MyFunction).
  • $resource_name$event_name은 함수를 트리거하는 이벤트에 따라 다릅니다. 지원되는 리소스 및 이벤트의 예로는 Google Cloud Pub/SubGoogle Cloud Storage가 있습니다.

소스에서 함수를 배포할 때 Google Cloud CLI는 소스 디렉터리(및 모든 하위 디렉터리 포함)를 Google Cloud에 업로드하여 빌드합니다. 불필요한 파일을 전송하지 않으려면 .gcloudignore 파일을 사용하면 됩니다. .gcloudignore 파일을 수정하여 .gittarget/과 같은 일반 디렉터리를 무시합니다. 예를 들어 .gcloudignore 파일에 다음이 포함될 수 있습니다.

.git
target
build
.idea

JAR에서 배포

함수가 포함된 사전 빌드된 JAR을 배포할 수 있습니다. 이는 소스에서 빌드할 때 Google Cloud의 빌드 파이프라인에서 액세스할 수 없는 비공개 아티팩트 스토리지의 종속 항목을 사용하는 함수를 배포해야 하는 경우에 유용합니다. JAR은 함수 클래스와 모든 종속 항목 클래스를 포함하는 Uber JAR이거나 META-INF/MANIFEST.MF 파일에 종속 항목 JAR에 대한 Class-Path 항목이 있는 씬 JAR일 수 있습니다.

Uber JAR 빌드 및 배포

Uber JAR은 함수 클래스와 모든 종속 항목을 포함하는 JAR 파일입니다. Maven 및 Gradle을 사용하여 Uber JAR을 빌드할 수 있습니다. Uber JAR을 배포하려면 이 파일이 자체 디렉터리의 유일한 JAR 파일이어야 합니다. 예를 들면 다음과 같습니다.

my-function-deployment/
 ├─ my-function-with-all-dependencies.jar

이 디렉터리 구조에 파일을 복사하거나 Maven 및 Gradle 플러그인을 사용하여 올바른 배포 디렉터리를 생성할 수 있습니다.

Maven

Maven Shade 플러그인을 사용하여 Uber JAR을 빌드합니다. Shade 플러그인으로 pom.xml을 구성합니다.

<?xml version="1.0" encoding="UTF-8"?>
<project ...>
  ...
  <build>
    ...
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <executions>
          <execution>
            <phase>package</phase>
            <goals><goal>shade</goal></goals>
            <configuration>
              <outputFile>${project.build.directory}/deployment/${build.finalName}.jar</outputFile>
              <transformers>
                <!-- This may be needed if you need to shade a signed JAR -->
                <transformer implementation="org.apache.maven.plugins.shade.resource.DontIncludeResourceTransformer">
                  <resource>.SF</resource>
                  <resource>.DSA</resource>
                  <resource>.RSA</resource>
                </transformer>
                <!-- This is needed if you have dependencies that use Service Loader. Most Google Cloud client libraries does. -->
                <transformer implementation=
       "org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

Uber JAR을 빌드합니다.

mvn package

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

gcloud functions deploy jar-example \
    --entry-point=Example \
    --runtime=java21 \
    --trigger-http \
    --source=target/deployment

Gradle

Gradle용 Shadow 플러그인을 사용합니다. build.gradle 파일에서 플러그인을 설정합니다.

buildscript {
   repositories {
       jcenter()
   }
   dependencies {
       ...
       classpath "com.github.jengelman.gradle.plugins:shadow:5.2.0"
   }
}

plugins {
   id 'java'
   ...
}
sourceCompatibility = '17.0'
targetCompatibility = '17.0'
apply plugin: 'com.github.johnrengelman.shadow'

shadowJar {
   mergeServiceFiles()
}
...

이제 shadowJar 명령어를 사용하여 Gradle을 실행할 수 있습니다.

gradle shadowJar

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

gcloud functions deploy jar-example \
   --entry-point=Example \
   --runtime=java21 \
   --trigger-http \
   --source=build/libs

외부 종속 항목을 사용하여 씬 JAR 빌드 및 배포

Uber JAR이 아닌 씬 JAR 파일을 빌드하고 배포할 수 있습니다. 씬 JAR은 동일한 JAR 파일에 삽입된 종속 항목 없이 함수 클래스만 포함된 JAR 파일입니다. 배포에는 여전히 종속 항목이 필요하므로 다음과 같이 설정해야 합니다.

  • 배포할 JAR보다 한 수준 낮은 하위 디렉터리에 종속 항목이 있어야 합니다.
  • JAR에는 값에 필수 종속 항목 경로가 나열된 Class-Path 속성이 포함된 META-INF/MANIFEST.MF 파일이 있어야 합니다.

예를 들어 JAR 파일 my-function.jar에는 libs/ 디렉터리에 2개의 종속 항목이 있는 META-INF/MANIFEST.MF 파일이 있습니다(공백으로 구분된 상대 경로 목록).

Manifest-Version: 1.0
Class-Path: libs/dep1.jar libs/dep2.jar

그러면 배포 디렉터리에 기본 함수 JAR 파일은 물론 함수가 종속되는 두 종속 항목이 있는 하위 디렉터리가 포함되어 있어야 합니다.

function-deployment/
├─ my-function.jar
├─ libs
       ├─ dep1.jar
       ├─ dep2.jar

Maven 및 Gradle을 모두 사용하여 씬 JAR을 빌드할 수 있습니다.

Maven

Maven JAR 플러그인을 사용하여 종속 항목의 경로로 MANIFEST.MF를 자동으로 구성하고 Maven 종속 항목 플러그인을 사용하여 종속 항목을 복사합니다.

<?xml version="1.0" encoding="UTF-8"?>
<project ...>
  ...
  <build>
    ...
    <plugins>
      <plugin>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
          <archive>
            <manifest>
              <addClasspath>true</addClasspath>
              <classpathPrefix>libs/</classpathPrefix>
            </manifest>
          </archive>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>copy-dependencies</goal>
            </goals>
            <configuration>
              <overWriteReleases>false</overWriteReleases>
              <includeScope>runtime</includeScope>
              <outputDirectory>${project.build.directory}/libs</outputDirectory>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-resources-plugin</artifactId>
        <executions>
          <execution>
            <id>copy-resources</id>
            <phase>package</phase>
            <goals><goal>copy-resources</goal></goals>
            <configuration>
              <outputDirectory>${project.build.directory}/deployment</outputDirectory>
              <resources>
                <resource>
                  <directory>${project.build.directory}</directory>
                  <includes>
                    <include>${build.finalName}.jar</include>
                    <include>libs/**</include>
                  </includes>
                  <filtering>false</filtering>
                </resource>
              </resources>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

씬 JAR을 빌드합니다.

mvn package

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

gcloud functions deploy jar-example \
    --entry-point=Example \
    --runtime=java21 \
    --trigger-http \
    --source=target/deployment

Gradle

build.gradle 프로젝트 파일을 업데이트하여 종속 항목을 가져올 새 작업을 추가합니다.

dependencies {
   // API available at compilation only, but provided at runtime
   compileOnly 'com.google.cloud.functions:functions-framework-api:1.0.1'
   // dependencies needed by the function
   // ...
}

jar {
 manifest {
   attributes(
     "Class-Path": provider {
         configurations.runtimeClasspath
           .collect { "libs/${it.name}" }.join(' ')
     }
   )
 }
}

task prepareDeployment(type: Copy) {
 into("${buildDir}/deployment")
 into('.') {
   from jar
 }
 into('libs') {
   from configurations.runtimeClasspath
 }
}