안녕하세요 주간SaaS 입니다.
오늘은 11 years of hosting a SaaS 라는 제목의 글을 소개 합니다. 11년 동안 SaaS 서비스를 운영하며 거쳐온 플랫폼의 변화 과정을 솔직하게 쓴 글입니다. 본문에 특정 클라우드 서비스명이 거론되지만 이름에 집중하기 보다 이 글을 작성한 Tanda의 팀 스스로가 느끼고 배워온 부분을 집중하면 좋겠습니다🎅🏻
개인적으로 시스템 부재로 인해 담당자 oncall로 꾸역꾸역 무장애 서비스를 이어갔던 과거가 생각나 공감하며 읽었습니다.
그럼 오늘 하루도 즐거운 하루되세요!
Tanda가 곧 11살이 됩니다. 한 독자가 그 동안 인터넷에서 앱을 운영하면서 배운 것들을 되돌아보는 것도 재미있을 것 같다고 제안했습니다.
배포, 호스팅, 인프라 관리가 제가 10년 동안 일하면서 가장 어렵고 답답했던 부분이었기 때문에 오랫동안 이 글을 썼습니다. 그 이유는 대부분 제가 끊임없이 깊이 파고들다 보니 제가 무엇을 하고 있는지 모르는 경우가 많았기 때문입니다. 안타깝게도 많은 사람이 사용하는 프로덕션 앱을 만들다 보면 제대로 배울 시간이 항상 있는 것은 아닙니다.
이 글은 저희가 지나온 몇 가지 단계에 대한 이야기로, 여러분도 저희와 같은 길을 걷고 있다면 몇 가지 최악의 상황을 피할 수 있기를 바라는 마음으로 작성되었습니다.
1단계: Heroku
2012년에 앱 배포가 포함된 Ruby on Rails 튜토리얼을 완료하면 Heroku 계정이 생겼기 때문에 Heroku에서 서비스 개발을 시작했습니다.
Heroku의 사용 편의성은 타의 추종을 불허했습니다. 하지만 웹 앱을 배포해 본 적이 없는 사람에게는 큰 의미가 없었습니다. 사람들이 앱을 배포하는 가장 간단한 방법이라고 생각한다는 것은 알고 있었지만, 이전보다 얼마나 크게 개선되었는지 이해하지 못했습니다.
오히려 Heroku의 몇 가지 약점을 이해하게됐습니다.
- 규정(Prescriptiveness)
- 비용(Costs)
규정(Prescriptiveness)
Heroku는 의도한 대로만 사용한다면 매우 잘 작동했습니다. 저희의 데이터베이스, 백그라운드 워커, 캐시가 있는 웹 앱이 그 의도에 거의 접근해 있었습니다.
다만 한 가지 차이점이 있었는데, 우리 앱은 가끔 느린 클라이언트(신호가 좋지 않은 곳에서 실행되는 휴대폰이나 태블릿)의 긴 요청(파일 업로드)을 처리해야 한다는 점이었습니다. 모바일 파일 업로드를 개척한 것은 아니지만, 이를 처리하도록 Unicorn을 구성하는 올바른 방법이 기본값과 너무 달라서 고민이 많았습니다. 웹 애플리케이션 배포에 대해 아무것도 몰랐기 때문에 저는 이것이 Heroku의 잘못이라고 결론내렸습니다.
지금은 조금 더 잘 알게 되었고 그들이 하려고 했던 일의 어려움과 복잡성을 이해할 수 있게 되었지만, 앱 배포에 필요한 모든 것을 제공한다는 그들의 엘리베이터 피치를 너무 문자 그대로 받아들인 것은 저 혼자만의 생각은 아니었던 것 같습니다.
(*🐶저자가 Prescriptiveness 라는 표현을 사용한 이유는, Heroku가 서비스가 규정한 방법이 매우 구체적이지만 그것을 벗어나지 못하는 엄격함이 있어 저자가 원하는 방식으로 사용하지 못했기 때문으로 생각 됩니다. 즉 Heroku는 너무 규범적이었다 라고 하는것 같습니다)
비용(Costs)
Heroku는 자체 VPS(가상 사설 서버)를 운영하는 것과 같은 대안들 보다 훨씬 더 많은 비용이 들었습니다. 물론 - 그만큼 더 많은 일을 했죠! 하지만 제가 직접 무언가를 배포하는 것이 처음 이었기 때문에 그 뒤에 숨은 가치를 제대로 평가하지 못했고, 대안들과 비교할 때 단지 높은 Heroku 비용의 크기만 보았습니다.
이것은 오늘날 Rails를 처음 접하는 사람과 옛날에 Java나 다른 언어에서 사용하다가 Rails로 넘어온 사람의 경험 차이와 비슷할 것이라고 생각합니다. 예전과 비교했을 때 얼마나 더 좋아졌는지에 대한 평가는 같지 않을 것입니다. 다행히도 요즘에는 풀스택 자바스크립트 앱을 빌드한 다음 다시 Rails로 돌아와서 같은 감동을 쉽게 얻을 수 있습니다.
어쨌든 비용 때문에 결국 Heroku에서 마이그레이션하게 되었습니다. 마지막 Heroku 청구서는... $104.95였습니다.🤦♂️
2단계: Digital Ocean
Tanda에 입사한 지 1년쯤 되었을 때 인프라 및 비용 최적화에 관심이 많았던 대학생 인턴이 있었습니다. 그는 기본적으로 Heroku에 돈을 지불하는 것은 돈을 불태우는 것과 같다고 저를 설득했습니다. 그는 정말 멋진 사람이었고 당시에는 그의 도움이 정말 감사했지만, 솔직하게…10년이 지난 지금 생각해보면 그건 끔찍한 조언이었다고 말할 수 있습니다(그 조언을 들었던 제 책임도 있습니다).
Heroku를 떠난다는 것은 Heroku가 제공하던 모든 부분을 교체한다는 것을 의미했습니다. 저희는 규모가 작았기 때문에 완전히 자동화된 방식으로 교체하지 못했습니다! 저희는 규모가 너무 작아서 그럴 필요가 없었어요. 대신 Digital Ocean의 UI에서 서버를 가리키고 클릭 하기만 하면 되었습니다. 그런 다음 서버에 배포할 Capistrano 스크립트를 설정했습니다. 주말 동안 엄청나게 짧은 시간 동안 사이트를 오프라인으로 전환하고 Heroku에서 데이터베이스를 다운로드하여 Digital Ocean의 "droplet"(일명 서버)에 업로드한 후 DNS 레코드를 변경했습니다. 마이그레이션이 완료되었습니다!
첫 번째 Digital Ocean 청구서는 $28.93이었고, 두 번째 청구서(첫 달 전체)는 $39.23이었습니다. 하루에 2달러씩 절약하는 것이 정말 현명 하다고 생각했습니다. 한동안은 괜찮았지만, 아주 작은 앱을 실행하는 데 사용하는 월 $40으로 훨씬 더 많은 서버를 구입할 수 있다는 것을 알게되었습니다.
하지만 회사가 빠르게 성장하기 시작하면서 균열이 보이기 시작했습니다. 9개월마다 고객 기반 규모가 두 배로 늘어나면서 곧 더 많은 서버가 필요하게 되었습니다. 서버를 추가하는 과정은 수동적이고 까다롭고 그리고 실수하기 쉬웠습니다. 방법을 알아냈지만 '하드웨어'를 추가할 때 마다 항상 속이 불편했습니다.
데이터베이스 서버에 과부하가 걸리기 시작하면서 균열이 실제로 나타나기 시작했습니다. 사이트를 하루 이상 배포하지 않으면 Postgres의 메모리가 부족해져 운영 체제에 의해 종료되는 일이 거의 매일 반복되었습니다. 저절로 해결되는 경우도 있었지만, 누군가가 앱 서버에 SSH로 접속하여 모든 서버를 다시 시작해야 하는 경우가 더 많았습니다. 업무 시간 중에는 성가신 일이었지만, 그 시간 동안 술집 화장실에서 휴대폰으로 서버를 다시 시작했던 기억이 몇 번이나 있습니다.
하지만 Digital Ocean에서 겪은 최악의 사건은 모든 거래가 한꺼번에 정지된 일이었습니다. 계정에 입력한 신용 카드가 만료되어 백업 카드를 입력할 방법이 없었고, 계정의 연락처 이메일이 모니터링되지 않는 공유 받은 편지함으로 전송되었습니다. 그래서 한 달 정도는 청구 알림을 받고도 무시하다가 모든 것이 오프라인 상태가 되었고, 결국 SSH 접속이 안돼서야 알게되었습니다. 전적으로 Digital Ocean의 잘못은 아니었지만 당시에는 모든 것이 불안정하고 흔들리는 환경에서 운영하는것 처럼 느껴졌습니다.
거의 10년이 지난 지금 이 글을 쓰다 보니 우리가 얼마나 아무것도 몰랐는지 충격적이기도 하고, 무사히 넘긴 것이 기적처럼 느껴지기도 합니다. 저에게 타임머신이 있다면 돌아가서 Digital Ocean에 10배 더 많은 돈을 쓰고(한 달에 $500은 정말 큰돈이 아니었겠죠) 제대로 잠을 자라고 말하고 싶어요.
Digital Ocean에서 약 3년을 사용한 후, 저희는 Digital Ocean이 너무 단순해서 증가하는 요구사항에 대응하기 어렵다고 판단했습니다. 더 큰 규모의 고객을 유치하기 시작했고, 앱 호스팅에 좀 더 진취적인 접근 방식이 필요하다고 생각했습니다. 저희는 자체 Postgres 서버를 관리하는 대신 관리형 데이터베이스를 원했습니다. 플랫폼 다운타임을 줄이고 싶었습니다. 수요 변동에 따라 자동 확장할 수 있어야 했고, 다양한 리소스 그룹(... 모노레포)에 대한 다양한 경로를 로드 밸런싱할 수 있어야 했습니다. 저희는 이것들이 꼭 필요했습니다.
하지만 지금 돌이켜보면, 대부분의 이러한 생각은 잘못된 것이었습니다. 자동 스케일링은 AWS만의 제품이 아니라 기술이며, 더 많은 도전을 찾기보다는 우리가 완전히 이해하고 사용할 수 있는 충분히 단순한 플랫폼을 찾는 것이 더 나았을 겁니다. (물론, 관리형 데이터베이스에 대한 생각은 좋았지만요.)
Digital Ocean을 떠나야 했던 유일한 합리적인 이유는 호주에 데이터 센터가 없었기 때문이었고, 이를 중요하게 생각하는 고객들이 있었기 때문입니다. 당시에는 2022년 말 출시가 임박해 있었습니다. 그래서 그 때까지 기다리지 않기를 잘한 거죠.
어쨌든. 저희는 레벨업이 필요했습니다. 만약 여러분들이라면 호스팅 환경을 레벨 업 한다면 누굴 찾을 건가요?
3단계: AWS
우리는 진짜 비즈니스가 되어야 했고, 우리의 진짜 비즈니스는 AWS에서 호스팅 되었습니다. 정확히 말하면 Digital Ocean 인프라를 그대로 AWS EC2로 포팅했습니다. AWS의 다른 기능을 활용하지 않고 AWS를 다른 VPS처럼 취급했습니다.
몇 달 후 저희를 지원하는 AWS account manager(*🐶고객 담당 영업사원)가 있다는 사실을 알게 되었습니다. 소개를 해준 고객으로부터 이 사실을 알게 되었습니다. account manager가 있으면 우리가 매우 빠르게 성장하고 확장하는데 도움을 줄 수 있을 거라고 생각해 기뻤습니다.
첫 미팅에서 어카운트 매니저는 솔루션 아키텍트(*🐶고객 담당 기술 지원 엔지니어)를 데려왔습니다. 저는 솔루션 아키텍트를 만나본 적이 없어서 어떤 일을 하는지 잘 몰랐어요. 이 사람은 우리가 묻는 모든 질문에 "서버가 없는 세상에서 어떻게 작동할까요?"라고 대답하기만 했어요. AWS 람다가 어떻게 도움이 되는지도 잘 몰랐고(지금도 잘 모르지만), 람다의 존재를 상기시켜주는 것 외에는 별다른 기여를 하지 못했습니다. 어카운트 매니저가 생긴다는 사실에 너무 들떠 있었기 때문에 한동안은 람다를 이해하지 못하고 AWS를 활용할 만큼 똑똑하지 못한 자신이 바보 같다고 느꼈죠. 결국 문제가 제게 있지 않다는 걸 깨달았어요.
약 1년 후에 있었던 또 다른 재미있는 사건은 정수(Integer)가 부족했던 것이었습니다. 저희 Rails 앱은 꽤 오래되었고 거의 모든 테이블이 기본 키 유형으로 정수(Integer)를 사용했습니다. 최신 버전의 Rails는 새로운 테이블을 bigints 만들었지만, 팀원 중 아무도 이것이 문제라는 것을 깨닫지 못했고, 그러다가 어느 금요일(이건 지어낸 이야기가 아니에요 - 바로 13일의 금요일이었죠!)에 가장 자주 쓰이는 테이블에 새로운 행을 삽입할 수 없게 되었습니다. 다행히도 모두가 아직 사무실에 남아서 술을 마시고 있었기 때문에 사고에 신속하게 대응할 수 있었습니다. (이 이야기가 정말 공감이 갑니다)
이 사건을 계기로 모니터링에 더 많은 노력을 기울여 문제가 발생했을 때 더 신속하게 대응할 수 있게 되었습니다. 또한, 이 사건으로 인해 평생 동안 완전히 떨쳐버릴 수 없었던 PostgreSQL의 다른 숨겨진 문제점에 대한 편집증을 갖게 되었습니다(이것이 희망인지 아닌지는 잘 모르겠습니다).
최근 AWS 기반의 주요 프로젝트는 대부분 규정 준수와 관련된 것이었습니다. GDRP 및 이에 상응하는 다른 국가의 모든 규정을 체크하는 것이 SOC-2 인증 획득으로 이어졌습니다. 이 과정에서 Amazon 로고를 사용할 수 있다는 것이 약간은 일을 쉽게 만들었지만(*🐶관련 규정 준수 AWS 서비스를 사용한 덕분에 인증 과정이 수월 했다는 의미로 추측됩니다), 특정 클라우드에 있다고 해서 우리가 하고자 하는 모든 일이 가능하거나 불가능한 것은 아닙니다.
AWS를 사용한 지 몇 년이 지나면서, 우리는 인프라 면에서 안정적이라고 느꼈습니다. 우리는 오랫동안 시스템 구조를 개편하지 않았고, 굳이 그럴 필요도 없다고 생각했죠. 하지만 우리가 마주친 다음 큰 문제는 기술적 지식의 부족이었습니다. Tanda에서 'DevOps'라는 분야에서 일한 사람은 10명도 채 되지 않았어요. 사람들은 들어오고 나가는 법이죠. 당시 2명이 있었고, 한 명은 곧 떠날 예정이라, 팀 안에 단 한 명의 사이트 신뢰성 엔지니어(SRE)만 두는 건 그리 매력적으로 느껴지지 않았습니다.
SRE들이 완전히 혼자서 일한 것은 아니었습니다. 우리는 엔지니어들을 위한 oncall 교대를 오래전부터 해왔지만, Rails 앱 이외의 복잡한 시스템 부분에 대한 교육은 잘 이루어지지 않았습니다. 그 결과 oncall 담당자들은 대부분의 시간을 경보에 응답하고 모니터링 하는데 보냈지만, 실제로 문제에 보다 깊숙이 파고들어 결국 해결하거나 시스템을 크게 개선하는 일은 드물었습니다.
결국, 이 시스템은 마치 실과 개인의 간헐적인 뛰어난 노력에 의존하는 것처럼 느껴졌습니다. 이런 모습은 장기적인 전략 측면에서 바람직하지 않았습니다. 저희는 어떤 문제든 한 사람의 손에 의존하지 않고, 모든 이슈를 디버깅할 수 있는 제대로 된 팀 구조가 필요했습니다.
4단계: 플랫폼 인프라 팀 (PIT)
이를 위해 약 1년 전에 CTO에게 보고하는 플랫폼 인프라 팀을 만들었습니다. 이 팀은 각 시간대별로 여러 명의 사람들로 구성되어 있어, 운영, 인프라 및 관련 업무에 24시간 대응할 수 있었습니다.
이것은 개인적으로 큰 하이라이트였습니다 - 드디어 온콜에서 벗어날 수 있었죠!
또한, 우리가 전문성을 구축하는 팀을 가졌다고 느낀 것은 이번이 처음이었습니다. 수십 년간 충분한 지식이 없다는 걱정, 민망한 방식으로 문제가 발생하는 것, 그리고 플랫폼을 자주 바꾸는 것에 대해 걱정했던 것에 비해, 안정성과 전문성으로 가는 로드맵을 갖게 된 것은 정말 좋은 경험이었습니다.
PIT가 처음 한 일은 진행 중인 여러 인프라 프로젝트를 종료하고 가능한 한 많은 미사용 인프라를 정리하는 것이었습니다. 이것과 oncall 프로세스를 제대로 문서화하는 것을 통해, 그들은 매우 빠르게 많은 복잡성을 제거했습니다. 이는 팀의 모든 구성원들이 바로 더 생산적으로 변하게 만들었고, 모든 팀 구성원들에게 시스템에 대한 오너쉽을 부여했습니다. 아직 작업 중이긴 하지만, 복잡한 영역에서 전문성을 쌓는 데는 시간이 오래 걸립니다. 하지만 처음으로 정말 팀에 자신감을 느끼고, 1년 동안 그들이 이룬 성과에 대해 자랑스럽게 생각하고 있습니다.
그나저나, 우리는 여전히 AWS를 사용하고 있지만, 이것이 우리가 다시 플랫폼을 바꾸고 싶지 않다는 것을 의미하지는 않습니다. 항상 주변을 탐색하는 것이 좋고, 우리는 클라우드에서 벗어나 관리되는 데이터 센터로 옮겨가는 것에 대해 조금 더 배우는 시간을 가졌습니다. 하지만 좋은 점은 굳이 그렇게 할 필요가 없다고 느끼는 것입니다.
타임머신이 있다면
만약 2012년으로 돌아가 제 자신에게 몇 가지 조언을 해줄 수 있는 시간 여행을 할 수 있다면, 무엇을 말할까요?
작은 팁들이 많지만, 세 가지 큰 조언이 있습니다. 이 세가지 조언들은 조금 더 많은 돈을 지출함으로써 많은 골칫거리를 피할 수 있다는 것으로 결론지어집니다.
가능한 한 오래 관리형 서비스를 사용하세요.
몇 개월만에 Heroku를 떠난 것은 우리에게 큰 불이익이었습니다. 우리는 몇 년 동안 그곳에 머물렀어야 했습니다 - 초기 중요한 시기에 우리 대신 서버 관리를 해줄 수 있는 시간을 많이 낭비했습니다.
PIT를 더 일찍 설립하세요.
이 분야에서 일하고 싶어하는 전문가들로 팀을 훨씬 더 일찍 구성했어야 했습니다. Heroku 시절에는 아니었지만, 우리가 실제 규모에 도달하면서 유지하기 힘들어졌을 때죠.
자신을 조금 더 챙기세요.
이유를 모르겠지만, 문제 발생을 알리는 알림 줄이고, oncall을 단순화하여 더 많은 수면을 취하도록 하는 일들에 우선순위를 두는일이 항상 어렵게 느껴졌습니다. 그러다 어느 날 갑자기 마음이 바뀌어 PIT 팀을 설립하기 위해 많은 예산을 할당했습니다. 충분한 수면은 많은 상업적 이익을 가져다주며, 그리고 팀이 다른 일에 집중하는 것보다 이것을 우선하는 것은 이기적인 것이 아니라고 생각합니다.
의견을 남겨주세요