![[실전 서버리스 21] 비용 폭탄 피하기, 청구서에서 배운 것](https://img.thenullpage.com/posts/5624/5624_1_f9b42d.webp)
서버리스는 저렴하다고 계속 말했지만, 방심하면 비용이 튄다. 잘못된 설계 하나가 예상 못 한 청구서로 돌아올 수 있다. 나도 데이터베이스 읽기 폭증으로 한도에 부딪혀본 적이 있다. 이번 편은 서버리스에서 비용이 튀는 경우들과, 그걸 피하는 법을 실전 경험으로 정리한다.
비용 관리는 개인 프로젝트의 지속 가능성을 좌우한다. 어느 날 큰 청구서에 놀라지 않으려면, 어디서 비용이 튀는지 미리 알고 대비해야 한다.
1. 데이터베이스 읽기 폭탄
가장 흔한 비용 폭탄이 데이터베이스 읽기다. 앞서 여러 편에서 다뤘듯, 인덱스 없는 쿼리가 큰 테이블을 통째로 스캔하면 읽기량이 폭증한다. 여기에 봇 트래픽이 겹치면 그 비효율적 쿼리가 수만 번씩 실행되어 폭탄이 된다. 내가 실제로 겪은 게 이거였다.
이걸 막는 건 앞서 다룬 최적화들이다. 인덱스로 각 쿼리를 가볍게 하고, 캐시로 읽는 횟수를 줄이고, 봇의 무한 페이지를 막는다. 이 세 가지가 함께 작동하면 데이터베이스 읽기가 극적으로 준다. 데이터베이스 비용 폭탄은 대부분 이 최적화로 막을 수 있다. 읽기가 곧 돈이라는 걸 늘 의식하는 게 시작이다.
중요한 건 이걸 사고가 나기 전에 하는 것이다. 나는 폭증을 겪고서야 최적화를 했는데, 미리 인덱스와 캐시를 갖췄다면 그 사고를 안 겪었을 것이다. 데이터가 적을 때는 비효율적 쿼리도 티가 안 나지만, 데이터와 트래픽이 늘면 갑자기 폭탄이 된다. 그래서 처음부터 인덱스와 캐시를 염두에 두는 게 좋다.
데이터베이스 읽기가 가장 흔한 비용 폭탄이다. 인덱스 없는 쿼리가 큰 테이블을 스캔하고 봇 트래픽이 겹치면, 그 비효율적 쿼리가 수만 번 실행돼 폭탄이 된다. 이걸 막는 건 인덱스와 캐시, 봇 방어다. 데이터가 적을 땐 티가 안 나지만 늘면 갑자기 폭탄이 되니, 처음부터 이 최적화를 염두에 두는 게 좋다.
조금 더 배경을 주면, 비용 관리는 개인 프로젝트의 지속 가능성을 좌우한다. 아무리 좋은 사이트도 매달 큰 비용이 나가면 유지가 안 된다. 그래서 어디서 비용이 나는지 알고 관리하는 능력은 기능 개발만큼 중요하다. 오래 살아남는 사이트는 대개 비용 관리를 잘한 사이트다. 저렴하게 유지하는 것도 실력이다.
2. 무거운 연산의 비용
무거운 연산도 비용을 키운다. CPU를 많이 쓰는 작업을 사용자 요청 안에서 처리하면, 그 요청의 CPU 시간이 길어져 과금이 늘고 한도에 가까워진다. 이미지 처리나 복잡한 계산 같은 걸 요청마다 하면 비용이 쌓인다.
이건 앞서 다룬 큐로 해결한다. 무거운 연산을 큐로 넘겨 뒤에서 처리하면, 사용자 요청 자체는 가볍게 유지된다. 급한 것과 안 급한 것을 나누는 것이다. 무거운 후처리는 뒤로 미루고, 사용자 요청은 최소한만 처리해 빠르고 저렴하게 유지한다. 비동기 설계가 비용 관리이기도 한 것이다.
또 무거운 연산은 반복하지 않게 결과를 캐시한다. 같은 계산을 매번 다시 하면 낭비니, 한 번 한 결과를 저장해 재사용한다. 앞서 정기 작업으로 미리 계산해두라고 한 것도 이 맥락이다. 비싼 연산은 한 번만 하고 그 결과를 여러 번 쓰는 게 비용을 아끼는 길이다.
무거운 연산도 비용을 키운다. CPU를 많이 쓰는 작업을 요청 안에서 처리하면 CPU 시간이 길어져 과금이 는다. 이건 큐로 뒤에 미뤄 사용자 요청을 가볍게 유지해 해결한다. 또 비싼 연산은 결과를 캐시해 반복하지 않는다. 급한 것과 안 급한 것을 나누고, 비싼 계산은 한 번만 하는 게 비용 관리의 요령이다.
3. 저장소 비용
저장소도 비용이 쌓이는 곳이다. R2의 egress는 0이지만 저장 자체는 과금된다. 파일이 계속 쌓이면 저장 비용이 는다. 특히 앞서 다룬 고아 파일이 방치되면, 쓰지도 않는 파일에 저장 비용을 내게 된다. 이 낭비를 막으려면 고아 파일 정리가 필요하다.
또 파일을 무겁게 저장하면 그만큼 비용이다. 원본 이미지를 그대로 저장하기보다 적절히 압축해 저장하면 용량이 줄어 비용도 준다. 앞서 미디어 편에서 다룬 최적화가 저장 비용에도 기여한다. 화질과 용량의 균형을 맞춰, 필요 이상으로 무거운 파일을 저장하지 않는 것이다.
데이터베이스 저장도 마찬가지다. 안 쓰는 오래된 데이터가 계속 쌓이면 저장 비용이 는다. 그래서 정기적으로 오래된 임시 데이터를 정리한다. 앞서 크론으로 정리 작업을 돌리라고 한 게 이 맥락이다. 쌓이는 걸 주기적으로 치워 저장 비용을 관리하는 것이다.
저장소도 비용이 쌓이는 곳이다. R2의 egress는 0이지만 저장 자체는 과금되고, 고아 파일이 방치되면 쓰지도 않는 파일에 비용을 낸다. 그래서 고아 정리와 파일 압축, 오래된 데이터 정리가 저장 비용을 관리한다. 앞서 다룬 여러 정리 작업이 결국 비용 관리와 이어지는 것이다. 쌓이는 걸 치우는 게 비용을 아낀다.
조금 더 실무적으로, 비용 폭탄은 대부분 예방 가능하다. 데이터가 적을 때 미리 인덱스와 캐시를 갖추고, 무거운 건 큐로 넘기고, 쌓이는 건 정기적으로 치우면 폭탄이 안 생긴다. 나는 폭증을 겪고서 배웠지만, 이 시리즈를 읽는 사람은 그 아픔 없이 미리 대비할 수 있다. 예방이 사후 대응보다 훨씬 싸다.
4. 측정하고 감시한다
비용 폭탄을 막는 근본은 측정과 감시다. 어디서 얼마나 비용이 나는지 모르면 관리할 수 없다. 플랫폼이 제공하는 사용량 대시보드로 데이터베이스 읽기, 코드 실행, 저장소 사용량을 주기적으로 확인한다. 어느 항목이 갑자기 튀면 그게 폭탄의 신호다.
특히 갑작스러운 증가를 감시하는 게 중요하다. 평소와 다르게 어느 지표가 치솟으면, 새로 배포한 코드에 비효율이 생겼거나 봇 트래픽이 몰렸을 수 있다. 이걸 빨리 발견해 원인을 찾으면 폭탄이 커지기 전에 막는다. 나도 데이터베이스 읽기가 튀는 걸 대시보드에서 보고 대응했다.
이건 앞서 SEO 시리즈부터 반복한 감이 아니라 데이터라는 원칙과 같다. 비용도 감으로 관리하는 게 아니라 지표를 보며 관리한다. 어느 쪽에서 비용이 나는지 측정하고, 튀는 걸 감시하고, 원인을 찾아 최적화한다. 이 측정 습관이 비용 폭탄을 예방하는 가장 확실한 방법이다.
측정하고 감시하는 게 비용 폭탄을 막는 근본이다. 사용량 대시보드로 데이터베이스 읽기, 코드 실행, 저장소를 주기적으로 확인하고, 어느 지표가 갑자기 튀는지 감시한다. 튀는 걸 빨리 발견하면 폭탄이 커지기 전에 막는다. 비용도 감이 아니라 데이터로 관리한다는, 이 시리즈 내내 반복한 원칙이 여기서도 적용된다.
5. 한도를 안전망으로
플랫폼이 제공하는 한도나 알림을 안전망으로 쓸 수 있다. 사용량이 일정 수준을 넘으면 알림을 받게 설정해두면, 비용이 튀기 시작할 때 바로 안다. 모르는 사이 폭탄이 커지는 걸 막는 것이다. 무료 요금제의 한도 자체가 안전망이 되기도 한다. 한도를 넘으면 멈추니, 모르는 새 큰 비용이 나가는 걸 막는다.
중요한 건 비용을 두려워해 서버리스를 피할 필요는 없다는 것이다. 제대로 설계하면 서버리스는 매우 저렴하다. 비용 폭탄은 대부분 비효율적 설계와 감시 부재에서 온다. 최적화하고 측정하고 감시하면, 서버리스의 저렴함을 온전히 누릴 수 있다. 폭탄은 관리 실패의 결과지 서버리스의 본질이 아니다.
정리하면 비용 폭탄은 데이터베이스 읽기, 무거운 연산, 저장소에서 주로 나고, 최적화와 큐와 정리로 막으며, 측정과 감시와 한도 알림으로 예방한다. 다음 편은 이 시리즈의 마지막으로, 페이지스에서 워커스로 옮기는 이야기, 언제 어떻게 이전하는지를 다룬다.
한도와 알림을 안전망으로 쓰면 든든하다. 사용량이 일정 수준을 넘으면 알림을 받게 해두면, 비용이 튀기 시작할 때 바로 안다. 무료 요금제의 한도 자체가 안전망이 되기도 한다. 중요한 건 비용을 두려워해 서버리스를 피할 필요는 없다는 것이다. 제대로 설계하면 서버리스는 매우 저렴하고, 폭탄은 관리 실패의 결과일 뿐이다.
또 하나, 비용 폭탄을 한 번 겪으면 오히려 좋은 습관이 생긴다. 어디서 비용이 나는지 민감해지고, 쿼리를 짤 때마다 이게 비쌀까를 먼저 생각하게 된다. 나도 폭증을 겪은 뒤로 데이터베이스를 대하는 태도가 달라졌다. 아프게 배운 교훈이 오래 남듯, 비용 관리도 한 번 데이면 확실히 몸에 밴다.
다음 편은 이 시리즈의 마지막으로, 페이지스에서 워커스로 옮기는 이야기와 시리즈 전체를 관통하는 결론을 정리한다. 스물두 편의 서버리스 여정을 마무리하는 편이다.