Go 1.11은 지원이 종료되었으며 2026년 1월 31일에 지원 중단됩니다. 지원 중단 후에는 조직에서 이전에 조직 정책을 사용하여 레거시 런타임의 배포를 다시 사용 설정한 경우에도 Go 1.11 애플리케이션을 배포할 수 없습니다. 기존 Go 1.11 애플리케이션은 지원 중단 날짜 이후에도 계속 실행되고 트래픽을 수신합니다. 지원되는 최신 Go 버전으로 마이그레이션하는 것이 좋습니다.
Google Cloud CLI에는 Go 애플리케이션에서 App Engine 서비스에 투명하게 액세스할 수 있도록 하는 remote_api 패키지가 포함되어 있습니다. 예를 들어 Remote API를 사용하여 로컬 머신에서 실행되는 앱 또는 다른 App Engine 앱에서 Datastore에 액세스할 수 있습니다.
먼저 app.yaml에 remote_apiurl 핸들러를 추가합니다. 예를 들면 다음과 같습니다.
- url: /_ah/remote_api
script: _go_app
그러면 URL /_ah/remote_api가 Go 앱에 매핑됩니다. 이 URL에 대한 액세스는 Remote API 핸들러에 의해 애플리케이션 관리자로 제한됩니다.
그런 다음 .go 소스 파일에 다음 줄을 추가하여 프로젝트의 패키지 중 하나에서 remote_api 패키지를 가져옵니다.
import_"google.golang.org/appengine/remote_api"
프로그램이 초기화되는 동안 remote_api 패키지는 /_ah/remote_api 경로의 핸들러를 등록합니다. 가져오기 선언의 밑줄 표시는 '이 패키지를 가져오지만 직접 사용하지 않을 것'을 의미합니다. 밑줄이 없으면 컴파일 시 '가져 왔지만 사용되지 않음' 오류 메시지가 표시됩니다.
Remote API는 App Engine 서비스를 사용하고 Datastore에 액세스하는 로컬 애플리케이션을 작성하는 데 사용할 수 있습니다. Remote API를 사용하면 액세스 중인 애플리케이션에서 할당량이 사용된다는 점에 유의해야 합니다.
시작하기 전에 App Engine 애플리케이션에서 Remote API가 사용 설정되어 있는지 확인하세요. 로컬 애플리케이션에서 Remote API를 사용하려면 remote_api.NewRemoteContext로 컨텍스트를 생성하고 모든 API 호출에서 일반 App Engine 컨텍스트 대신 사용하면 됩니다.
// Copyright 2011 Google Inc. All rights reserved.// Use of this source code is governed by the Apache 2.0// license that can be found in the LICENSE file.packagemainimport("log""time""golang.org/x/net/context""golang.org/x/oauth2/google""google.golang.org/appengine/datastore""google.golang.org/appengine/remote_api")funcmain(){consthost="<your-app-id>.appspot.com"ctx:=context.Background()hc,err:=google.DefaultClient(ctx,"https://www.googleapis.com/auth/appengine.apis","https://www.googleapis.com/auth/userinfo.email","https://www.googleapis.com/auth/cloud-platform",)iferr!=nil{log.Fatal(err)}remoteCtx,err:=remote_api.NewRemoteContext(host,hc)iferr!=nil{log.Fatal(err)}q:=datastore.NewQuery("Greeting").Filter("Date >=",time.Now().AddDate(0,0,-7))log.Println(q.Count(remoteCtx))}
서버의 호스트 이름과 NewRemoteContext에 대한 호출의 http.Client를 제공해야 합니다. 제공된 http.Client는 각 요청에 필요한 인증 정보를 전달해야 합니다.
위의 샘플에서 golang.org/x/oauth2/google 패키지의 DefaultClient는 애플리케이션 기본 사용자 인증 정보를 통해 OAuth 2 사용자 인증 정보를 제공합니다.
제한사항 및 권장사항
remote_api 모듈은 기본 App Engine Datastore와 완전히 동일하게 작동되도록 하기 위해 최대한으로 시도합니다. 즉, 경우에 따라 효율성이 떨어지는 작업을 수행하기도 한다는 의미입니다. 따라서 remote_api를 사용할 때는 다음 사항에 주의하시기 바랍니다.
모든 Datastore 요청에 왕복이 필요함
HTTP를 통해 Datastore에 액세스하는 경우 로컬에서 액세스할 때보다 오버헤드와 지연 시간이 좀 더 늘어날 수 있습니다. 시간을 단축하고 부하를 줄이기 위해서는 get과 put 작업을 일괄 처리하고 쿼리 항목을 일괄적으로 가져와 왕복 횟수를 제한해야 합니다. 일괄 작업은 단일 Datastore 작업으로만 간주되기 때문에 이 방식은 remote_api뿐만 아니라 일반적으로 Datastore를 사용할 때도 유용합니다.
remote_api 요청 시 할당량이 사용됨
remote_api가 HTTP를 통해 작동하므로 Datastore를 호출할 때마다 HTTP 요청에 대한 할당량(바이트 단위 입출력)뿐만 아니라 일반적으로 예상되는 Datastore 할당량이 차감됩니다. 일괄 업데이트에 remote_api를 사용하는 경우 이 점을 염두에 두시기 바랍니다.
1MB API 제한 적용
기본 실행에서와 마찬가지로 API 요청 및 응답에는 1MB 제한이 계속 적용됩니다. 특히 항목 크기가 큰 경우 이 한도가 초과되지 않도록 한 번에 수행하는 fetch 또는 put 작업 횟수를 제한해야 할 수 있습니다. 이 경우 왕복을 최소화하는 접근 방식과 상충되기 때문에 요청 또는 응답 크기의 제한을 넘지 않는 범위 내에서 가장 큰 배치를 사용하는 것이 좋습니다. 그러나 대부분의 항목에서는 이 제한이 문제가 되지 않습니다.
쿼리 반복 방지
쿼리를 반복 실행하는 경우 SDK에서는 Datastore의 항목을 20개 단위의 배치로 가져오며 기존의 항목이 소모될 때마다 새 배치를 가져옵니다.
각 배치는 remote_api를 통해 별도 요청으로 가져와야 하기 때문에 효율성이 떨어질 수밖에 없습니다. 대신 remote_api는 오프셋 기능을 사용하여 배치별로 완전히 새로운 쿼리를 실행하므로 결과의 정확성이 높아집니다.
필요한 항목 수를 알고 있다면 필요한 숫자를 요청하는 방식으로 하나의 요청에서 전체 가져오기를 처리할 수 있습니다.
원하는 항목 수를 모르는 경우에는 커서를 사용하여 큰 결과 집합을 효율적으로 반복할 수 있습니다. 이렇게 하면 일반적인 Datastore 쿼리에 적용되는 1,000개 항목 제한을 피할 수 있습니다.
트랜잭션의 효율성이 떨어짐
remote_api를 통해 트랜잭션을 구현하기 위해 트랜잭션 내에서 가져온 항목에 대한 정보와 트랜잭션 내에서 배치 또는 삭제한 항목의 사본이 축적됩니다. 트랜잭션이 커밋되면 이 모든 정보가 App Engine 서버로 전송되며, 이때 트랜잭션에 사용된 모든 항목을 다시 가져와 변경되지 않았는지 확인한 다음 트랜잭션에 적용된 모든 변경사항에 대해 put 및 delete 작업을 수행한 후 커밋합니다. 충돌이 발생하면 서버가 트랜잭션을 롤백하고 클라이언트 측에 이를 알립니다. 그러면 클라이언트가 전체 프로세스를 처음부터 다시 반복해야 합니다.
이 접근 방식은 제대로 작동하며 트랜잭션에서 제공된 기능을 로컬 Datastore에 정확하게 복제하지만, 다소 비효율적입니다. 따라서 어떤 경우에도 꼭 필요한 경우에만 트랜잭션을 사용해야 하며 효율성을 위해 실행할 트랜잭션의 수와 복잡성을 제한해야 합니다.
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["이해하기 어려움","hardToUnderstand","thumb-down"],["잘못된 정보 또는 샘플 코드","incorrectInformationOrSampleCode","thumb-down"],["필요한 정보/샘플이 없음","missingTheInformationSamplesINeed","thumb-down"],["번역 문제","translationIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-09-04(UTC)"],[[["\u003cp\u003eThe Google Cloud CLI's \u003ccode\u003eremote_api\u003c/code\u003e package allows Go applications to access App Engine services, including Datastore, from outside of the App Engine environment, such as a local machine.\u003c/p\u003e\n"],["\u003cp\u003eEnabling the Remote API requires adding a \u003ccode\u003eurl\u003c/code\u003e handler to your \u003ccode\u003eapp.yaml\u003c/code\u003e file and importing the \u003ccode\u003eremote_api\u003c/code\u003e package into your Go project, with specific attention to using the underscore import notation.\u003c/p\u003e\n"],["\u003cp\u003eLocal applications can interact with App Engine services by creating a context with \u003ccode\u003eremote_api.NewRemoteContext\u003c/code\u003e and utilizing it instead of the regular App Engine context in API calls, with the necessary credentials provided through an \u003ccode\u003ehttp.Client\u003c/code\u003e.\u003c/p\u003e\n"],["\u003cp\u003eUsing the \u003ccode\u003eremote_api\u003c/code\u003e package involves certain considerations, such as increased latency due to HTTP round-trips, quota usage for every Datastore call, and the 1MB API request/response limits, which may require batching of operations.\u003c/p\u003e\n"],["\u003cp\u003eWhen querying data, it's recommended to avoid iterating over queries due to inefficiency and use cursors for large result sets, and while transactions are supported, they are less efficient and should be used sparingly.\u003c/p\u003e\n"]]],[],null,["# Accessing App Engine with Remote API\n\nThe Google Cloud CLI includes a `remote_api` package that lets you transparently\naccess App Engine services from any Go application. For example, you can use the\nRemote API to access Datastore from an app running on your local\nmachine or from another one of your App Engine apps.\n\nTo view the contents of the `remote_api` package, see the\n[`remote_api` package](/appengine/docs/legacy/standard/go111/tools/remoteapi/reference)\nreference.\n| **Caution:** **This solution is no longer recommended:** Apps that use this API can only run in the Go 1.11 runtime and will need to upgrade to a [recommended solution](/appengine/migration-center/standard/services/migrating-services) before migrating to the Go 1.12+ runtime.\n\nEnabling Remote API\n-------------------\n\nFirst, add the `remote_api` `url` handler to your `app.yaml`. For example: \n\n - url: /_ah/remote_api\n script: _go_app\n\nThis maps the URL `/_ah/remote_api` to your Go app. Access to this URL is\nrestricted to administrators for the application by the Remote API handler.\n\nThen you import the `remote_api` package in one of your project's\npackages by adding the following line to any of your `.go` source files: \n\n import _ \"google.golang.org/appengine/remote_api\"\n\nDuring program initialization, the `remote_api` package registers a handler\nfor the `/_ah/remote_api` path. The underscore in the import\ndeclaration means \"import this package, but we won't use it directly.\" Without\nthe underscore, you would receive an \"imported but not used\" error message on\ncompilation.\n\nFinally, you [deploy the update to\nApp Engine](/appengine/docs/legacy/standard/go111/tools/uploadinganapp). For example: \n\n gcloud app deploy app.yaml\n\nUsing the Remote API in a Local Client\n--------------------------------------\n\nThe Remote API can be used to write local applications that use App Engine\nservices and access datastore. It is important to note that using the Remote\nAPI will incur quota usage on the application you are accessing.\n\nBefore beginning, make sure the Remote API is enabled in your App Engine\napplication. The local application can use the Remote API by creating a context\nwith `remote_api.NewRemoteContext`, and using that in place of the regular App\nEngine context in all API calls. \n\n // Copyright 2011 Google Inc. All rights reserved.\n // Use of this source code is governed by the Apache 2.0\n // license that can be found in the LICENSE file.\n\n package main\n\n import (\n \t\"log\"\n \t\"time\"\n\n \t\"golang.org/x/net/context\"\n \t\"golang.org/x/oauth2/google\"\n\n \t\"google.golang.org/appengine/datastore\"\n \t\"google.golang.org/appengine/remote_api\"\n )\n\n func main() {\n \tconst host = \"\u003cyour-app-id\u003e.appspot.com\"\n\n \tctx := context.Background()\n\n \thc, err := google.DefaultClient(ctx,\n \t\t\"https://www.googleapis.com/auth/appengine.apis\",\n \t\t\"https://www.googleapis.com/auth/userinfo.email\",\n \t\t\"https://www.googleapis.com/auth/cloud-platform\",\n \t)\n \tif err != nil {\n \t\tlog.Fatal(err)\n \t}\n\n \tremoteCtx, err := remote_api.https://cloud.google.com/appengine/docs/legacy/standard/go111/reference/latest/remote_api.html#google_golang_org_appengine_remote_api_NewRemoteContext(host, hc)\n \tif err != nil {\n \t\tlog.Fatal(err)\n \t}\n\n \tq := datastore.https://cloud.google.com/appengine/docs/legacy/standard/go111/reference/latest/datastore.html#google_golang_org_appengine_datastore_Query_NewQuery(\"Greeting\").\n \t\thttps://cloud.google.com/appengine/docs/legacy/standard/go111/reference/latest/datastore.html#google_golang_org_appengine_datastore_Query_Filter(\"Date \u003e=\", time.Now().AddDate(0, 0, -7))\n\n \tlog.Println(q.https://cloud.google.com/appengine/docs/legacy/standard/go111/reference/latest/datastore.html#google_golang_org_appengine_datastore_Query_Count(remoteCtx))\n }\n\nTo run this code, you need to fetch these packages: \n\n $ go get google.golang.org/appengine/...\n $ go get golang.org/x/oauth2/...\n\nYou need to provide the hostname of your server and a `http.Client` in the call\nto `NewRemoteContext`. The provided `http.Client` is responsible for passing\nthe required authentication information in each request.\n\nIn the sample above, the `DefaultClient` from the `golang.org/x/oauth2/google`\npackage provides OAuth 2 credentials via [Application Default Credentials](https://developers.google.com/identity/protocols/application-default-credentials).\n\nLimitations and best practices\n------------------------------\n\nThe remote_api module goes to great lengths to make sure that as far as\npossible, it behaves exactly like the native App Engine datastore. In some\ncases, this means doing things that are less efficient than they might\notherwise be. When using remote_api, here's a few things to keep in mind:\n\n### Every datastore request requires a round-trip\n\nBecause you're accessing the datastore over HTTP, there's a bit more overhead\nand latency than when you access it locally. In order to speed things up and\ndecrease load, try to limit the number of round-trips you do by batching\ngets and puts, and fetching batches of entities from queries. This is good\nadvice not just for remote_api, but for using the datastore in general,\nbecause a batch operation is only considered to be a single Datastore\noperation.\n\n### Requests to remote_api use quota\n\nBecause the remote_api operates over HTTP, every datastore call you make incurs\nquota usage for HTTP requests, bytes in and out, as well as the usual\ndatastore quota you would expect. Bear this in mind if you're using\nremote_api to do bulk updates.\n\n### 1 MB API limits apply\n\nAs when running natively, the 1MB limit on API requests and responses still\napplies. If your entities are particularly large, you may need to limit the\nnumber you fetch or put at a time to keep below this limit. This conflicts\nwith minimising round-trips, unfortunately, so the best advice is to use the\nlargest batches you can without going over the request or response size\nlimitations. For most entities, this is unlikely to be an issue, however.\n\n### Avoid iterating over queries\n\nWhen you iterate over queries, the SDK fetches entities from the datastore in\nbatches of 20, fetching a new batch whenever it uses up the existing ones.\nBecause each batch has to be fetched in a separate request by remote_api, it's\nunable to do this as efficiently. Instead, remote_api executes an entirely new\nquery for each batch, using the offset functionality to get further into the\nresults.\n\nIf you know how many entities you need, you can do the whole fetch in one\nrequest by asking for the number you need.\n\nIf you don't know how many entities you will want, you can use\n[cursors](/appengine/docs/legacy/standard/go111/datastore/query-cursors)\nto efficiently iterate over large result sets. This also\nallows you to avoid the 1000 entity limit imposed on normal datastore\nqueries.\n\n### Transactions are less efficient\n\nIn order to implement transactions via remote_api, it accumulates\ninformation on entities fetched inside the transaction, along with copies of\nentities that were put or deleted inside the transaction. When the\ntransaction is committed, it sends all of this information off to the App\nEngine server, where it has to fetch all the entities that were used in the\ntransaction again, verify that they have not been modified, then put and\ndelete all the changes the transaction made and commit it. If\nthere's a conflict, the server rolls back the transaction and notifies the\nclient end, which then has to repeat the process all over again.\n\nThis approach works, and exactly duplicates the functionality provided by\ntransactions on the local datastore, but is rather inefficient. By all means\nuse transactions where they are necessary, but try to limit the number and\ncomplexity of the transactions you execute in the interest of efficiency."]]