1. 개요
이 Codelab 시리즈 (사용자 주도형, 실무 가이드)는 Google App Engine (표준 환경) 개발자가 일련의 마이그레이션을 통해 자신의 앱을 현대화할 수 있도록 돕기 위한 것입니다. 가장 중요한 단계는 차세대 런타임이 더 유연하고 다양한 서비스 옵션을 제공하기 때문에 원래의 런타임 번들 서비스로부터 벗어나는 것입니다. 새로운 세대의 런타임으로 이동하면 Google Cloud 제품과 보다 쉽게 통합하고, 지원되는 다양한 서비스를 사용하고, 최신 출시 버전을 지원할 수 있습니다.
이 선택사항 튜토리얼에서는 개발자가 Datastore 서비스와 통신하는 클라이언트 라이브러리로 Cloud NDB에서 Cloud Datastore로 마이그레이션하는 방법을 보여줍니다. NDB를 선호하는 개발자는 Python 3와 호환되므로 NDB를 계속 사용할 수 있습니다. 따라서 이 마이그레이션은 선택사항입니다. 이 마이그레이션은 Cloud Datastore를 이미 사용 중인 다른 앱과 일관된 코드베이스 및 공유 라이브러리를 빌드하려는 사용자에게만 제공됩니다. 자세한 내용은 '배경' 섹션에 설명되어 있습니다.
학습 목표
- Cloud NDB 사용 (익숙하지 않은 경우)
- Cloud NDB에서 Cloud Datastore로 마이그레이션
- 추가로 앱을 Python 3로 마이그레이션
필요한 항목
- 활성 GCP 결제 계정이 있는 Google Cloud Platform 프로젝트
- 기본 Python 기술
- 기본 Linux 명령어에 대한 실무 지식
- App Engine 앱 개발 및 배포에 관한 기본 지식
- 작동되는 모듈 2 App Engine 2.x 또는 3.x 앱
설문조사
이 Codelab을 어떻게 사용할 예정인가요?
2. 배경
Cloud NDB는 오랜 기간 App Engine을 사용해 온 개발자에게 적합한 Datastore 솔루션이며 Python 3으로 전환하는 데 도움이 되지만 App Engine 개발자가 Datastore에 액세스할 수 있는 유일한 방법은 아닙니다. App Engine의 Datastore가 2013년에 자체 제품이 되었을 때 Google Cloud Datastore라는 새로운 클라이언트 라이브러리가 만들어져 모든 사용자가 Datastore를 사용할 수 있게 되었습니다.
Python 3 App Engine 및 App Engine 이외 개발자는 Cloud NDB가 아닌 Cloud Datastore를 사용해야 합니다. Python 2 App Engine 개발자는 ndb에서 Cloud NDB로 마이그레이션하고 거기에서 Python 3로 포팅하는 것이 권장되지만 Cloud Datastore로 추가 마이그레이션할 수도 있습니다. 이는 특히 앞에서 언급한 것과 같이 Cloud Datastore를 사용하는 코드가 이미 있고 모든 애플리케이션에서 공유 라이브러리를 만들려는 개발자에게 논리적인 결정입니다. 코드 재사용은 코드 일관성과 마찬가지로 권장사항이며, 둘 다 전반적인 유지관리 비용 절감에 기여합니다.
Cloud NDB에서 Cloud Datastore로 마이그레이션
- 개발자가 Datastore 액세스를 위한 단일 코드베이스에 집중할 수 있음
- Cloud NDB를 사용하는 코드와 Cloud Datastore를 사용하는 코드를 유지관리하지 않아도 됨
- 코드베이스의 일관성이 향상되고 코드 재사용성이 개선됩니다.
- 전반적인 유지관리 비용을 절감하는 데 도움이 되는 공통/공유 라이브러리 사용을 지원합니다.
이 마이그레이션에는 다음과 같은 기본 단계가 사용됩니다.
- 설정/사전 작업
- Cloud NDB를 Cloud Datastore 클라이언트 라이브러리로 대체
- 애플리케이션 업데이트
3. 설정/사전 작업
이 가이드의 주요 부분을 진행하기 전에 프로젝트를 설정하고 코드를 가져온 후 기본 앱을 배포하여 작동하는 코드로 시작할 수 있도록 준비합니다.
1. 프로젝트 설정
모듈 2 Codelab을 완료했으면 동일 프로젝트 (및 코드)를 다시 사용하는 것이 좋습니다. 또는 완전히 새로운 프로젝트를 만들거나 다른 기존 프로젝트를 다시 사용할 수도 있습니다. 프로젝트에 활성 결제 계정이 있고 App Engine(앱)이 사용 설정되어 있는지 확인합니다.
2. 기준 샘플 앱 가져오기
기본 요건 중 하나는 작동하는 모듈 2 샘플 앱을 준비하는 것입니다. 해당 가이드를 완료한 경우 해당 솔루션을 사용합니다. 지금 완료할 수도 있고 (위 링크), 건너뛰려는 경우 모듈 2 저장소를 복사할 수도 있습니다 (아래 링크).
무엇을 사용하든 모듈 2 코드에서부터 시작해야 합니다. 이 모듈 3 Codelab은 각 단계를 진행합니다. 완료되었을 때는 완료 지점의 코드와 비슷해야 합니다. 이 튜토리얼에는 Python 2와 3 버전이 있으므로 아래에서 올바른 코드 저장소를 가져오세요.
Python 2
Python 2 모듈 2 시작 파일(사용자 또는 Google의 파일)의 디렉터리는 다음과 같습니다.
$ ls
README.md appengine_config.py requirements.txt
app.yaml main.py templates
모듈 2 가이드를 완료했으면 Flask 및 해당 종속 항목이 포함된 lib 폴더가 있을 것입니다. lib 폴더가 없으면 다음 단계에서 이 기준 앱을 배포할 수 있도록 pip install -t lib -r requirements.txt 명령어로 만듭니다. Python 2 및 3가 모두 설치된 경우 Python 3와 충돌을 방지하기 위해 pip 대신 pip2를 사용하는 것이 좋습니다.
Python 3
Python 3 모듈 2 시작 파일 (사용자 또는 Google의 파일)의 디렉터리는 다음과 같습니다.
$ ls
README.md main.py templates
app.yaml requirements.txt
Python 3에는 lib도 appengine_config.py도 사용되지 않습니다.
3. 모듈 2 앱 (재)배포
이제 남은 사전 작업 실행 단계는 다음과 같습니다.
gcloud명령줄 도구 사용 방법을 다시 숙지합니다(필요한 경우).- 모듈 1 코드를 App Engine에 (재)배포합니다(필요한 경우).
이러한 단계를 성공적으로 실행하고, 작동하는지 확인한 후에는 이 가이드로 이동하여, 구성 파일 작업을 시작합니다.
4. Cloud NDB를 Cloud Datastore 클라이언트 라이브러리로 대체
구성 변경사항은 requirements.txt 파일의 사소한 패키지 스왑뿐입니다.
1. requirements.txt 업데이트
모듈 2를 완료하면 requirements.txt 파일이 다음과 같이 표시됩니다.
- 이전 (Python 2 및 3):
Flask==1.1.2
google-cloud-ndb==1.7.1
Cloud NDB 라이브러리 (google-cloud-ndb)를 최신 버전의 Cloud Datastore 라이브러리 (google-cloud-datastore)로 대체하여 requirements.txt를 업데이트합니다. Python 2와 호환되는 최종 버전의 Cloud Datastore는 1.15.3이므로 Flask 항목은 그대로 둡니다.
- AFTER (Python 2):
Flask==1.1.2
google-cloud-datastore==1.15.3
- AFTER (Python 3):
Flask==1.1.2
google-cloud-datastore==2.1.0
저장소는 이 튜토리얼보다 더 정기적으로 유지관리되므로 requirements.txt 파일에 최신 버전이 반영될 수 있습니다. 각 라이브러리에 대해 최신 버전이 권장되지만, 작동하지 않을 경우에는 이전 출시 버전으로 롤백할 수 있습니다. 위의 버전 번호는 이 Codelab이 마지막으로 업데이트되었을 때의 최신 버전입니다.
2. 기타 구성 파일
다른 구성 파일인 app.yaml 및 appengine_config.py는 이전 마이그레이션 단계에서 변경되지 않은 상태로 유지되어야 합니다.
app.yaml는 타사 번들 패키지grpcio및setuptools를 참조해야 합니다 (계속).appengine_config.py은lib의 서드 파티 리소스를pkg_resources및google.appengine.ext.vendor로 가리켜야 합니다 (여전히).
이제 애플리케이션 파일로 이동합니다.
5. 애플리케이션 파일 업데이트
template/index.html에는 변경사항이 없지만 main.py에는 몇 가지 업데이트가 있습니다.
1. 가져오기
가져오기 섹션의 시작 코드는 다음과 같습니다.
- 이전:
from flask import Flask, render_template, request
from google.cloud import ndb
google.cloud.ndb 가져오기를 Cloud Datastore용 google.cloud.datastore로 바꿉니다. Datastore 클라이언트 라이브러리는 항목에서 타임스탬프 필드의 자동 생성을 지원하지 않으므로 표준 라이브러리 datetime 모듈도 가져와서 수동으로 만듭니다. 규칙에 따라 표준 라이브러리 가져오기는 서드 파티 패키지 가져오기 위에 배치됩니다. 이 변경사항을 완료하면 다음과 같이 표시됩니다.
- 이후:
from datetime import datetime
from flask import Flask, render_template, request
from google.cloud import datastore
2. 초기화 및 데이터 모델
Flask를 초기화한 후 NDB 데이터 모델 클래스와 필드를 만드는 모듈 2 샘플 앱은 다음과 같습니다.
- 이전:
app = Flask(__name__)
ds_client = ndb.Client()
class Visit(ndb.Model):
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
Cloud Datastore 라이브러리에는 이러한 클래스가 없으므로 Visit 클래스 선언을 삭제합니다. Datastore와 통신하려면 클라이언트가 필요하므로 ndb.Client()을 datastore.Client()로 변경합니다. Datastore 라이브러리는 더 '유연'하므로 NDB처럼 구조를 '사전 선언'하지 않고도 엔티티를 만들 수 있습니다. 이 업데이트 후 main.py의 이 부분은 다음과 같이 표시됩니다.
- 이후:
app = Flask(__name__)
ds_client = datastore.Client()
3. Datastore 액세스
Cloud Datastore로 이전하려면 Datastore 항목 (사용자 수준)을 만들고 저장하고 쿼리하는 방식을 변경해야 합니다. 애플리케이션의 경우 이 마이그레이션의 난이도는 Datastore 코드의 복잡도에 따라 달라집니다. 샘플 앱에서는 업데이트를 최대한 간단하게 만들려고 했습니다. 시작 코드는 다음과 같습니다.
- 이전:
def store_visit(remote_addr, user_agent):
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
def fetch_visits(limit):
with ds_client.context():
return (v.to_dict() for v in Visit.query().order(
-Visit.timestamp).fetch_page(limit)[0])
Cloud Datastore를 사용하여 항목에서 그룹화된 객체를 '키'로 식별하는 일반 항목을 만듭니다. 키-값 쌍의 JSON 객체 (Python dict)로 데이터 레코드를 만든 다음 예상되는 put()를 사용하여 Datastore에 씁니다. Datastore를 사용하면 쿼리가 비슷하지만 더 간단합니다. 여기에서 해당 Datastore 코드가 어떻게 다른지 확인할 수 있습니다.
- 이후:
def store_visit(remote_addr, user_agent):
entity = datastore.Entity(key=ds_client.key('Visit'))
entity.update({
'timestamp': datetime.now(),
'visitor': '{}: {}'.format(remote_addr, user_agent),
})
ds_client.put(entity)
def fetch_visits(limit):
query = ds_client.query(kind='Visit')
query.order = ['-timestamp']
return query.fetch(limit=limit)
위와 같이 store_visit() 및 fetch_visits()의 함수 본문을 업데이트하여 서명을 이전 버전과 동일하게 유지합니다. 기본 핸들러 root()에는 변경사항이 없습니다. 이러한 변경사항을 완료하면 앱이 이제 Cloud Datastore를 사용할 수 있도록 준비되었으며 테스트할 준비가 되었습니다.
6. 요약/삭제
애플리케이션 배포
gcloud app deploy로 앱을 다시 배포하고 앱이 작동하는지 확인합니다. 이제 코드는 모듈 3 저장소 폴더에 있는 것과 일치해야 합니다.
앞의 Codelab을 수행하지 않고 이 시리즈를 바로 시작한 경우에는 앱 자체가 변경되지 않습니다. 모든 방문을 기본 웹페이지(/)에 등록하고 사이트를 충분히 방문한 후 다음과 같이 표시됩니다.

이 모듈 3 Codelab 완료를 축하합니다. 이제 Cloud NDB 및 Cloud Datastore 클라이언트 라이브러리를 모두 사용하여 Datastore에 액세스할 수 있다는 것을 알게 되었습니다. 후자로 이전하면 이제 공유 라이브러리, 공통 코드, 코드 재사용의 이점을 활용하여 일관성을 유지하고 유지관리 비용을 절감할 수 있습니다.
선택사항: 삭제
다음 마이그레이션 Codelab으로 이동할 준비가 될 때까지 비용이 결제되지 않도록 하려면 삭제를 수행해야 합니다. 기존 개발자라면 App Engine 가격 책정 정보를 이미 잘 알고 계실 것입니다.
선택사항: 앱 사용 중지
다음 가이드로 이동할 준비가 되지 않았으면 비용 발생을 방지하기 위해 앱을 사용 중지하세요. 다음 Codelab으로 이동할 준비가 되었으면 이를 다시 사용 설정하면 됩니다. 앱이 사용 중지되면 비용을 일으키는 트래픽이 수행되지 않습니다. 하지만 무료 할당량을 초과할 경우 해당 Datastore 사용량에 대한 비용이 결제될 수 있습니다. 따라서 제한에 걸리지 않도록 충분히 삭제해야 합니다.
반면에 마이그레이션을 계속하지 않고 모든 것을 완전히 삭제하려면 프로젝트를 종료하면 됩니다.
다음 단계
여기에서 다음 이전 모듈을 살펴보세요.
- 모듈 3 보너스: 보너스 섹션으로 계속하여 Python 3 및 차세대 App Engine 런타임으로 포팅하는 방법을 알아봅니다.
- 모듈 7: App Engine push 태스크 큐([push] 태스크 큐를 사용하는 경우 필요)
- App Engine
taskqueuepush 태스크를 모듈 1 앱에 추가합니다. - 모듈 8에서 Cloud Tasks로 마이그레이션하기 위해 사용자를 준비합니다.
- App Engine
- 모듈 4: Docker를 사용하여 Cloud Run으로 마이그레이션합니다.
- Docker를 사용하여 Cloud Run에서 실행하기 위해 앱을 컨테이너화합니다.
- Python 2로 계속 유지합니다.
- 모듈 5: Cloud 빌드팩을 사용하여 Cloud Run으로 마이그레이션
- Cloud Buildpacks를 사용하여 Cloud Run에서 실행할 앱 컨테이너화
- Docker, 컨테이너,
Dockerfile에 대해 알 필요가 없습니다. - 앱이 이미 Python 3로 마이그레이션되어 있어야 합니다.
- 모듈 6: Cloud Firestore로 마이그레이션
- Cloud Firestore로 마이그레이션하여 Firebase 기능에 액세스
- Cloud Firestore는 Python 2를 지원하지만 이 Codelab은 Python 3에서만 사용할 수 있습니다.
7. 보너스: Python 3으로 마이그레이션
최신 App Engine 런타임 및 기능에 액세스하기 위해서는 Python 3로 마이그레이션하는 것이 좋습니다. 샘플 앱에서 Datastore는 사용된 유일한 기본 제공 서비스였습니다. ndb에서 Cloud NDB로 마이그레이션했기 때문에 이제는 App Engine의 Python 3 런타임으로 포팅할 수 있습니다.
개요
Python 3로 포팅이 Google Cloud 가이드의 범위를 벗어나지만, 이 Codelab 부분을 통해 개발자는 Python 3 App Engine 런타임의 차이점을 이해할 수 있습니다. 차세대 런타임의 뛰어난 기능 중 하나는 서드 파티 패키지에 대한 액세스가 간소화되었다는 점입니다. app.yaml에서 기본 제공 패키지를 지정할 필요도 없고 비기본 제공 라이브러리를 복사하거나 업로드할 필요도 없습니다. 이것들은 requirements.txt에 나열된 대로 암시적으로 설치됩니다.
샘플이 매우 간단하고 그리고 Cloud Datastore가 Python 2-3과 호환되기 때문에 애플리케이션 코드를 3.x로 명시적으로 포팅할 필요가 없습니다. 앱은 수정하지 않은 상태로 2.x 및 3.x에서 실행됩니다. 즉, 이 경우 구성만 변경하면 됩니다.
- Python 3를 참조하고 번들로 제공되는 서드 파티 라이브러리 참조를 삭제하도록
app.yaml을 단순화합니다. - 더 이상 필수가 아니므로
appengine_config.py및lib폴더를 삭제합니다.
main.py 및 templates/index.html 애플리케이션 파일은 변경되지 않은 상태로 유지됩니다.
requirements.txt 업데이트
Python 2를 지원하는 Cloud Datastore의 최종 버전은 1.15.3입니다. Python 3의 최신 버전으로 requirements.txt를 업데이트합니다 (현재는 더 최신 버전일 수 있음). 이 튜토리얼이 작성되었을 때 최신 버전은 2.1.0이므로 해당 줄을 다음과 같이 수정합니다 (또는 최신 버전이 무엇이든).
google-cloud-datastore==2.1.0
app.yaml 단순화
이전:
이 샘플 앱의 유일한 실제 변경은 app.yaml을 상당히 단축시키는 것입니다. 다시 말하지만 모듈 3의 결론에서 app.yaml에 포함되는 내용은 다음과 같습니다.
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: grpcio
version: 1.0.0
- name: setuptools
version: 36.6.0
이후:
Python 3에서 threadsafe, api_version, libraries 지시문은 모두 지원 중단되었으며 모든 앱이 스레드에 안전한 것으로 가정됩니다. api_version은 Python 3에서 사용되지 않습니다. App Engine 서비스에 사전 설치된 기본 제공 타사 패키지가 더 이상 없으므로 libraries도 지원 중단됩니다. 이러한 변경사항에 대한 자세한 내용은 app.yaml 변경사항에 대한 문서를 참조하세요. 따라서 app.yaml의 3개 항목을 모두 삭제하고 지원되는 Python 3 버전(아래 참조)으로 업데이트해야 합니다.
선택사항: handlers 지시문 사용
또한 App Engine 애플리케이션에서 트래픽을 전달하는 handlers 지시문도 지원 중단되었습니다. 차세대 런타임에서는 웹 프레임워크가 앱 라우팅을 관리하므로, 모든 '핸들러 스크립트'를 'auto'로 변경해야 합니다. 위 변경사항을 조합하면 다음 app.yaml에 도달합니다.
runtime: python38
handlers:
- url: /.*
script: auto
app.yaml 참조 페이지에서 script: auto에 대해 자세히 알아보세요.
handlers 지시문 삭제
handlers가 지원 중단되었기 때문에 전체 섹션을 삭제하고 한 줄 app.yaml만 남겨둘 수 있습니다.
runtime: python38
기본적으로 이렇게 하면 모든 애플리케이션에 사용할 수 있는 Gunicorn WSGI 웹 서버가 시작됩니다. gunicorn에 익숙할 경우 이것은 기본적으로 베어본 app.yaml로 시작될 때 실행되는 명령어입니다.
gunicorn main:app --workers 2 -c /config/gunicorn.py
선택사항: entrypoint 지시문 사용
하지만 애플리케이션에 특정 시작 명령어가 필요하면 entrypoint 지시문으로 지정할 수 있으며, 그 결과 app.yaml이 다음과 같이 표시됩니다.
runtime: python38
entrypoint: python main.py
이 예시는 특히 gunicorn 대신 Flask 개발 서버를 사용하도록 요청합니다. 이 작은 섹션을 main.py 하단에 추가하여 포트 8080으로 0.0.0.0 인터페이스에서 시작하도록 개발 서버를 시작하는 코드도 앱에 추가해야 합니다.
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080, debug=True)
app.yaml 참조 페이지에서 entrypoint에 대해 자세히 알아보세요. 더 많은 예시와 권장사항은 App Engine 표준 환경 시작 문서 및 App Engine 가변형 환경 시작 문서에서 찾아볼 수 있습니다.
appengine_config.py 및 lib 삭제
appengine_config.py 파일 및 lib 폴더를 삭제합니다. Python 3로 마이그레이션하는 경우 App Engine이 requirements.txt에 나열된 패키지를 획득하고 설치합니다.
직접 복사했거나 App Engine 서버에서 이미 제공되는 항목(기본 제공)을 사용하는지 여부에 관계없이 appengine_config.py 구성 파일은 타사 라이브러리/패키지를 인식하는 데 사용됩니다. Python 3로 이동할 때 중요한 변경사항에 대한 요약은 다음과 같습니다.
- 복사된 타사 라이브러리를 번들로 묶지 않음(
requirements.txt에 나열됨) lib폴더로pip install을 수행하지 않음,lib폴더 기간 없음app.yaml에 기본 제공 타사 라이브러리 목록 없음- 타사 라이브러리에 앱 참조 필요 없음, 따라서
appengine_config.py파일 없음
requirements.txt에서 모든 필수 타사 라이브러리만 나열하면 됩니다.
애플리케이션 배포
앱이 작동하는지 확인하기 위해 앱을 다시 배포합니다. 또한 솔루션이 모듈 3 샘플 Python 3 코드에 얼마나 가까운지도 확인할 수 있습니다. Python 2와의 차이를 시각화하려면 코드를 해당 Python 2 버전과 비교합니다.
모듈 3의 보너스 단계를 완료하신 것을 축하합니다! Python 3 런타임을 위한 구성 파일 준비 문서를 참조하세요. 마지막으로 위의 요약을 검토하여 다음 단계와 정리 작업을 확인합니다.
개발자의 애플리케이션 준비
개발자의 애플리케이션을 마이그레이션할 시간이 되었으면 main.py 및 기타 애플리케이션 파일을 3.x로 포팅해야 합니다. 따라서 권장사항은 2.x 애플리케이션을 가능한 한 '이후 버전과 호환'되도록 만들기 위해 최선을 다하는 것입니다.
이를 위해 정말 많은 온라인 리소스가 존재하지만, 이들 중 몇 가지 중요한 팁은 다음과 같습니다.
- 모든 애플리케이션 종속 항목이 3.x와 완전히 호환되도록 합니다.
- 애플리케이션이 최소 2.6(2.7 추천) 이상으로 실행되도록 합니다.
- 애플리케이션이 전체 테스트 모음을 통과하도록 합니다(최소 80% 지원).
six, Future 또는 Modernize와 같은 호환성 라이브러리를 사용합니다.- 이전 버전과 호환되는 주요 2.x와 3.x 사이의 차이점을 확인합니다.
- 모든 I/O는 유니코드 및 바이트 문자열 간의 비호환성으로 이어질 수 있습니다.
이 샘플 앱은 이 모든 것을 염두에 두고 설계되었습니다. 따라서 차세대 플랫폼을 사용하기 위해 변경해야 하는 것들을 집중적으로 보여줄 수 있도록 앱이 2.x 및 3.x에서 바로 실행됩니다.
8. 추가 리소스
App Engine 마이그레이션 모듈 Codelab 문제/의견
이 Codelab에 문제가 발견된 경우 문제를 기록하기 전에 먼저 비슷한 기록이 있는지 검색해보세요. 검색 및 새 문제 만들기 링크:
마이그레이션 리소스
모듈 2 (시작) 및 모듈 3 (완료)의 저장소 폴더 링크는 아래 표에서 찾을 수 있습니다. 또한 클론 또는 ZIP 파일로 다운로드할 수 있는 모든 App Engine 마이그레이션 저장소에서 액세스할 수도 있습니다.
Codelab | Python 2 | Python 3 |
모듈 3 |
App Engine 리소스
다음은 이 특정 마이그레이션과 관련된 추가적인 리소스입니다.
- Python Cloud NDB 및 Cloud Datastore 참조
- Python 3 및 GAE 차세대 런타임으로 마이그레이션
- 일반