1. 개요
이 Codelab 시리즈 (사용자 주도형, 실무 가이드)는 Google App Engine (표준) 개발자가 일련의 마이그레이션을 통해 자신의 앱을 현대화할 수 있도록 돕기 위한 것입니다. 이러한 마이그레이션의 대부분은 차세대 런타임이 더 유연하고 다양한 서비스 옵션을 제공하기 때문에 원래의 런타임 번들 서비스로부터 벗어나는 것입니다. 앱을 현대화하는 또 다른 방법은 최신 제품으로 업그레이드하는 것입니다. 이 Codelab에서는 이 방법을 다룹니다.
Cloud NDB 또는 Cloud Datastore 클라이언트 라이브러리로 Datastore에 액세스하는 App Engine 사용자는 추가로 마이그레이션할 필요가 없습니다. 하지만 Cloud Firestore는 Firebase 실시간 데이터베이스의 기능을 갖춘 최신 확장 가능 고가용성 NoSQL 데이터 스토어를 나타냅니다.
Firestore의 기능을 활용하기 위해 Firestore를 사용해야 한다고 생각하거나 마이그레이션에 대해 알아볼 만큼 관심이 있는 개발자라면 이 가이드가 적합합니다. 이 튜토리얼에서는 Cloud Datastore를 사용하는 App Engine 앱을 Cloud Firestore로 이전하는 방법을 알아봅니다.
학습 목표
- Datastore와 Firestore의 차이점 인식
- Cloud Datastore에서 Cloud Firestore로 마이그레이션
필요한 항목
- 다음을 포함하는 Google Cloud Platform 프로젝트
- 기본 Python 기술
- 일반적인 Linux 명령어에 대한 실무 지식
- App Engine 앱 개발 및 배포에 대한 기본 지식
- 이 모듈(모듈 6)을 시작하기 전에 모듈 3 Codelab을 완료하는 것이 좋습니다(Python 3으로 포팅 포함).
- 작동되는 모듈 3 Cloud Datastore Python 3 App Engine 앱
설문조사
이 Codelab을 어떻게 사용할 예정인가요?
2. 배경
App Engine의 Datastore는 2013년에 자체 제품인 Google Cloud Datastore가 되었으며 이제 App Engine 외부의 개발자가 액세스할 수 있습니다. 다음 해에 Firebase는 Google에 인수되었습니다. 당시에는 실시간 데이터베이스로 유명했습니다.
그 후 몇 년 동안 Firebase 및 Cloud Datastore팀은 Firebase 기능을 Datastore에 통합하기 위해 노력했습니다. 그 결과 2017년에 차세대 Cloud Datastore가 출시되었습니다. 일부 Firebase 기능을 상속하는 것을 반영하기 위해 Cloud Firestore로 리브랜딩되었습니다.
Cloud Firestore가 Google Cloud 프로젝트의 기본 NoSQL 스토리지 메커니즘이 되었습니다. 새 앱은 Cloud Firestore를 기본적으로 사용할 수 있으며 기존 Datastore 데이터베이스는 내부적으로 Firestore로 변환되어 이제 Datastore 작업과의 호환성을 유지하기 위해 'Datastore 모드의 Firestore'로 작동합니다. 따라서 애플리케이션은 이러한 모드 중 하나에서만 Cloud Firestore를 작동할 수 있으며 일단 설정되면 변경할 수 없습니다.
현재 사용자가 새 프로젝트를 만들고 NoSQL 솔루션을 선택하면 Datastore 모드의 Firestore 또는 네이티브 모드의 Firestore를 선택하라는 메시지가 표시됩니다. 사용자가 Datastore 엔티티를 추가하면 Firestore로 변경할 수 없으며, 마찬가지로 Firestore 기본 모드를 선택하면 더 이상 Datastore (또는 Datastore 모드의 Firestore)로 다시 전환할 수 없습니다. 자세한 내용은 문서의 Datastore 모드의 Cloud Firestore와 기본 Firestore 모드 중 선택 페이지를 참고하세요. 앱을 Firestore로 이전하려면 새 프로젝트를 만들고 Datastore를 내보낸 후 Firestore로 가져와야 합니다. 이 튜토리얼의 목적은 개발자에게 Cloud Datastore와 Cloud Firestore 사용 간의 차이점을 알려주는 것입니다.
이 이전은 사용자가 실행할 것으로 예상되지 않으므로 선택적 이전입니다. 클라이언트 인증, Firebase 규칙 통합, Firebase 실시간 데이터베이스와 같은 Cloud Firestore를 기본적으로 사용하는 데는 분명한 이점이 있지만 마이그레이션 단계가 '불편'합니다.
- 현재 앱의 프로젝트와 다른 프로젝트를 사용해야 합니다.
- 앱에서 Datastore 항목을 추가한 프로젝트는 Native 모드의 Firestore로 전환할 수 없습니다.
- 마찬가지로 네이티브 모드의 Firestore를 선택한 프로젝트는 Datastore 모드의 Firestore로 되돌릴 수 없습니다.
- 한 프로젝트에서 다른 프로젝트로 데이터를 스트리밍할 수 있는 마이그레이션 도구는 없습니다.
- 네임스페이스, 더 높은 쓰기 처리량 (>10,000/초) 등 일부 중요한 Datastore 기능은 Firestore에서 사용할 수 없습니다.
- 내보내기 및 가져오기 도구는 '원시' 및 '전부 또는 전무' 시나리오입니다.
- 앱에 Datastore 항목이 많은 경우 내보낸 후 Firestore로 가져오는 데 몇 시간이 걸릴 수 있습니다.
- 이 기간 동안 애플리케이션/서비스는 데이터를 쓰거나 업데이트할 수 없습니다.
- 이전 활동은 일반 사용량에 포함되므로 비용을 최소화하려면 가능한 경우 일일 할당량에 걸쳐 분산하는 것이 좋습니다.
- 새 서비스가 다른 프로젝트에서 실행되므로 DNS 업데이트가 전파될 시간이 필요합니다.
- Datastore와 Firestore는 데이터 모델이 유사하지만 다르므로 마이그레이션하려면 앱/서비스가 작동하는 방식을 업데이트해야 합니다.
- 이제 Datastore의 상위 요소 쿼리가 Firestore 컬렉션 쿼리 (기본값)입니다.
- Datastore의 광범위한 유형 쿼리는 Firestore 컬렉션 그룹 쿼리입니다.
- 색인과 처리 방식이 다릅니다.
하지만 마이그레이션을 고려 중인 앱이 비교적 간단하거나, 마이그레이션 시뮬레이션을 준비 중이거나, Datastore와 Firestore에 대해 알아보고 싶다면 계속 진행하세요.
Python 2 사용자: 이 선택적 이전 Codelab은 Python 3에서만 제공되지만 Cloud Firestore는 2.x도 지원하므로 사용자는 사용 시 차이점을 보간할 수 있습니다. 한 가지 예로 Firestore 레코드는 바이트 문자열 대신 유니코드 문자열을 사용하므로 Python 2 문자열 리터럴에는 u'' 선행 표시기가 필요합니다. 즉, 2.x store_visit() 함수는 다음과 같이 표시됩니다.
def store_visit(remote_addr, user_agent):
doc_ref = fs_client.collection(u'Visit')
doc_ref.add({
u'timestamp': datetime.now(),
u'visitor': u'{}: {}'.format(remote_addr, user_agent),
})
그 외에는 클라이언트 라이브러리가 유사하게 작동해야 합니다. 고려해야 할 다른 문제는 2.x Cloud Firestore 라이브러리가 개발 측면에서 '고정'되어 있으므로 점점 더 많은 최신 기능이 3.x Firestore 클라이언트 라이브러리에서만 제공된다는 것입니다.
이 마이그레이션을 진행할 때 이 튜토리얼의 기본 단계는 다음과 같습니다.
- 설정/사전 작업
- Cloud Firestore 라이브러리 추가
- 애플리케이션 파일 업데이트
3. 설정/사전 작업
이 가이드의 주요 부분을 진행하기 전에 프로젝트를 설정하고 코드를 가져온 후 기본 앱을 배포하여 작동하는 코드로 시작할 수 있도록 준비합니다.
1. 프로젝트 설정
모듈 3 Codelab을 완료하는 데 사용한 것과 동일한 프로젝트를 재사용하는 것이 좋습니다. 또는 완전히 새로운 프로젝트를 만들거나 다른 기존 프로젝트를 다시 사용할 수도 있습니다. 프로젝트에 활성 결제 계정이 있고 App Engine(앱)이 사용 설정되어 있는지 확인합니다.
2. 기준 샘플 앱 가져오기
이 Codelab의 기본 요건 중 하나는 작동하는 모듈 3 샘플 앱을 준비하는 것입니다. 샘플 앱이 없는 경우에는 계속하기 전에 모듈 3 가이드 (위 링크)를 완료하세요. 가이드 내용을 잘 알고 계시다면 아래 모듈 3 코드를 선택하여 시작하세요.
무엇을 사용하든 모듈 3 코드에서부터 시작해야 합니다. 이 모듈 6 Codelab은 각 단계를 안내합니다. 완료되면 완료 지점의 코드와 비슷해야 합니다. (이 튜토리얼은 Python 3에서만 사용할 수 있습니다.)
모듈 3 파일 (사용자 또는 Google의 파일)의 디렉터리는 다음과 같습니다.
$ ls
README.md main.py templates
app.yaml requirements.txt
3. 모듈 3 앱 (재)배포
이제 남은 사전 작업 실행 단계는 다음과 같습니다.
gcloud명령줄 도구 사용 방법을 다시 숙지합니다(필요한 경우).- 모듈 3 코드를 App Engine에 (재)배포합니다 (필요한 경우).
이러한 단계를 성공적으로 실행하고, 작동하는지 확인한 후에는 이 가이드로 이동하여, 구성 파일 작업을 시작합니다.
Python 2 요구사항
app.yaml가 서드 파티 번들 패키지인grpcio및setuptools를 참조하는지 확인합니다.appengine_config.py가 여전히pkg_resources및google.appengine.ext.vendor를 사용하여 앱이 서드 파티 리소스를 가리키도록 해야 합니다.- 다음 섹션에서
requirements.txt를 업데이트할 때는google-cloud-firestore==1.9.0를 사용해야 합니다. 이는 Python Firestore 클라이언트 라이브러리의 최종 2.x 호환 버전이기 때문입니다.requirements.txt에google-cloud-core항목이 있는 경우 그대로 둡니다.lib을 삭제하고pip install -t lib -r requirements.txt로 다시 설치합니다.
4. 구성 파일 업데이트 (Cloud Firestore 라이브러리 추가)
설정 외에 필요한 다음 단계는 구성과 애플리케이션 파일을 업데이트하는 것입니다. 전자의 경우 requirements.txt 파일에서 패키지를 약간만 바꾸면 되므로 지금 바로 진행하겠습니다.
requirements.txt에서 google-cloud-datastore 줄을 google-cloud-firestore로 바꿔 다음과 같이 만듭니다.
Flask==1.1.2
google-cloud-firestore==2.0.2
각 라이브러리의 최신 버전을 사용하는 것이 좋습니다. 위의 버전 번호는 이 글을 작성할 당시의 최신 버전입니다. FINISH 저장소 폴더의 코드는 더 자주 업데이트되며 최신 버전이 있을 수 있습니다.
다른 구성 변경사항은 없으므로 app.yaml 및 templates/index.html은 그대로 유지됩니다.
5. 애플리케이션 파일 업데이트
애플리케이션 파일이 main.py 하나뿐이므로 이 섹션의 모든 변경사항은 해당 파일에만 영향을 미칩니다.
1. 가져오기
패키지 가져오기를 datastore에서 firestore로 전환하는 것은 사소한 변경사항입니다.
- 이전:
from google.cloud import datastore
- 이후:
from google.cloud import firestore
2. Firestore 액세스
Flask를 초기화한 후 Firestore 클라이언트를 만듭니다. 위와 유사한 변경사항을 클라이언트 초기화에 적용합니다.
- 이전:
app = Flask(__name__)
ds_client = datastore.Client()
- 이후:
app = Flask(__name__)
fs_client = firestore.Client()
Cloud NDB에서 Cloud Datastore로 마이그레이션하면 Cloud Firestore를 사용하기 위한 준비가 완료됩니다. Datastore를 사용하면 일반 속성으로 구성된 항목을 만들고 키별로 그룹화하여 데이터 레코드를 만들 수 있습니다. Firestore의 데이터 레코드는 키-값 쌍으로 구성되고 컬렉션으로 그룹화된 문서입니다. Datastore에서 이전하려면 이러한 차이점을 고려해야 합니다. 데이터 레코드를 만들 때뿐만 아니라 데이터 레코드를 쿼리할 때도 이러한 차이점이 나타나기 때문입니다. Datastore 코드의 복잡성에 따라 결과가 달라질 수 있습니다.
Datastore의 경우 필터링 및 정렬 기준과 함께 항목 유형을 기반으로 쿼리를 실행합니다. Firestore의 경우 데이터 쿼리도 비슷합니다. 다음 쿼리 값, 클라이언트 (각각 ds_client 또는 fs_client), 가져오기를 가정하여 간단한 예를 살펴보겠습니다.
from datetime import datetime
from firestore.Query import DESCENDING
OCT1 = datetime(2020, 10, 1)
LIMIT = 10
Datastore의 경우 2020년 10월 1일 이후의 최신 Visit 항목 10개를 내림차순으로 쿼리합니다.
query = ds_client.query(kind='Visit')
query.add_filter('timestamp', '>=', datetime(2020, 10, 1))
query.order = ['-timestamp']
return query.fetch(limit=LIMIT)
Firestore의 경우 Visit 컬렉션에서 동일한 작업을 수행합니다.
query = fs_client.collection('Visit')
query.where('timestamp', '>=', datetime(2020, 10, 1))
query.order_by('timestamp', direction=DESCENDING)
return query.limit(LIMIT).stream()
샘플 앱 쿼리가 더 간단합니다('WHERE' 절 없음). 검토를 위해 Cloud 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)
Firestore로 이전하면 새 문서를 엔티티와 유사하게 만들고 쿼리는 앞에서와 같이 만들 수 있습니다.
- 이후:
def store_visit(remote_addr, user_agent):
doc_ref = fs_client.collection('Visit')
doc_ref.add({
'timestamp': datetime.now(),
'visitor': '{}: {}'.format(remote_addr, user_agent),
})
def fetch_visits(limit):
visits_ref = fs_client.collection('Visit')
visits = (v.to_dict() for v in visits_ref.order_by('timestamp',
direction=firestore.Query.DESCENDING).limit(limit).stream())
return visits
기본 함수 root()는 index.html 템플릿 파일과 마찬가지로 동일하게 유지됩니다. 변경사항을 다시 확인하고 저장한 후 배포하고 확인합니다.
6. 요약/삭제
애플리케이션 배포
gcloud app deploy로 앱을 다시 배포하고 앱이 작동하는지 확인합니다. 이제 코드는 모듈 6 저장소 (또는 원하는 경우 2.x 버전)에 있는 것과 일치해야 합니다.
앞의 Codelab을 수행하지 않고 이 시리즈를 바로 시작한 경우에는 앱 자체가 변경되지 않습니다. 모든 방문을 기본 웹페이지(/)에 등록하고 사이트를 충분히 방문한 후 다음과 같이 표시됩니다.

선택사항인 모듈 6 마이그레이션을 완료하셨습니다. 이는 App Engine 데이터 스토리지에 관해 수행할 수 있는 마지막 마이그레이션 중 하나일 수 있습니다. 아직 앱을 컨테이너화하지 않은 경우 Cloud Run용으로 앱을 컨테이너화하는 방법을 고려해 볼 수 있습니다 (아래 링크된 Codelab의 모듈 4 및 5 참고).
선택사항: 삭제
다음 마이그레이션 Codelab으로 이동할 준비가 될 때까지 비용이 결제되지 않도록 하려면 삭제를 수행해야 합니다. 기존 개발자라면 App Engine 가격 책정 정보를 이미 잘 알고 계실 것입니다.
선택사항: 앱 사용 중지
다음 가이드로 이동할 준비가 되지 않았으면 비용 발생을 방지하기 위해 앱을 사용 중지하세요. 다음 Codelab으로 이동할 준비가 되었으면 이를 다시 사용 설정하면 됩니다. 앱이 사용 중지되면 비용을 일으키는 트래픽이 수행되지 않습니다. 하지만 무료 할당량을 초과할 경우 해당 Firestore 사용량에 대한 비용이 결제될 수 있습니다. 따라서 제한에 걸리지 않도록 충분히 삭제해야 합니다.
반면에 마이그레이션을 계속하지 않고 모든 것을 완전히 삭제하려면 프로젝트를 종료하면 됩니다.
다음 단계
이 튜토리얼 외에도 고려할 수 있는 다른 이전 모듈 Codelab이 있습니다.
- 모듈 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 Buildpacks를 사용하여 Cloud Run으로 마이그레이션
- Cloud Buildpacks를 사용하여 Cloud Run에서 실행할 앱 컨테이너화
- Docker, 컨테이너,
Dockerfile에 대해 알 필요가 없습니다. - 앱이 이미 Python 3로 마이그레이션되어 있어야 합니다(Buildpacks는 Python 2를 지원하지 않음).
7. 추가 리소스
App Engine 마이그레이션 모듈 Codelab 문제/의견
이 Codelab에 문제가 발견된 경우 문제를 기록하기 전에 먼저 비슷한 기록이 있는지 검색해보세요. 검색 및 새 문제 만들기 링크:
마이그레이션 리소스
모듈 3 (시작) 및 모듈 6 (완료)의 저장소 폴더 링크는 아래 표에서 찾을 수 있습니다. 또한 클론 또는 ZIP 파일로 다운로드할 수 있는 모든 App Engine 마이그레이션 저장소에서 액세스할 수도 있습니다.
Codelab | Python 2 | Python 3 |
(코드) | ||
모듈 6 | (해당 없음) |
App Engine 리소스
다음은 이 특정 마이그레이션과 관련된 추가적인 리소스입니다.
- Python Cloud Datastore 및 Cloud Firestore 참조
- Python 3 및 GAE 차세대 런타임으로 마이그레이션
- 일반