넘겨받은 커머스의 GCP 자원을 리전별로 늘어놓자, 하나의 서비스가 세 나라에 걸쳐 있었다. 질문은 셋이었다. 왜 이렇게 퍼졌는가, 의도된 것인가, 국내로 모두 가져오면 비용과 동작이 어떻게 달라지는가. 셋 다 라이브 조회와 공시가로 답했고, 금액은 실청구가 아니라 Cloud Billing Catalog API 의 공시가 기준이다.
Table of contents
Open Table of contents
배경 — 한 요청이 대륙을 오가는 구조
라이브로 센 자원은 크게 세 무리였다.
- 미국 쪽 리전: 운영 GKE 클러스터(e2-medium 노드 9대, 디스크 18개 972GB), Firestore(미국 멀티 리전), Realtime Database, Cloud Functions 43개 중 42개, 운영 이미지 레지스트리
- 국내 리전: Cloud SQL(PostgreSQL), Memorystore Redis, 업무용 VM 8대 중 대부분
- 아시아의 다른 나라 리전: 결제용 PHP VM 한 대. 2016년에 만들어진 것이다
GCS 버킷 28개와 BigQuery 데이터셋 26개도 미국·국내·아시아 멀티 리전에 나뉘어 있었다. BigQuery 는 예전 세대 데이터셋이 미국에, 새 세대가 국내에 있었다. 결과적으로 미국의 GKE 에서 도는 앱 서버가 국내의 Cloud SQL·Redis 를 요청마다 오가는 구조가 이미 만들어져 있었다.
원인 — 의도된 결정의 기록은 없었다
「왜 미국인가」를 적은 결정 문서나 커밋 메시지는 찾지 못했다. 남은 것은 정황뿐이다. 리전이 섞인 시기가 한 달 안에 몰려 있다. 운영 GKE 클러스터는 미국에, 같은 달 며칠 뒤에 생긴 Cloud SQL·Redis·VM 은 국내에 있다. 배포 스크립트에는 미국 쪽 존이 REGION="…" 으로 하드코딩돼 있다.
정황으로는 두 해석이 모두 성립한다. 하나는 기본값 상속이다. Firebase 프로젝트가 2016년에 미국 기본값으로 만들어져 Firestore·Realtime Database·Functions 가 미국에 고정됐고, GKE 도 그 흐름을 따랐다는 해석이다. 다른 하나는 비용 선택이다. 미국 쪽 컴퓨트가 국내보다 약 22% 싼 것은 사실이지만, 같은 달에 DB 는 국내에 둔 것과는 잘 맞지 않는다. 그래서 의도 여부는 기록이 아니라 결정한 사람의 기억으로만 확인할 수 있다고 보고, 결정 질문으로 올렸다.
비용이 아닌 대가는 이미 실제로 나타나 있었다. 한 결제대행사가 국내 IP 만 자동으로 허용해, 미국 쪽 GKE 에서 직접 부르면 403 이 났다. 그래서 국내 VM 에 프록시를 따로 두어야 했다.
측정 — 지연과 비용
지연은 국내 사무실에서 미국 쪽 운영 로드밸런서로 같은 요청을 5번 보내 쟀다. TCP 연결은 4ms, TLS 완료는 1131ms 였다. 글로벌 로드밸런서가 국내 가까운 엣지에서 TLS 를 종단하기 때문이다. 그러나 첫 바이트는 192217ms 였다. 로드밸런서에서 미국 백엔드까지와 서버 처리에 약 180ms 가 든다는 뜻이다. 앱이 화면 하나에 API 를 여러 번 부르면 그 횟수만큼 이 지연이 쌓인다. 아시아의 결제 VM 은 직접 TCP 연결이 52ms 였다. 국내 원점으로 옮기면 첫 바이트가 수십 ms 로 줄 것으로 추정했지만, 국내 원점은 방화벽 때문에 같은 방법으로 직접 재지 못했다.
비용은 반대로 움직인다. E2 코어 단가가 국내가 약 28.5% 비싸고, 디스크도 비슷하게 비싸다. 운영 GKE 노드와 디스크만 옮겨도 월 비용이 오르고, Firestore 까지 옮기면 더 오른다. 이 인프라는 이미 월 비용을 줄이는 목표가 걸려 있어서, 국내로 모으는 일은 비용 목표와 정면으로 충돌한다.
판단 — 무엇을 옮길 수 있고 무엇을 못 옮기는가
옮기는 방식은 다음 세 가지 방법을 놓고 비교했다.
- 전부 국내로 모은다
- 지금 그대로 둔다
- 옮기기 쉬운 것부터 점진적으로 옮긴다
1번은 시작하기 전에 막힌다. 옮길 수 없거나, 옮기면 클라이언트가 바뀌는 자원이 많다. Firestore 의 위치는 만든 뒤 바꿀 수 없고, Realtime Database 인스턴스의 위치도 그렇다. GCS 버킷의 이름과 위치, BigQuery 데이터셋의 위치, 리전에 묶인 고정 IP, Cloud Functions 의 호출 URL 은 옮기면 그것을 부르는 쪽을 모두 바꿔야 한다. 반면 가장 쉬운 것은 GKE 다. 글로벌 로드밸런서 뒤에 국내 백엔드를 더해 트래픽을 조금씩 옮기면, 클라이언트는 바뀌지 않는다.
3번이 맞다고 본 이유는 비용만으로는 이동을 정당화할 수 없고, 지연과 결제대행사의 국내 IP 제약을 푸는 것이 이유일 때만 의미가 있기 때문이다. GKE 를 국내로 옮기면 앱 서버와 국내 Cloud SQL·Redis 사이의 대륙 간 왕복은 없어지지만, 미국에 남는 Firestore·Realtime Database 와의 왕복은 반대로 새로 생긴다. 그래서 어느 호출이 더 많은지를 먼저 재야 이득이 정해진다. 대가는 GKE 를 옮기는 만큼 월 비용이 오른다는 점이다. 그래서 이동 여부는 「지연을 얼마나 줄이는 것이 그 비용만큼의 가치가 있는가」라는 사업 판단으로 남겼다.
결과 — 비용과 지연을 함께 올린 사업 판단
- 판단의 형태. 「국내로 모은다」를 기술 작업이 아니라 「지연을 줄이는 가치가 오르는 비용만큼인가」라는 사업 판단으로 바꿔 올렸다
- 계획의 경계. 위치가 영구인 Firestore·Realtime Database 와 옮기면 주소가 바뀌는 자원을 먼저 세어, 옮길 수 있는 것(GKE)과 없는 것을 갈랐다
- 남긴 질문. 리전이 섞인 이유를 적은 기록은 찾지 못했다. 결정한 사람의 기억을 묻는 질문으로 남겼다
정리
- 리전이 섞인 인프라는 먼저 자원을 리전별로 센다. 한 요청이 어느 대륙을 몇 번 오가는지가 거기서 보인다
- 「왜 이렇게 됐나」는 기록에서 찾고, 없으면 정황을 두 해석으로 나눠 적은 뒤 결정한 사람에게 묻는다
- 지연은 연결·TLS·첫 바이트로 나눠 잰다. 글로벌 LB 가 TLS 를 가까이서 끝내도, 백엔드까지의 거리는 첫 바이트에 그대로 남는다
- 옮기기 전에 옮길 수 없는 것부터 센다. 위치가 영구인 데이터 저장소와, 옮기면 클라이언트가 바뀌는 주소가 계획의 경계를 정한다