1. 개요
서버리스 마이그레이션 스테이션 Codelab 시리즈 (사용자 주도형, 실무 가이드) 및 관련 동영상은 Google Cloud 서버리스 개발자가 주로 기존 서비스에서 벗어나는 하나 이상의 마이그레이션을 통해 애플리케이션을 현대화할 수 있도록 돕기 위한 것입니다. 이렇게 하면 앱의 이식성이 높아지고 더 많은 옵션과 유연성을 제공하여 다양한 Cloud 제품과 통합하고 액세스할 수 있으며 최신 언어 출시로 더 쉽게 업그레이드할 수 있습니다. 이 시리즈는 처음에는 주로 App Engine (표준 환경) 개발자와 같은 초기 Cloud 사용자를 대상으로 하지만, Cloud Functions, Cloud Run과 같은 다른 서버리스 플랫폼이나 해당하는 경우 다른 플랫폼도 포함할 수 있을 만큼 광범위합니다.
이 Codelab의 목적은 Python 2 App Engine 개발자에게 App Engine Memcache에서 Cloud Memorystore (Redis용)로 마이그레이션하는 방법을 보여주는 것입니다. App Engine ndb에서 Cloud NDB로의 암시적 마이그레이션도 있지만 이는 주로 모듈 2 Codelab에서 다룹니다. 단계별 자세한 내용은 여기를 참고하세요.
다음 실습에서는
- Cloud Memorystore 인스턴스 설정 (Cloud 콘솔 또는
gcloud도구에서) - Cloud 서버리스 VPC 액세스 커넥터 설정 (Cloud Console 또는
gcloud도구에서) - App Engine Memcache에서 Cloud Memorystore로 마이그레이션
- 샘플 앱에서 Cloud Memorystore로 캐싱 구현
- App Engine
ndb에서 Cloud NDB로 마이그레이션
필요한 항목
- 활성 결제 계정이 있는 Google Cloud 프로젝트 (무료 Codelab이 아님)
- 기본 Python 기술
- 일반적인 Linux 명령어에 대한 실무 지식
- App Engine 앱 개발 및 배포에 대한 기본 지식
- 작동하는 모듈 12 App Engine 앱 (모듈 12 Codelab을 완료하거나 [권장] 저장소에서 모듈 12 앱을 복사)
설문조사
본 가이드를 어떻게 사용하실 계획인가요?
귀하의 Python 사용 경험이 어떤지 평가해 주세요.
귀하의 Google Cloud 서비스 사용 경험을 평가해 주세요.
2. 배경
이 Codelab에서는 샘플 앱을 App Engine Memcache (및 NDB)에서 Cloud Memorystore (및 Cloud NDB)로 마이그레이션하는 방법을 보여줍니다. 이 프로세스에는 App Engine 번들 서비스의 종속 항목을 대체하여 앱의 이식성을 높이는 작업이 포함됩니다. App Engine을 계속 사용하거나 앞서 설명한 대안으로 이전할 수 있습니다.
이 마이그레이션은 이 시리즈의 다른 마이그레이션에 비해 더 많은 노력이 필요합니다. App Engine Memcache에 권장되는 대안은 완전 관리형 클라우드 기반 캐싱 서비스인 Cloud Memorystore입니다. Memorystore는 널리 사용되는 오픈소스 캐싱 엔진인 Redis 및 Memcached를 지원합니다. 이 이전 모듈은 Redis용 Cloud Memorystore를 사용합니다. 자세한 내용은 Memorystore 및 Redis 개요를 참고하세요.
Memorystore에는 실행 중인 서버가 필요하므로 Cloud VPC도 필요합니다. 특히 App Engine 앱이 비공개 IP 주소를 통해 Memorystore 인스턴스에 연결할 수 있도록 서버리스 VPC 액세스 커넥터를 만들어야 합니다. 이 실습을 완료하면 이전과 동일하게 작동하지만 Cloud Memorystore가 App Engine의 Memcache 서비스를 대체하는 캐싱 서비스가 되도록 앱이 업데이트됩니다.
이 튜토리얼은 Python 2의 모듈 12 샘플 앱으로 시작한 후 Python 3으로의 추가적인 선택적 마이너 업그레이드로 이어집니다. Python 3 App Engine SDK를 통해 Python 3에서 App Engine 번들 서비스에 액세스하는 방법을 이미 알고 있다면 모듈 12 샘플 앱의 Python 3 버전으로 시작해도 됩니다. 이렇게 하면 Memorystore가 App Engine 번들 서비스가 아니므로 SDK 사용이 삭제됩니다. Python 3 App Engine SDK 사용 방법은 이 튜토리얼의 범위를 벗어납니다.
이 튜토리얼에는 다음 주요 단계가 포함되어 있습니다.
- 설정/사전 작업
- 캐싱 서비스 설정
- 구성 파일 업데이트
- 기본 애플리케이션 업데이트
3. 설정/사전 작업
Cloud 프로젝트 준비
모듈 12 Codelab을 완료하는 데 사용한 것과 동일한 프로젝트를 재사용하는 것이 좋습니다. 또는 완전히 새로운 프로젝트를 만들거나 다른 기존 프로젝트를 다시 사용할 수도 있습니다. 이 시리즈의 모든 Codelab에는 '시작' (시작할 기준 코드)과 '완료' (마이그레이션된 앱)가 있습니다. 문제가 있는 경우 솔루션을 Google의 솔루션과 비교할 수 있도록 FINISH 코드가 제공됩니다. 문제가 발생하면 언제든지 롤백하여 처음부터 다시 시작할 수 있습니다. 이러한 체크포인트는 마이그레이션 수행 방법을 성공적으로 학습할 수 있도록 설계되었습니다.
어떤 Cloud 프로젝트를 사용하든 활성 결제 계정이 있어야 합니다. 또한 App Engine이 사용 설정되어 있어야 합니다. 이 튜토리얼을 진행할 때의 일반적인 비용 영향을 검토하고 이해해야 합니다. 하지만 이 Codelab은 이 시리즈의 다른 Codelab과 달리 무료 등급이 없는 클라우드 리소스를 사용하므로 연습을 완료하는 데 비용이 발생합니다. 비용 절감을 위한 권장사항과 함께 더 구체적인 비용 정보가 제공되며, 청구 요금을 최소화하기 위해 리소스를 해제하는 방법에 관한 안내가 마지막에 포함됩니다.
기준 샘플 앱 가져오기
이 Codelab에서는 기준 모듈 12 코드에서 시작하여 단계별로 이전하는 방법을 안내합니다. 완료되면 FINISH 폴더 중 하나의 코드와 매우 유사한 작동하는 모듈 13 앱이 표시됩니다. 다음은 해당 리소스입니다.
- 시작: 모듈 12 Python 2 (
mod12) 또는 Python 3 (mod12b) 앱 - 완료: 모듈 13 Python 2 (
mod13a) 또는 Python 3 (mod13b) 앱 - 전체 마이그레이션 저장소 (클론 또는 ZIP 다운로드)
시작 폴더에는 다음 파일이 포함되어야 합니다.
$ ls README.md app.yaml main.py requirements.txt templates
Python 2 버전에서 시작하는 경우 appengine_config.py 파일도 있으며 모듈 12 Codelab을 완료한 경우 lib 폴더도 있을 수 있습니다.
모듈 12 앱 (재)배포
남은 사전 작업 단계는 다음과 같습니다.
gcloud명령줄 도구 사용 방법을 다시 숙지합니다 (필요한 경우).- 모듈 12 코드를 App Engine에 (재)배포합니다 (필요한 경우).
Python 2 사용자는 다음 명령어를 사용하여 lib 폴더를 삭제하고 다시 설치해야 합니다.
rm -rf ./lib; pip install -t lib -r requirements.txt
이제 모든 사용자 (Python 2 및 3 사용자)가 다음 명령어를 사용하여 코드를 App Engine에 업로드해야 합니다.
gcloud app deploy
배포가 완료되면 앱이 모듈 12의 앱과 동일하게 표시되고 작동하는지 확인합니다. 모듈 12의 앱은 방문을 추적하고 동일한 사용자에 대해 한 시간 동안 캐시하는 웹 앱입니다.

최근 방문이 캐시되므로 페이지 새로고침이 비교적 빠르게 로드됩니다.
4. 캐싱 서비스 설정
Cloud Memorystore는 서버리스가 아닙니다. 인스턴스가 필요합니다. 이 경우 실행 중인 Redis입니다. Memcache와 달리 Memorystore는 독립형 Cloud 제품이며 무료 등급이 없으므로 계속하기 전에 Redis용 Memorystore 가격 정보를 확인하세요. 이 연습의 비용을 최소화하려면 Basic 서비스 등급과 1GB 용량 등 운영에 필요한 최소한의 리소스를 사용하는 것이 좋습니다.
Memorystore 인스턴스가 App Engine 앱 (인스턴스)과 다른 네트워크에 있으므로 App Engine이 Memorystore 리소스에 액세스할 수 있도록 서버리스 VPC 액세스 커넥터를 만들어야 합니다. VPC 비용을 최소화하려면 인스턴스 유형 (f1-micro)과 요청할 인스턴스 수 (최소 2개, 최대 3개 권장)를 선택하세요. VPC 가격 정보 페이지도 확인하세요.
필요한 각 리소스를 만드는 과정을 안내하면서 비용 절감에 관한 권장사항을 반복합니다. 또한 Cloud 콘솔에서 Memorystore 및 VPC 리소스를 만들면 오른쪽 상단에 각 제품의 가격 계산기가 표시되어 월별 비용을 추정할 수 있습니다 (아래 그림 참고). 옵션을 변경하면 이러한 값이 자동으로 조정됩니다. 다음과 같이 표시됩니다.

두 리소스 모두 필요하며 어떤 리소스를 먼저 만드는지는 중요하지 않습니다. Memorystore 인스턴스를 먼저 만들면 App Engine 앱이 VPC 커넥터 없이 인스턴스에 도달할 수 없습니다. 마찬가지로 VPC 커넥터를 먼저 만들면 App Engine 앱이 통신할 VPC 네트워크에 아무것도 없습니다. 이 튜토리얼에서는 먼저 Memorystore 인스턴스를 만든 다음 VPC 커넥터를 만듭니다.
두 리소스가 모두 온라인 상태가 되면 앱이 캐시에 액세스할 수 있도록 관련 정보를 app.yaml에 추가합니다. 공식 문서의 Python 2 또는 Python 3 가이드를 참조할 수도 있습니다. Cloud NDB 마이그레이션 페이지 ( Python 2 또는 Python 3)의 데이터 캐싱 가이드도 참고할 만합니다.
Cloud Memorystore 인스턴스 만들기
Cloud Memorystore에는 무료 등급이 없으므로 Codelab을 완료하는 데 필요한 최소한의 리소스를 할당하는 것이 좋습니다. 다음 설정을 사용하여 비용을 최소화할 수 있습니다.
- 가장 낮은 서비스 등급인 Basic을 선택합니다 (콘솔 기본값: 'Standard',
gcloud기본값: 'Basic'). - 최소 스토리지 용량인 1GB를 선택합니다 (콘솔 기본값: 16GB,
gcloud기본값: 1GB). - 일반적으로 모든 소프트웨어의 최신 버전은 가장 많은 리소스가 필요하지만 가장 오래된 버전을 선택하는 것도 권장되지 않습니다. 현재 두 번째 최신 버전은 Redis 버전 5.0입니다 (콘솔 기본값: 6.x).
이러한 설정을 염두에 두고 다음 섹션에서는 Cloud 콘솔에서 인스턴스를 만드는 방법을 안내합니다. 명령줄에서 수행하려면 건너뛰세요.
Cloud Console 사용
Cloud Console에서 Cloud Memorystore 페이지로 이동합니다 (결제 정보를 묻는 메시지가 표시될 수 있음). 아직 Memorystore를 사용 설정하지 않은 경우 사용 설정하라는 메시지가 표시됩니다.

이 기능을 사용 설정하면 (결제와 함께) Memorystore 대시보드로 이동합니다. 여기에서 프로젝트에 생성된 모든 인스턴스를 확인할 수 있습니다. 아래에 표시된 프로젝트에는 행이 없으므로 '표시할 행이 없습니다'라는 메시지가 표시됩니다. Memorystore 인스턴스를 만들려면 상단의 인스턴스 만들기를 클릭합니다.

이 페이지에는 원하는 설정으로 작성하여 Memorystore 인스턴스를 만드는 양식이 있습니다.

이 튜토리얼과 샘플 앱의 비용을 절감하려면 앞에서 설명한 권장사항을 따르세요. 선택을 완료한 후 만들기를 클릭합니다. 생성 프로세스는 몇 분 정도 걸립니다. 완료되면 인스턴스의 IP 주소와 포트 번호를 복사하여 app.yaml에 추가합니다.
명령줄에서
Cloud Console에서 Memorystore 인스턴스를 만드는 것이 시각적으로 유용하지만 명령줄을 선호하는 사용자도 있습니다. 계속하기 전에 gcloud가 설치되고 초기화되었는지 확인하세요.
Cloud Console과 마찬가지로 Redis용 Cloud Memorystore가 사용 설정되어 있어야 합니다. 다음 예와 같이 gcloud services enable redis.googleapis.com 명령어를 실행하고 완료될 때까지 기다립니다.
$ gcloud services enable redis.googleapis.com Operation "operations/acat.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.
서비스가 이미 사용 설정된 경우 명령어를 다시 실행해도 부작용이 없습니다. 서비스가 사용 설정되었으므로 Memorystore 인스턴스를 만들어 보겠습니다. 명령어는 다음과 같습니다.
gcloud redis instances create NAME --redis-version VERSION \
--region REGION --project PROJECT_ID
Memorystore 인스턴스의 이름을 선택합니다. 이 실습에서는 'demo-ms'를 이름으로 사용하고 프로젝트 ID는 'my-project'입니다. 이 샘플 앱의 리전은 us-central1 (us-central과 동일)이지만, 지연 시간이 우려되는 경우 더 가까운 리전을 사용해도 됩니다. App Engine 앱과 동일한 리전을 선택해야 합니다. 원하는 Redis 버전을 선택할 수 있지만 앞서 권장한 버전 5를 사용합니다. 이러한 설정을 고려할 때 실행해야 하는 명령어는 다음과 같습니다 (관련 출력 포함).
$ gcloud redis instances create demo-ms --region us-central1 \
--redis-version redis_5_0 --project my-project
Create request issued for: [demo-ms]
Waiting for operation [projects/my-project/locations/us-central1/operations/operation-xxxx] to complete...done.
Created instance [demo-ms].
Cloud 콘솔 기본값과 달리 gcloud은 최소 리소스로 기본 설정됩니다. 그 결과 해당 명령어에는 서비스 등급과 스토리지 용량이 모두 필요하지 않았습니다. Memorystore 인스턴스를 만드는 데 몇 분 정도 걸리며, 완료되면 인스턴스의 IP 주소와 포트 번호를 기록해 둡니다. 곧 app.yaml에 추가될 예정입니다.
인스턴스 생성 확인
Cloud 콘솔 또는 명령줄에서
Cloud Console 또는 명령줄에서 인스턴스를 만든 경우 gcloud redis instances list --region REGION 명령어를 사용하여 인스턴스를 사용할 수 있는지 확인할 수 있습니다.
다음은 us-central1 리전의 인스턴스를 확인하는 명령어와 방금 만든 인스턴스를 보여주는 예상 출력입니다.
$ gcloud redis instances list --region us-central1 INSTANCE_NAME VERSION REGION TIER SIZE_GB HOST PORT NETWORK RESERVED_IP STATUS CREATE_TIME demo-ms REDIS_5_0 us-central1 BASIC 1 10.aa.bb.cc 6379 default 10.aa.bb.dd/29 READY 2022-01-28T09:24:45
인스턴스 정보를 묻거나 앱을 구성하라는 메시지가 표시되면 HOST 및 PORT을 사용해야 합니다 (RESERVED_IP 아님). 이제 Cloud Console의 Cloud Memorystore 대시보드에 해당 인스턴스가 표시됩니다.

Compute Engine 가상 머신에서
Compute Engine 가상 머신 (VM)이 있는 경우 VM에서 Memorystore 인스턴스로 직접 명령어를 전송하여 작동하는지 확인할 수도 있습니다. VM 사용에는 이미 사용 중인 리소스와 별도로 관련 비용이 발생할 수 있습니다.
서버리스 VPC 액세스 커넥터 만들기
Cloud Memorystore와 마찬가지로 Cloud Console 또는 명령줄에서 서버리스 Cloud VPC 커넥터를 만들 수 있습니다. 마찬가지로 Cloud VPC에는 무료 등급이 없으므로 비용을 최소로 유지하기 위해 코드랩을 완료하는 데 필요한 최소한의 리소스를 할당하는 것이 좋습니다. 다음 설정으로 이를 달성할 수 있습니다.
- 최소 최대 인스턴스 수인 3을 선택합니다 (콘솔 및
gcloud기본값: 10). - 가장 저렴한 머신 유형인
f1-micro을 선택합니다 (콘솔 기본값:e2-micro,gcloud기본값 없음).
다음 섹션에서는 위의 Cloud VPC 설정을 사용하여 Cloud 콘솔에서 커넥터를 만드는 방법을 안내합니다. 명령줄에서 실행하려면 다음 섹션으로 건너뜁니다.
Cloud 콘솔에서
Cloud Console에서 Cloud 네트워킹 '서버리스 VPC 액세스' 페이지로 이동합니다 (결제 정보를 입력하라는 메시지가 표시될 수 있음). 아직 API를 사용 설정하지 않은 경우 사용 설정하라는 메시지가 표시됩니다.

API를 사용 설정하면 (결제와 함께) 생성된 모든 VPC 커넥터가 표시된 대시보드로 이동합니다. 아래 스크린샷에 사용된 프로젝트에는 행이 없으므로 '표시할 행이 없습니다'라고 표시됩니다. 콘솔에서 상단의 커넥터 만들기를 클릭합니다.

원하는 설정으로 양식을 작성합니다.

자체 애플리케이션에 적합한 설정을 선택합니다. 이 튜토리얼과 최소한의 요구사항이 있는 샘플 앱의 경우 비용을 최소화하는 것이 합리적이므로 앞에서 설명한 권장사항을 따르세요. 선택을 완료한 후 만들기를 클릭합니다. VPC 커넥터를 요청하는 데 몇 분 정도 걸립니다.
명령줄에서
VPC 커넥터를 만들기 전에 먼저 Serverless VPC Access API를 사용 설정하세요. 다음 명령어를 실행하면 다음과 비슷한 출력이 표시됩니다.
$ gcloud services enable vpcaccess.googleapis.com Operation "operations/acf.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.
API가 사용 설정되면 다음과 같은 명령어로 VPC 커넥터가 생성됩니다.
gcloud compute networks vpc-access connectors create CONNECTOR_NAME \
--range 10.8.0.0/28 --region REGION --project PROJECT_ID
커넥터의 이름과 사용되지 않은 /28 CIDR 블록 시작 IP 주소를 선택합니다. 이 튜토리얼에서는 다음과 같은 가정을 합니다.
- 프로젝트 ID:
my-project - VPC 커넥터 이름:
demo-vpc - 최소 인스턴스: 2 (기본값), 최대 인스턴스: 3
- 인스턴스 유형:
f1-micro - 리전:
us-central1 - IPv4 CIDR 블록:
10.8.0.0/28(클라우드 콘솔에서 권장)
위의 가정을 염두에 두고 다음 명령어를 실행하면 아래와 비슷한 출력이 표시됩니다.
$ gcloud compute networks vpc-access connectors create demo-vpc \
--max-instances 3 --range 10.8.0.0/28 --machine-type f1-micro \
--region us-central1 --project my-project
Create request issued for: [demo-vpc]
Waiting for operation [projects/my-project/locations/us-central1/operations/xxx] to complete...done.
Created connector [demo-vpc].
위 명령어에서는 최소 인스턴스 수 2, default라는 네트워크와 같은 기본값 지정이 생략됩니다. VPC 커넥터를 만드는 데 몇 분 정도 걸립니다.
커넥터 생성 확인
프로세스가 완료되면 리전이 us-central1이라고 가정하고 다음 gcloud 명령어를 실행하여 생성되었으며 사용할 준비가 되었는지 확인합니다.
$ gcloud compute networks vpc-access connectors list --region us-central1 CONNECTOR_ID REGION NETWORK IP_CIDR_RANGE SUBNET SUBNET_PROJECT MIN_THROUGHPUT MAX_THROUGHPUT STATE demo-vpc us-central1 default 10.8.0.0/28 200 300 READY
마찬가지로 대시보드에 방금 만든 커넥터가 표시됩니다.

Cloud 프로젝트 ID, VPC 커넥터 이름, 리전을 기록해 둡니다.
명령줄을 사용하든 콘솔을 사용하든 필요한 추가 Cloud 리소스를 만들었으므로 이제 이러한 리소스의 사용을 지원하도록 애플리케이션 구성을 업데이트해야 합니다.
5. 구성 파일 업데이트
첫 번째 단계는 구성 파일을 필요한 대로 모두 업데이트하는 것입니다. Python 2 사용자의 마이그레이션을 지원하는 것이 이 Codelab의 주요 목표이지만, 아래 각 섹션에서는 Python 3으로 추가 포팅하는 방법에 관한 정보도 제공합니다.
requirements.txt
이 섹션에서는 Cloud Memorystore와 Cloud NDB를 지원하는 패키지를 추가합니다. Redis용 Cloud Memorystore의 경우 Cloud Memorystore 클라이언트 라이브러리가 없으므로 Python용 표준 Redis 클라이언트 (redis)를 사용하면 됩니다. requirements.txt에 redis와 google-cloud-ndb을 모두 추가하여 모듈 12의 flask에 결합합니다.
flask
redis
google-cloud-ndb
이 requirements.txt 파일에는 버전 번호가 없으므로 최신 버전이 선택됩니다. 비호환성이 발생하면 버전 번호를 지정하여 작동하는 버전을 잠급니다.
app.yaml
추가할 새 섹션
Python 2 App Engine 런타임에서는 Cloud NDB와 같은 Cloud API를 사용할 때 특정 서드 파티 패키지(grpcio 및 setuptools)가 필요합니다. Python 2 사용자는 app.yaml에 사용 가능한 버전과 함께 이러한 내장 라이브러리를 나열해야 합니다. 아직 libraries 섹션이 없다면 섹션을 만들고 다음과 같이 두 라이브러리를 모두 추가합니다.
libraries:
- name: grpcio
version: latest
- name: setuptools
version: latest
내 앱을 이전할 때 이미 libraries 섹션이 있을 수 있습니다. 이 섹션이 있고 grpcio 및 setuptools이 누락된 경우 기존 libraries 섹션에 추가하면 됩니다.
다음으로 샘플 앱에 Cloud Memorystore 인스턴스 및 VPC 커넥터 정보가 필요하므로 사용 중인 Python 런타임에 관계없이 다음 두 섹션을 app.yaml에 추가합니다.
env_variables:
REDIS_HOST: 'YOUR_REDIS_HOST'
REDIS_PORT: 'YOUR_REDIS_PORT'
vpc_access_connector:
name: projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR
필수 업데이트는 여기까지입니다. 업데이트된 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
env_variables:
REDIS_HOST: 'YOUR_REDIS_HOST'
REDIS_PORT: 'YOUR_REDIS_PORT'
vpc_access_connector:
name: projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR
아래는 app.yaml에 적용해야 하는 업데이트를 보여주는 '전후'입니다.

*Python 3 차이점
이 섹션은 선택사항이며 Python 3으로 포팅하는 경우에만 필요합니다. 이렇게 하려면 Python 2 구성을 여러 가지로 변경해야 합니다. 지금 업그레이드하지 않는 경우 이 섹션을 건너뛰세요.
Python 3 런타임에는 threadsafe도 api_version도 사용되지 않으므로 이 두 설정을 모두 삭제합니다. 최신 App Engine 런타임은 내장된 서드 파티 라이브러리와 내장되지 않은 라이브러리의 복사를 지원하지 않습니다. 서드 파티 패키지의 유일한 요구사항은 requirements.txt에 나열하는 것입니다. 따라서 app.yaml의 전체 libraries 섹션을 삭제할 수 있습니다.
다음으로 Python 3 런타임에서는 자체 라우팅을 실행하는 웹 프레임워크를 사용해야 하므로 모듈 1에서 webp2에서 Flask로 이전하는 방법을 개발자에게 보여드렸습니다. 따라서 모든 스크립트 핸들러를 auto로 변경해야 합니다. 이 앱은 정적 파일을 제공하지 않으므로 핸들러를 나열하는 것은 '무의미'합니다 (모두 auto이므로). 따라서 전체 handlers 섹션도 삭제할 수 있습니다. 따라서 Python 3에 맞게 조정된 새 약식 app.yaml는 다음과 같이 단축되어야 합니다.
runtime: python39
env_variables:
REDIS_HOST: 'YOUR_REDIS_HOST'
REDIS_PORT: 'YOUR_REDIS_PORT'
vpc_access_connector:
name: projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR
Python 3로 포팅할 때 app.yaml의 차이점을 요약하면 다음과 같습니다.
threadsafe및api_version설정 삭제libraries섹션 삭제handlers섹션 삭제 (또는 앱에서 정적 파일을 제공하는 경우script핸들러만 삭제)
값 바꾸기
Memorystore 및 VPC 커넥터의 새 섹션에 있는 값은 자리표시자일 뿐입니다. 대문자로 표시된 값 (YOUR_REDIS_HOST, YOUR_REDIS_PORT, PROJECT_ID, REGION, CONNECTOR_NAME)을 이전에 리소스를 만들 때 저장한 값으로 바꿉니다. Memorystore 인스턴스의 경우 RESERVED_IP이 아닌 HOST와 PORT를 사용해야 합니다. 인스턴스 이름이 demo-ms이고 REGION이 us-central1인 경우 HOST 및 PORT을 가져오는 빠른 명령줄 방법은 다음과 같습니다.
$ gcloud redis instances describe demo-ms --region us-central1 \
--format "value(host,port)"
10.251.161.51 6379
예시 Redis 인스턴스 IP 주소가 10.10.10.10이고, 포트가 6379이며, 리전이 us-central1이고, VPC 커넥터 이름이 demo-vpc인 프로젝트 my-project에 있는 경우 app.yaml의 해당 섹션은 다음과 같습니다.
env_variables:
REDIS_HOST: '10.10.10.10'
REDIS_PORT: '6379'
vpc_access_connector:
name: projects/my-project/locations/us-central1/connectors/demo-vpc
appengine_config.py 만들기 또는 업데이트
내장된 서드 파티 라이브러리 지원 추가
앞서 app.yaml를 사용한 것과 마찬가지로 grpcio 및 setuptools 라이브러리 사용을 추가합니다. 내장된 서드 파티 라이브러리를 지원하도록 appengine_config.py 수정 이 내용이 익숙하게 느껴진다면 모듈 2에서 App Engine ndb에서 Cloud NDB로 마이그레이션할 때도 필요했기 때문입니다. 필요한 정확한 변경사항은 lib 폴더를 setuptools.pkg_resources 작업 집합에 추가하는 것입니다.

*Python 3 차이점
이 섹션은 선택사항이며 Python 3으로 포팅하는 경우에만 필요합니다. App Engine 2세대에서 반가운 변경사항 중 하나는 (기본 제공이 아닌) 서드 파티 패키지의 복사 (때로는 '벤더링'이라고 함)와 app.yaml의 기본 제공 서드 파티 패키지 참조가 더 이상 필요하지 않다는 것입니다. 즉, 전체 appengine_config.py 파일을 삭제할 수 있습니다.
6. 애플리케이션 파일 업데이트
애플리케이션 파일이 main.py 하나뿐이므로 이 섹션의 모든 변경사항은 해당 파일에만 영향을 미칩니다. 이 애플리케이션을 Cloud Memorystore로 이전하기 위해 변경할 사항을 그림으로 나타냈습니다. 이는 설명 목적으로만 제공되며 자세히 분석해서는 안 됩니다. 모든 작업은 코드 변경에 있습니다.

맨 위부터 한 섹션씩 살펴보겠습니다.
가져오기 업데이트
모듈 12의 main.py 가져오기 섹션에서는 Cloud NDB와 Cloud Tasks를 사용합니다. 가져오기는 다음과 같습니다.
이전:
from flask import Flask, render_template, request
from google.appengine.api import memcache
from google.appengine.ext import ndb
Memorystore로 전환하려면 환경 변수를 읽어야 하므로 Python Redis 클라이언트인 redis뿐만 아니라 Python os 모듈도 필요합니다. Redis는 Python 객체를 캐시할 수 없으므로 pickle를 사용하여 가장 최근 방문 목록을 마샬링합니다. 따라서 pickle도 가져옵니다. Memcache의 장점 중 하나는 객체 직렬화가 자동으로 이루어지는 반면 Memorystore는 약간 더 'DIY'에 가깝다는 것입니다. 마지막으로 google.appengine.ext.ndb을 google.cloud.ndb로 바꿔 App Engine ndb에서 Cloud NDB로 업그레이드합니다. 이러한 변경사항을 적용한 후 가져오기는 다음과 같이 표시됩니다.
AFTER:
import os
import pickle
from flask import Flask, render_template, request
from google.cloud import ndb
import redis
초기화 업데이트
모듈 12 초기화는 Flask 애플리케이션 객체 app를 인스턴스화하고 1시간 분량의 캐싱을 위한 상수를 설정하는 것으로 구성됩니다.
이전:
app = Flask(__name__)
HOUR = 3600
Cloud API를 사용하려면 클라이언트가 필요하므로 Flask 바로 뒤에 Cloud NDB 클라이언트를 인스턴스화합니다. 다음으로 app.yaml에서 설정한 환경 변수에서 Memorystore 인스턴스의 IP 주소와 포트 번호를 가져옵니다. 이 정보를 사용하여 Redis 클라이언트를 인스턴스화합니다. 업데이트 후 코드는 다음과 같습니다.
AFTER:
app = Flask(__name__)
ds_client = ndb.Client()
HOUR = 3600
REDIS_HOST = os.environ.get('REDIS_HOST', 'localhost')
REDIS_PORT = os.environ.get('REDIS_PORT', '6379')
REDIS = redis.Redis(host=REDIS_HOST, port=REDIS_PORT)
*Python 3 마이그레이션
이 섹션은 선택사항이며 모듈 12 앱의 Python 3 버전에서 시작하는 경우에만 필요합니다. 이 경우 가져오기 및 초기화와 관련된 몇 가지 필수 변경사항이 있습니다.
먼저 Memcache는 App Engine 번들 서비스이므로 Python 3 앱에서 사용하려면 App Engine SDK가 필요합니다. 특히 WSGI 애플리케이션과 기타 필요한 구성을 래핑해야 합니다.
이전:
from flask import Flask, render_template, request
from google.appengine.api import memcache, wrap_wsgi_app
from google.appengine.ext import ndb
app = Flask(__name__)
app.wsgi_app = wrap_wsgi_app(app.wsgi_app)
HOUR = 3600
Memcache와 같은 App Engine 번들 서비스가 아닌 Cloud Memorystore로 마이그레이션하므로 SDK 사용을 삭제해야 합니다. memcache와 wrap_wsgi_app를 모두 가져오는 전체 줄을 삭제하면 되므로 간단합니다. wrap_wsgi_app()를 호출하는 줄도 삭제합니다. 이러한 업데이트를 적용하면 앱의 이 부분 (실제로 전체 앱)이 Python 2 버전과 동일하게 유지됩니다.
AFTER:
import os
import pickle
from flask import Flask, render_template, request
from google.cloud import ndb
import redis
app = Flask(__name__)
ds_client = ndb.Client()
HOUR = 3600
REDIS_HOST = os.environ.get('REDIS_HOST', 'localhost')
REDIS_PORT = os.environ.get('REDIS_PORT', '6379')
REDIS = redis.Redis(host=REDIS_HOST, port=REDIS_PORT)
마지막으로 app.yaml에서 SDK 사용을 삭제하고 (app_engine_apis: true 줄 삭제) requirements.txt에서 SDK 사용을 삭제합니다 (appengine-python-standard 줄 삭제).
Cloud Memorystore (및 Cloud NDB)로 마이그레이션
Cloud NDB의 데이터 모델은 App Engine ndb와 호환되도록 설계되었으며, 이는 Visit 객체의 정의가 동일하게 유지된다는 의미입니다. 모듈 2의 Cloud NDB로의 마이그레이션을 모방하여 store_visit() 및 fetch_visits()의 모든 Datastore 호출이 증강되고 새 with 블록에 삽입됩니다 (Cloud NDB 컨텍스트 관리자 사용이 필요하므로). 변경 전의 통화는 다음과 같습니다.
이전:
def store_visit(remote_addr, user_agent):
'create new Visit entity in Datastore'
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
def fetch_visits(limit):
'get most recent visits'
return Visit.query().order(-Visit.timestamp).fetch(limit)
두 함수에 with ds_client.context() 블록을 추가하고 Datastore 호출을 내부에 배치합니다 (들여쓰기). 이 경우 호출 자체를 변경할 필요는 없습니다.
AFTER:
def store_visit(remote_addr, user_agent):
'create new Visit entity in Datastore'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
def fetch_visits(limit):
'get most recent visits'
with ds_client.context():
return Visit.query().order(-Visit.timestamp).fetch(limit)
다음으로 캐싱 변경사항을 살펴보겠습니다. 모듈 12의 main() 함수는 다음과 같습니다.
이전:
@app.route('/')
def root():
'main application (GET) handler'
# check for (hour-)cached visits
ip_addr, usr_agt = request.remote_addr, request.user_agent
visitor = '{}: {}'.format(ip_addr, usr_agt)
visits = memcache.get('visits')
# register visit & run DB query if cache empty or new visitor
if not visits or visits[0].visitor != visitor:
store_visit(ip_addr, usr_agt)
visits = list(fetch_visits(10))
memcache.set('visits', visits, HOUR) # set() not add()
return render_template('index.html', visits=visits)
Redis에는 Memcache와 마찬가지로 'get' 및 'set' 호출이 있습니다. 각 클라이언트 라이브러리를 바꾸기만 하면 되나요? 거의 정확합니다. 앞서 언급했듯이 Redis를 사용하여 Python 목록을 캐시할 수는 없습니다 (먼저 직렬화해야 함. Memcache는 이 작업을 자동으로 처리함). 따라서 set() 호출에서 pickle.dumps()를 사용하여 방문을 문자열로 'pickle'합니다. 마찬가지로 캐시에서 방문을 가져올 때는 get() 직후에 pickle.loads()로 언피클해야 합니다. 이러한 변경사항을 구현한 후의 기본 핸들러는 다음과 같습니다.
AFTER:
@app.route('/')
def root():
'main application (GET) handler'
# check for (hour-)cached visits
ip_addr, usr_agt = request.remote_addr, request.user_agent
visitor = '{}: {}'.format(ip_addr, usr_agt)
rsp = REDIS.get('visits')
visits = pickle.loads(rsp) if rsp else None
# register visit & run DB query if cache empty or new visitor
if not visits or visits[0].visitor != visitor:
store_visit(ip_addr, usr_agt)
visits = list(fetch_visits(10))
REDIS.set('visits', pickle.dumps(visits), ex=HOUR)
return render_template('index.html', visits=visits)
이것으로 샘플 앱의 Memcache 사용을 Cloud Memorystore로 변환하는 데 필요한 main.py의 변경사항이 완료됩니다. HTML 템플릿과 Python 3로의 포팅은 어떻게 되나요?
HTML 템플릿 파일을 업데이트하고 Python 3로 포팅해야 하나요?
놀라운 소식입니다. 애플리케이션이 코드 변경이나 호환성 라이브러리 없이 Python 2와 3 모두에서 실행되도록 설계되었으므로 여기서는 아무것도 할 필요가 없습니다. main.py을 확인할 수 있습니다. mod13a (2.x) 및 mod13b (3.x) 'FINISH' 폴더에서 동일합니다. 버전 번호 (사용된 경우)의 차이를 제외하고 requirements.txt도 마찬가지입니다. 사용자 인터페이스는 변경되지 않으므로 templates/index.html도 업데이트되지 않습니다.
Python 3 App Engine에서 이 앱을 실행하는 데 필요한 모든 작업은 앞서 구성에서 완료되었습니다. 불필요한 지시문이 app.yaml에서 삭제되었고 appengine_config.py과 lib 폴더는 Python 3에서 사용되지 않으므로 삭제되었습니다.
7. 요약/삭제
이 섹션에서는 앱을 배포하고 의도한 대로 작동하는지, 반영된 출력이 있는지 확인하여 이 Codelab을 마무리합니다. 앱 유효성 검사 후 정리 작업을 실행하고 다음 단계를 고려합니다.
애플리케이션 배포 및 확인
마지막으로 항상 샘플 앱을 배포해야 합니다. Python 2 개발자는 아래 명령어를 사용하여 lib를 삭제하고 다시 설치하세요. (시스템에 Python 2와 3이 모두 설치되어 있는 경우 대신 pip2를 명시적으로 실행해야 할 수 있습니다.)
rm -rf ./lib pip install -t lib -r requirements.txt
이제 Python 2 및 3 개발자는 다음을 사용하여 앱을 배포해야 합니다.
gcloud app deploy
완전히 다른 캐싱 서비스를 위해 내부적으로만 다시 연결했으므로 앱 자체는 Module 12 앱과 동일하게 작동해야 합니다.

이 단계로 Codelab이 완료됩니다. 업데이트된 샘플 앱을 모듈 13 폴더인 mod13a (Python 2) 또는 mod13b (Python 3)과 비교해 보세요.
삭제
일반
지금까지 완료한 경우 청구가 발생하지 않도록 App Engine 앱을 사용 중지하는 것이 좋습니다. 하지만 테스트나 실험을 더 진행하고 싶다면 App Engine 플랫폼에 무료 할당량이 있으므로 해당 사용량 등급을 초과하지 않는 한 요금이 청구되지 않습니다. 이는 컴퓨팅에 대한 요금이며 관련 App Engine 서비스에 대한 요금도 부과될 수 있으므로 자세한 내용은 가격 책정 페이지를 확인하세요. 이 이전과 관련된 다른 클라우드 서비스는 별도로 청구됩니다. 두 경우 모두 해당하는 경우 아래의 '이 Codelab에만 해당' 섹션을 참고하세요.
완전한 공개를 위해 말씀드리면 App Engine과 같은 Google Cloud 서버리스 컴퓨팅 플랫폼에 배포하면 약간의 빌드 및 스토리지 비용이 발생합니다. Cloud Build에는 Cloud Storage와 마찬가지로 자체 무료 할당량이 있습니다. 해당 이미지를 저장하면 할당량의 일부가 사용됩니다. 하지만 무료 등급이 없는 지역에 거주할 수도 있으므로 스토리지 사용량을 파악하여 잠재적인 비용을 최소화하세요. 검토해야 하는 특정 Cloud Storage '폴더'는 다음과 같습니다.
console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/imagesconsole.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com- 위의 스토리지 링크는
PROJECT_ID및 *LOC*에 따라 달라집니다. 예를 들어 앱이 미국에서 호스팅되는 경우 'us'입니다.
반면에 이 애플리케이션 또는 기타 관련 이전 Codelab을 계속하지 않고 모든 것을 완전히 삭제하려면 프로젝트를 종료하세요.
이 Codelab에만 해당
아래에 나열된 서비스는 이 Codelab에만 해당합니다. 자세한 내용은 각 제품의 문서를 참고하세요.
- Cloud Memorystore에는 인스턴스가 필요하며 무료 등급이 없습니다. 사용 비용에 대해 자세히 알아보려면 가격 책정 페이지를 참고하세요.
- Cloud 서버리스 VPC 액세스 커넥터에는 인스턴스가 필요하며 무료 등급이 없습니다. 사용 비용에 대해 자세히 알아보려면 Cloud VPC 가격 책정 페이지의 해당 섹션을 참고하세요.
- Cloud Datastore (Datastore 모드의 Cloud Firestore)에는 무료 등급이 있습니다. 자세한 내용은 가격 책정 페이지를 참고하세요.
이 튜토리얼에서는 다음 네 가지 클라우드 제품을 사용했습니다.
- App Engine
- Cloud Datastore
- Cloud Memorystore
- Cloud VPC
아래는 이러한 리소스를 해제하고 요금 청구를 방지하거나 최소화하는 방법입니다.
Memorystore 인스턴스 및 VPC 커넥터 종료
무료 등급이 없는 제품이므로 지금 요금이 청구됩니다. Cloud 프로젝트를 종료하지 않으면 (다음 섹션 참고) 청구를 중지하기 위해 Memorystore 인스턴스와 VPC 커넥터를 모두 삭제해야 합니다. 이러한 리소스를 만들 때와 마찬가지로 Cloud Console 또는 명령줄에서 리소스를 해제할 수도 있습니다.
Cloud 콘솔에서
Memorystore 인스턴스를 삭제하려면 Memorystore 대시보드로 돌아가서 인스턴스 ID를 클릭합니다.

해당 인스턴스의 세부정보 페이지에서 '삭제'를 클릭하고 확인합니다.
VPC 커넥터를 삭제하려면 해당 대시보드로 이동하여 삭제할 커넥터 옆에 있는 체크박스를 선택한 다음 '삭제'를 클릭하고 확인합니다.

명령줄에서
다음 gcloud 명령어 쌍은 각각 Memorystore 인스턴스와 VPC 커넥터를 삭제합니다.
gcloud redis instances delete INSTANCE --region REGIONgcloud compute networks vpc-access connectors delete CONNECTOR --region REGION
gcloud config set project로 프로젝트 ID를 설정하지 않은 경우 --project PROJECT_ID를 제공해야 할 수 있습니다. Memorystore 인스턴스 이름이 demo-ms이고 VPC 커넥터 이름이 demo-vpc이며 둘 다 us-central1 리전에 있는 경우 다음 명령어 쌍을 실행하고 확인합니다.
$ gcloud redis instances delete demo-ms --region us-central1 You are about to delete instance [demo-ms] in [us-central1]. Any associated data will be lost. Do you want to continue (Y/n)? Delete request issued for: [demo-ms] Waiting for operation [projects/PROJECT/locations/REGION/operations/operation-aaaaa-bbbbb-ccccc-ddddd] to complete...done. Deleted instance [demo-ms]. $ $ gcloud compute networks vpc-access connectors delete demo-vpc --region us-central1 You are about to delete connector [demo-vpc] in [us-central1]. Any associated data will be lost. Do you want to continue (Y/n)? Delete request issued for: [demo-vpc] Waiting for operation [projects/PROJECT/locations/REGION/operations/aaaaa-bbbb-cccc-dddd-eeeee] to complete...done. Deleted connector [demo-vpc].
각 요청을 실행하는 데 몇 분 정도 걸립니다. 앞서 설명한 대로 전체 Cloud 프로젝트를 종료하는 경우 이 단계는 선택사항이지만 종료 프로세스가 완료될 때까지는 요금이 청구됩니다.
다음 단계
이 튜토리얼 외에도 기존 번들 서비스에서 벗어나는 데 중점을 둔 다른 이전 모듈은 다음과 같습니다.
- 모듈 2: App Engine
ndb에서 Cloud NDB로 마이그레이션 - 모듈 7~9: App Engine 태스크 큐 푸시 작업에서 Cloud Tasks로 마이그레이션
- 모듈 12~13: App Engine Memcache에서 Cloud Memorystore로 이전
- 모듈 15~16: App Engine Blobstore에서 Cloud Storage로 이전
- 모듈 18~19: App Engine 태스크 큐 (풀 태스크)에서 Cloud Pub/Sub로 이전
App Engine은 더 이상 Google Cloud의 유일한 서버리스 플랫폼이 아닙니다. 소규모 App Engine 앱이 있거나 기능이 제한된 앱이 있는데 이를 독립형 마이크로서비스로 전환하려는 경우 또는 모놀리식 앱을 재사용 가능한 여러 구성요소로 분할하려는 경우 Cloud Functions로 이전하는 것이 좋습니다. 컨테이너화가 애플리케이션 개발 워크플로의 일부가 된 경우, 특히 CI/CD (지속적 통합/지속적 배포) 파이프라인으로 구성된 경우 Cloud Run으로 이전하는 것이 좋습니다. 이러한 시나리오는 다음 모듈에서 다룹니다.
- App Engine에서 Cloud Functions로 이전: 모듈 11 참고
- App Engine에서 Cloud Run으로 마이그레이션: 모듈 4에서 Docker를 사용하여 앱을 컨테이너화하거나 모듈 5에서 컨테이너, Docker 지식 또는
Dockerfile없이 컨테이너화하는 방법을 알아보세요.
다른 서버리스 플랫폼으로 전환하는 것은 선택사항이며, 변경하기 전에 앱과 사용 사례에 가장 적합한 옵션을 고려하는 것이 좋습니다.
다음에 고려할 마이그레이션 모듈과 관계없이 모든 서버리스 마이그레이션 스테이션 콘텐츠 (Codelabs, 동영상, 소스 코드[사용 가능한 경우])는 오픈소스 저장소에서 액세스할 수 있습니다. 저장소의 README에서는 고려해야 할 이전과 관련 '순서'의 이전 모듈에 관한 안내도 제공합니다.
8. 추가 리소스
아래에는 이 마이그레이션 모듈 또는 관련 마이그레이션 모듈과 관련 제품을 자세히 살펴보는 개발자를 위한 추가 리소스가 나와 있습니다. 여기에는 이 콘텐츠에 대한 의견을 제공할 수 있는 위치, 코드 링크, 유용할 수 있는 다양한 문서가 포함됩니다.
Codelabs 문제/의견
이 Codelab에 문제가 발견된 경우 문제를 기록하기 전에 먼저 비슷한 기록이 있는지 검색해보세요. 검색 및 새 문제 만들기 링크:
마이그레이션 리소스
모듈 12 (시작) 및 모듈 13 (완료)의 저장소 폴더 링크는 아래 표에서 찾을 수 있습니다. 또한 클론 또는 ZIP 파일로 다운로드할 수 있는 모든 App Engine Codelab 마이그레이션 저장소에서 액세스할 수도 있습니다.
Codelab | Python 2 | Python 3 |
모듈 13 (이 Codelab) |
온라인 참조
다음은 이 튜토리얼과 관련이 있을 수 있는 온라인 리소스입니다.
App Engine
- App Engine 문서
- Python 2 App Engine (표준 환경) 런타임
- Python 2 App Engine에서 App Engine 내장 라이브러리 사용
- Python 3 App Engine (표준 환경) 런타임
- Python 2 및 3 App Engine (표준 환경) 런타임 간의 차이점
- Python 2~3 App Engine (표준 환경) 마이그레이션 가이드
- App Engine 가격 및 할당량 정보
App Engine NDB 및 Cloud NDB
- App Engine NDB 개요
- App Engine NDB Datastore 사용
- Google Cloud NDB 문서
- Google Cloud NDB 저장소
- Cloud Datastore 가격 정보
App Engine Memcache 및 Cloud Memorystore
- App Engine Memcache 개요
- Python 2 App Engine
memcache참조 - Python 3 App Engine
memcache참조 - App Engine
memcache에서 Cloud Memorystore로의 마이그레이션 가이드 - Cloud Memorystore 문서
- Redis용 Cloud Memorystore 문서
- Redis용 Cloud Memorystore 가격 정보
- Cloud Memorystore 지원 Redis 버전
- Cloud Memorystore 홈페이지
- Cloud 콘솔에서 새 Memorystore 인스턴스 만들기
- Python Redis 클라이언트 홈페이지
- Python Redis 클라이언트 라이브러리 문서
Cloud VPC
기타 클라우드 정보
- Google Cloud Platform에서 Python 사용
- Google Cloud Python 클라이언트 라이브러리
- Google Cloud '상시 무료' 등급
- Google Cloud SDK (
gcloud명령줄 도구) - 모든 Google Cloud 문서
라이선스
이 작업물은 Creative Commons Attribution 2.0 일반 라이선스에 따라 사용이 허가되었습니다.
