어느날 눈을 떠 보니 내 잔고가 0??

어늘날 갑자기 들려온 메일알림에 휴대폰을 확인해보니 천문학적인 숫자가 담긴 GCP 청구서를 받아들게 된다.
알고보니 사이드프로젝트로 만들어서 GCP 에 올려두었던 앱이 반응이 좋아 수많은 사람들의 무수한 리퀘스트를 받은 덕분에 학부생으로써는 감당하기 어려운 인스턴스 금액이 청구되어 버린 것!

image

겉보기에는 몇천원 밖에 안되는 금액이지만, 예상 사용자의 약 10% 정도만이 접속했을때의 비용청구 결과였다. 이 추세라면 프로젝트가 정상적인 궤도에 오를 경우 한달에 약 70,000KRW 가 청구 될 것으로 예상되었다.
만약 목표에 모자라는 규모더라도 한달에 4~5만원씩은 꾸준히 인스턴스 비용으로 나갈 것이라는게 팀원들과 회의 끝에 낸 결론이었다.

비록 얼마 안되는 금액일 듯 하지만, 별다른 고정수입이 없는 대학생들에게는 돈 한푼도 아쉬운 상황에서 월 4~5만원, 많게는 8만원은 꽤 큰 금액이었다.

목표 사용자 수에 도달하는 것 자체는 어려운 일이 아니라고 판단되고 근시일 내에 달성이 예상되고 있어서 청구되는 비용을 효과적으로 관리하는 것이 최우선 과제가 되었다.

발단

비용 리포트 분석 결과 백엔드 API 서버로 굴리던 App Engine 의 사용량이 가장 큰 원인인 것으로 나타났다. 그 중에서도, 청구단위가 사용시간에 따른 비용청구 형태라 한두것의 리퀘스트에도 상시로 켜져있게 되어 거의 24/7 으로 구동되었던것으로 추측된다.
image

전개

지도교수님과도 면담을 해 보았지만, 근 시일내에 뾰족한 해결책을 떠올리지 못했다. 결국 API 서버를 통으로 들어내고, 모든 정적 데이터를 Cloud Storage Bucket 으로 이전한 다음, 지금의 API 서버가 하던 로직을 클라이언트에 이식하는것이 그나마 효과적이라는 결론에 도달했다. 다른 선배님들께 질문을 드려봤지만 이 방법이 가장 효과적이고 효율적이라는 의견이 지배적이었다.

Cloud Storage 로 데이터 이전

일단 백엔드 GCP 프로젝트에 있던 파일들을 모두 프론트엔드쪽 GCP 프로젝트로 이전하는 작업을 진행했다. 이 작업을 마치면 실질적으로 백엔드 프로젝트는 별다른 액션이 없으므로 인스턴스를 지우고 프로젝트를 내릴 생각이다.

Bucket Storage 생성

먼저 GCP 메뉴 중, Storage 로 들어와서 새 버킷을 하나 생성해준다.
옵션은 다음과 같이 설정해 주었다.
screencapture-console-cloud-google-storage-create-bucket-2020-08-16-15_51_06

  • 전세계적 서비스를 할 것은 아니기 때문에 Region-단일리전내 짧은 지연시간 옵션을 선택하였다.
  • 위치는 당연히 서울리전.

    하지만 App Engine 인스턴스를 만들땐 서울리전이 없어서 도쿄리전에 생성했었다는건 안비밀.. 이 때문에 다른 리전간 네트워크 전송비용을 고민해봐야 했나 싶었는데, 십 몇 KB에 불과한 파일사이즈 정도면 큰 의미는 없는 수준이라서 신경쓰지 않아도 될 정도라고 판단했다.

  • 스토리지 클래스는 Standard.

이후 완료를 눌러 빠져나오면 다음과 같다.
image

Storage Bucket에 파일 추가 및 권한 부여

이제 만들어진 버킷에 들어가서 파일을 업로드한다. 하지만 이 상태로는 외부에서 익명의 사용자가 업로드한 파일에 접근할 수 없다.

모든 사용자가 읽을 수 있도록 다음 사진과 같이 “저장소 기존 개체 리더 역할에 “allUsers 를 입력해준다.

image

  • “저장소 기존 개체 리더” 와 “저장소 이전 버킷 리더” 의 차이점
    • 저장소 기존 개체 리더 : 표시가 포함되지 않은 개체에 대한 읽기권한 -> 다른 파일이 어떤게 있는지 알지 못함
    • 저장소 이전 버킷리더 : 개체표시를 포함한 버킷에 대한 읽기권한 ->
      다른 파일이 어떤게 있는지 조회 가능

공개된 URL을 통해 버킷에 접근했을 때 에러가 발새안 경우 xml 형태로 응답이 전달된다. 이 경우 버킷에 대한 전체 리더 권한이 있을 경우 다른 해당 버킷에 모든 객체에 대한 조회가 가능하므로 주의해야한다.

위기

버킷생성도 완료했고, 다 끝난 것 같았지만, 욕심이 좀 더 생겼다.
storageapi.google.com/~~~ 어쩌구 하는 기본 URL 말고, api.lorem.ipsum 과 같은 간지나는 서브도메인을 부여하고 싶었다.

이를 위해서 VPN네트워크 메뉴에서 고정IP를 할당받고, 네트워크 서비스 메뉴에서 부하분산기(Load balancer)를 생성했다.(알고보니 여기에서도 적접 고정IP주소를 할당받을 수도 있다.)
image
백엔드 구성 에서 이전에 만들었던 버킷을 추가하고,

image
프런트 엔드 구성 에서 IP와 프로토콜,인증서를 설정했다. 인증서의 경우 새 인증서를 만들고 Google Managed 방식을 선택했다.

image

최종적으로 Cloud CDN에 방금 만든 LB를 붙여주면 끝.
이렇게 아름다운 도메인과 api 서버를 완성했다.

적어도 아직까지는 그렇게 보였다.

절정

효과는 대단했다!!
아무래도 이번 포스팅의 제목을 바꿔야 할 것 같다.

자고일어났더니 GCP 청구금액이 ‘15000%’가 되어버렸다

image

전체 트래픽은 줄었는데 오히려 LB를 붙인 덕분에 전체적인 비용은 훨씬 더 늘어났다.
회사에서도 플랫폼 담당하시는 분들이 하시던 말씀을 기억해보니 AWS쪽 도 LB 개당 단가 책정이 “흉흉”해서 가능한 최소한으로 줄이는 방법을 찾고 계시던데, 역시 GCP또한 그런것 같다.
사실 우리가 캐싱 정책을 유연하게 걸어둔 것도 아니라서(기억하기로는 3600초…) 서비스 특성상 캐싱은 거의 무의미했던것도 한 몫을 했다. 매 요청마다 캐시가 만료되었으니 새 데이터를 요청했던 것이다.

결국 LoadBalancer와 CDN은 들어내고, 클라우드스토리지 api url을 이용하는 쪽으로 방향을 잡았다.

결말

image

다행히도 요즘은 계절학기도 모두 끝난 방학시즌이라 실제 일 사용자는 거의 없는 편이다. 우리로써는 일종의 유지보수에 올인하고 새 기획을 할수 있는 좋은 시기에 이런 고민을 할 수 있어서 다행이었다.

API 서버를 들어내고, Storage Bucket 으로 서비스 데이터를 옮긴 것 자체는 꽤 유효했다. 비용그래프를 다시 들여다 보면, 드라마틱한 차이가 있는 것을 알 수 있다.
사실 요즘같은 방학기간에 쓰는사람은 거의 없지만, 인스턴스만 주구장창 돌아가는것은 상당히 비효율 적인 일이다. 여러모로 API 서버를 반갈죽 낸 것은 유효한 판단이었다고 생각한다. 스토리지 자체 비용은 사용자가 많지 않은 요즘 기준 몇십원 수준이고, 학기가 개강한 뒤에도 이전 App Engine 인스턴스 때와는 비교도 안될만큼 저렴할 것이다.

그밖에도 청구내역에 Stiatic IP Charge 항목으로 천 얼마가 붙어있는데, 이건 지난번에 Load Balancer 를 들어내는 과정에서 깜빡하고 IP등록 했던걸 해제하지 않아서 약 5일분의 사용료가 청구되었다.. 🤔🤔🤔

데이터 업데이트는 다음글에서 다룰 Cloud Builder 를 이용하여 자동을 버킷 내용을 백업하고, 업데이트 하도록 설정하였다.

쏘아올린 커밋, CloudBuilder가 볼까? Storeage Bucket이 볼까?

정리

  • Before

    • API서버 : App Engine Instance
  • After

    • API서버 : 반갈죽 🔪👊🔪👊
    • 신설 : Google Storage Bucket(Master, Backup)
  • Result

    • 큰 폭의 비용절감(약 10000%…)