App Engine용 Cloud Endpoints Frameworks 버전 2.0으로 마이그레이션

이 페이지에서는 자바에서 기존의 Cloud Endpoints 버전 1.0 애플리케이션을 App Engine용 Endpoints 프레임워크로 마이그레이션하는 방법을 설명합니다.

장점

새로운 프레임워크에는 다음과 같은 여러 가지 장점이 있습니다.

  • 요청 지연 시간 감소
  • App Engine 기능(예: 커스텀 도메인)과의 통합 향상
  • Guice 구성 공식 지원
  • 새로운 API 관리 기능(선택사항)

Endpoints Frameworks 버전 2.0은 API에 대한 인터페이스에 영향을 주지 않습니다. 기존 클라이언트는 이전 후에도 클라이언트 측 코드 변경 없이 계속 작동합니다.

현재 제외된 기능과 도구

다음 기능은 현재 사용할 수 없습니다. 이 중에서 필요한 기능이 있으면 기능 요청을 제출하세요.

  • 기존 iOS 클라이언트에 필요한 JSON-RPC 프로토콜. Endpoints 프레임워크 버전 2.0 API의 iOS 클라이언트를 만들려면 REST API용 Google API Objective-C 클라이언트 라이브러리를 사용하는 것이 좋습니다.
  • 자동 ETag
  • 자동 종류 필드
  • IDE 통합
  • fields 부분 응답
  • 자동 PATCH API 메서드 생성

또한 Android 스튜디오는 Endpoints 버전 1.0은 지원하지만 버전 2.0은 현재 지원하지 않습니다.

Endpoints 프레임워크 버전 2.0으로 마이그레이션

Endpoints 프레임워크 버전 2.0은 com.google.endpoints 그룹의 Maven 아티팩트로 이동되었습니다. 기본 필수 JAR은 endpoints-framework 아티팩트에 있습니다. Guice 구성을 사용하려면 endpoints-framework-guice 아티팩트를 추가하세요.

다음 안내에서는 검색 문서를 사용하여 Endpoints 프레임워크 버전 1.0에서 Endpoints 프레임워크 버전 2.0으로 마이그레이션하는 방법의 예시를 보여줍니다.

  1. Cloud SDK를 다운로드하고 초기화합니다.
  2. 다음 명령어를 실행합니다.
    1. Cloud SDK에 Google Cloud의 데이터 및 서비스에 액세스할 수 있는 권한이 있는지 확인합니다.
      gcloud auth login
    2. 애플리케이션 기본 사용자 인증 정보를 사용합니다.
      gcloud auth application-default login
    3. Cloud SDK app-engine-java 구성요소를 설치합니다.
      gcloud components install app-engine-java
    4. Cloud SDK와 모든 구성요소를 최신 버전으로 업데이트합니다.
      gcloud components update

Maven 또는 Gradle을 사용하여 이전

Maven

  1. 기존 종속 항목인 appengine-endpoints 아티팩트를 삭제합니다.
    <dependency>
          <groupId>com.google.appengine</groupId>
          <artifactId>appengine-endpoints</artifactId>
          <version>1.9.53</version>
    </dependency>
  2. 새로운 Endpoints Frameworks 종속 항목을 추가합니다.
    <dependency>
        <groupId>com.google.endpoints</groupId>
        <artifactId>endpoints-framework</artifactId>
        <version>2.2.1</version>
    </dependency>
  3. 새로운 Endpoints Frameworks 플러그인을 추가하고 생성된 검색 문서의 호스트 이름을 정의합니다.
    <plugin>
        <groupId>com.google.cloud.tools</groupId>
        <artifactId>endpoints-framework-maven-plugin</artifactId>
        <version>1.0.2</version>
        <configuration>
            <!-- plugin configuration -->
            <hostname>YOUR-PROJECT-ID.appspot.com</hostname>
        </configuration>
    </plugin>
  4. 새로운 App Engine Maven 플러그인을 추가합니다.
    <plugin>
        <groupId>com.google.cloud.tools</groupId>
        <artifactId>appengine-maven-plugin</artifactId>
        <version>1.3.2</version>
        <configuration>
            <!-- deploy configuration -->
        </configuration>
    </plugin>
  5. 프로젝트 web.xml 파일에서 API 진입점을 업데이트합니다.
    • SystemServiceServlet이라는 이름을 모두 EndpointsServlet으로 바꿉니다.
    • /_ah/spi/ 경로를 모두 새로운 필수 경로인 /_ah/api/ 바꿉니다.

    다음은 마이그레이션 전과 후의 web.xml 내용입니다.

    마이그레이션 전

    Endpoints Frameworks 버전 1.0 web.xml:
    <servlet>
        <servlet-name>SystemServiceServlet</servlet-name>
        <servlet-class>com.google.api.server.spi.SystemServiceServlet</servlet-class>
        <init-param>
            <param-name>services</param-name>
            <param-value>com.example.helloendpoints.Greetings</param-value>
        </init-param>
        <init-param>
            <param-name>restricted</param-name>
            <param-value>false</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>SystemServiceServlet</servlet-name>
        <url-pattern>/_ah/spi/*</url-pattern>
    </servlet-mapping>

    마이그레이션 후

    Endpoints Frameworks 버전 2.0 web.xml:
    <servlet>
        <servlet-name>EndpointsServlet</servlet-name>
        <servlet-class>com.google.api.server.spi.EndpointsServlet</servlet-class>
        <init-param>
            <param-name>services</param-name>
            <param-value>com.example.helloendpoints.Greetings</param-value>
        </init-param>
        <init-param>
            <param-name>restricted</param-name>
            <param-value>false</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>EndpointsServlet</servlet-name>
        <url-pattern>/_ah/api/*</url-pattern>
    </servlet-mapping>

  6. 종속 항목을 수정한 후 프로젝트를 정리합니다.
    mvn clean
  7. 검색 문서를 생성할 수 있습니다.
    mvn endpoints-framework:discoveryDocs
    Maven Endpoints Frameworks 플러그인 목표에 대해 자세히 알아보세요.
  8. 프로젝트를 배포할 수 있습니다.
    mvn appengine:deploy

    Maven App Engine 플러그인 목표에 대해 자세히 알아보세요.

Gradle

  1. 기존 종속 항목인 appengine-endpoints 아티팩트를 삭제합니다.
    compile group: 'com.google.appengine', name: 'appengine-endpoints', version: '+'
  2. 새로운 Endpoints Frameworks 종속 항목을 추가합니다.
    compile group: 'com.google.endpoints', name: 'endpoints-framework', version: '2.0.8'
  3. 새로운 App Engine 및 Endpoints Frameworks 플러그인을 추가합니다.
    buildscript {    // Configuration for building
      repositories {
        mavenCentral()
        jcenter()    // Bintray's repository - a fast Maven Central mirror & more
      }
      dependencies {
        // App Engine Gradle plugin
        classpath 'com.google.cloud.tools:appengine-gradle-plugin:1.3.3'
    
        // Endpoints Frameworks Gradle plugin
        classpath 'com.google.cloud.tools:endpoints-framework-gradle-plugin:1.0.2'
      }
    }
  4. 새로운 App Engine 및 Endpoints Frameworks 플러그인을 적용합니다.
    apply plugin: 'com.google.cloud.tools.appengine'
    apply plugin: 'com.google.cloud.tools.endpoints-framework-server'
  5. 생성된 검색 문서의 호스트 이름 엔드포인트를 정의합니다.
    endpointsServer {
      // Endpoints Framework Plugin server-side configuration
      hostname = "YOUR-PROJECT-ID.appspot.com"
    }
  6. 프로젝트 web.xml 파일에서 API 진입점을 업데이트합니다.
    • SystemServiceServlet이라는 이름을 모두 EndpointsServlet으로 바꿉니다.
    • /_ah/spi/ 경로를 모두 새로운 필수 경로인 /_ah/api/ 바꿉니다.

    다음은 마이그레이션 전과 후의 web.xml 내용입니다.

    마이그레이션 전

    Endpoints Frameworks 버전 1.0 web.xml:
    <servlet>
        <servlet-name>SystemServiceServlet</servlet-name>
        <servlet-class>com.google.api.server.spi.SystemServiceServlet</servlet-class>
        <init-param>
            <param-name>services</param-name>
            <param-value>com.example.helloendpoints.Greetings</param-value>
        </init-param>
        <init-param>
            <param-name>restricted</param-name>
            <param-value>false</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>SystemServiceServlet</servlet-name>
        <url-pattern>/_ah/spi/*</url-pattern>
    </servlet-mapping>

    마이그레이션 후

    Endpoints Frameworks 버전 2.0 web.xml:
    <servlet>
        <servlet-name>EndpointsServlet</servlet-name>
        <servlet-class>com.google.api.server.spi.EndpointsServlet</servlet-class>
        <init-param>
            <param-name>services</param-name>
            <param-value>com.example.helloendpoints.Greetings</param-value>
        </init-param>
        <init-param>
            <param-name>restricted</param-name>
            <param-value>false</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>EndpointsServlet</servlet-name>
        <url-pattern>/_ah/api/*</url-pattern>
    </servlet-mapping>

  7. 종속 항목을 수정한 후 다음 명령어를 사용하여 프로젝트를 정리합니다.
    gradle clean
  8. 다음 명령어를 사용하여 검색 문서를 생성할 수 있습니다.
    gradle endpointsDiscoveryDocs
    Gradle Endpoints Frameworks 플러그인 작업에 대해 자세히 알아보세요.
  9. 다음 명령어를 사용하여 프로젝트를 배포할 수 있습니다.
    gradle appengineDeploy

    Gradle App Engine 플러그인 작업에 대해 자세히 알아보세요.

Guice를 사용하여 자바용 Endpoints Frameworks 구성

Guice를 사용하려면 다음 안내를 따르세요.

  1. 새로운 Endpoints Frameworks Guice 종속 항목을 추가합니다.

    Maven

    <dependency>
        <groupId>com.google.endpoints</groupId>
        <artifactId>endpoints-framework-guice</artifactId>
        <version>2.2.1</version>
    </dependency>

    Gradle

    compile 'com.google.endpoints:endpoints-framework-guice:2.0.9'
  2. EndpointsModule을 확장하는 새로운 모듈을 선언하고 다음과 같이 구성합니다.
    public class EchoEndpointModule extends EndpointsModule {
      @Override
      public void configureServlets() {
        super.configureServlets();
    
        bind(ServiceManagementConfigFilter.class).in(Singleton.class);
        filter("/_ah/api/*").through(ServiceManagementConfigFilter.class);
    
        Map<String, String> apiController = new HashMap<String, String>();
        apiController.put("endpoints.projectId", "YOUR-PROJECT-ID");
        apiController.put("endpoints.serviceName", "YOUR-PROJECT-ID.appspot.com");
    
        bind(GoogleAppEngineControlFilter.class).in(Singleton.class);
        filter("/_ah/api/*").through(GoogleAppEngineControlFilter.class, apiController);
    
        bind(Echo.class).toInstance(new Echo());
        configureEndpoints("/_ah/api/*", ImmutableList.of(Echo.class));
      }
    }

새 배포 확인

새 프레임워크가 트래픽을 제공하는지 확인할 수 있습니다.

  1. 새 배포에 요청을 보냅니다.
  2. Cloud Console에서 Stackdriver Logging > 로그(로그 뷰어) 페이지로 이동합니다.

    로그 뷰어 페이지로 이동

  3. 요청에 표시되는 경로가 /_ah/api로 시작된다면 Endpoints 프레임워크 버전 2.0이 API를 제공하고 있는 것입니다. 경로가 /_ah/spi로 시작되는 요청은 로그에 표시되지 않아야 합니다. 이러한 요청은 Endpoints Frameworks 버전 1.0 프록시에서 여전히 요청을 처리하고 있음을 나타냅니다.

Endpoints API 관리 추가

Endpoints Frameworks 버전 2.0에서는 다음을 비롯한 API 관리 기능도 사용할 수 있습니다.

  • API 키 관리
  • API 공유
  • 사용자 인증
  • API 측정항목
  • API 로그

이러한 기능을 사용하려면 API 관리 추가를 참조하세요.

문제해결

이 섹션에서는 Endpoints 프레임워크 버전 2.0으로 마이그레이션할 때 일반적으로 나타나는 불안정한 동작과 추천 해결 방법을 설명합니다.

API는 404 오류를 반환하지만 API 탐색기에는 API가 올바르게 표시됨

Endpoints 프레임워크 버전 2.0으로 마이그레이션할 때는 이전의 Endpoints 프레임워크 버전 1.0 구성을 삭제해야 합니다. 애플리케이션 구성에 이전 구성이 남아 있으면 Endpoints 서비스가 앱을 계속 버전 1.0 앱으로 취급합니다. 이러한 경우 /_ah/spi로 전송된 요청이 App Engine 로그에 나타날 수 있으며, 이로 인해 클라이언트에 HTTP 404 오류가 전송됩니다.

  1. web.xml 파일에 다음 줄이 있으면 삭제합니다.

    <servlet>
        <servlet-name>SystemServiceServlet</servlet-name>
        <servlet-class>com.google.api.server.spi.SystemServiceServlet</servlet-class>
        <init-param>
            <param-name>services</param-name>
            <param-value>...</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>SystemServiceServlet</servlet-name>
        <url-pattern>/_ah/spi/*</url-pattern>
    </servlet-mapping>
    
  2. web.xml 파일이 다음을 포함하는지 확인합니다.

    <servlet-mapping>
        <servlet-name>EndpointsServlet</servlet-name>
        <url-pattern>/_ah/api/*</url-pattern>
    </servlet-mapping>
    

API에서 리플렉션 오류 발생

애플리케이션에 이전의 appengine-endpoints JAR이 아닌 endpoints-framework 아티팩트만 패키징해야 합니다. 두 JAR을 모두 포함하여 애플리케이션을 배포하면 리플렉션 오류 또는 NoClassDefFoundError, NoSuchMethodError, ClassCastException 등의 런타임 유형 오류가 발생할 수 있습니다. 빌드 파일에 다음 줄이 있으면 삭제합니다.

Maven

<dependency>
      <groupId>com.google.appengine</groupId>
      <artifactId>appengine-endpoints</artifactId>
      <version>1.9.53</version>
</dependency>

Gradle

compile group: 'com.google.appengine', name: 'appengine-endpoints', version: '+'

또한 다른 종속 항목 중 하나라도 Guava의 이전 버전을 사용하면 TypeToken 메서드 누락이 발생할 수 있습니다. 따라서 Guava v19를 사용하거나 종속 항목을 섀도잉하는 endpoints-framework-all 아티팩트를 사용하는지 확인해야 합니다.

클라이언트 라이브러리 소스가 컴파일되지 않음

method does not override or implement a method from a supertype 또는 cannot find symbol method setBatchPath(String) 등의 오류가 발생하면 클라이언트 애플리케이션이 Google 자바 클라이언트 라이브러리의 이전 버전을 사용하고 있을 가능성이 높습니다. google-api-client 아티팩트가 1.23.0 이상인지 확인해야 합니다.

Maven

<dependency>
    <groupId>com.google.api-client</groupId>
    <artifactId>google-api-client</artifactId>
    <version>1.23.0</version>
</dependency>

Gradle

compile group: 'com.google.api-client', name: 'google-api-client', version: '1.23.0'

JPA/JDO Datanucleus 향상 관련 문제

Maven

새로운 Cloud SDK 기반 App Engine Maven 플러그인은 어떠한 유형의 Datanucleus 향상도 지원하지 않습니다. 프로젝트에서 이전 플러그인의 Datanucleus JDO 또는 JPA 향상 지원을 사용하는 경우에는 이전할 때 타사 Datanucleus Maven 플러그인을 별도로 구성해야 합니다. 자세한 내용은 다음을 참조하세요.

Gradle

프로젝트가 gradle-appengine-plugin 향상을 사용하는 경우 새로운 Cloud SDK 기반 Gradle 플러그인으로 전환한 후에 수동으로 Datanucleus 향상을 구성해야 합니다. Stackoverflow 예시를 참조하세요.