예시
Serverless는 인프라 관리를 AWS에 맡기고 필요할때만, 필요한 만큼 코드만 작성하면 비즈니스 요구사항을 구현하게 될 수 있습니다. 예시를 하나 들면 서버리스의 필요성이 좀 더 와닿지 않을까 싶어서 작성해봤습니다. 제 경험담이 일부 반영되어 있습니다.
서버개발자 A씨는 한 해커톤에 나갔습니다. 세 명이 팀을 이루게 되었고, 서로 머리를 싸맨 결과, 할 일을 간단하게 추가/삭제 할 수 있는 To-do list 앱을 만들기로 했습니다. 프론트는 react를 사용하기로 했기 때문에, 요구 사항에 맞춰서 API 서버 개발을 시작하려고 합니다.
요구 사항을 만족하는 서버를 빠르게 만드려고 조사를 해보니, firebase가 가장 심플하면서도 여러가지를 쉽게 할 수 있는 것 같아서 firebase를 사용하기로 했습니다. 사용하려고 보니 firebase에서 제공하는 여러가지 문법들을 익혀야 하는데 A씨는 mysql과 django에 익숙한 상황이기도 하고, 데이터베이스에 데이터를 추가 삭제하는 단순한 일을 하는 서버를 만드는 것이기 때문에 AWS에 자신이 익숙한 환경을 구축하고 빠르게 배포하는게 낫겠다는 생각을 하게 됩니다.
그래서 AWS에 EC2 인스턴스를 하나 띄워서(컴퓨터 하나를 빌리는 것) django 서버를 구축하려고 합니다. 하다보니 생각보다 할게 많습니다. 인스턴스를 만든 다음에 ssh로 접속해서 nginx를 설치하고, uwsgi를 사용해 django와 nginx를 연결한 다음 mysql 서버를 설치하고 django와 mysql을 연결했습니다. 작업은 로컬에서 해야하니 로컬에서 작업한 코드를 github으로 push하면, github에서 트리거를 발생시켜 EC2에서 github의 코드를 가져와서 갱신하고 uwsgi를 재실행하는 스크립트가 돌도록 해야합니다. 즉, 원격서버로 배포하는 스크립트가 필요합니다. 여차저차 해서 로컬에서 작업 후 push하게 되면 EC2에 반영되는 정도는 작업이 완료되어서, 웹 브라우저에 Hello World! 정도는 띄웠습니다. 여러 가지 삽질을 거치다보니 django에서 Hello World!를 띄우는데 3시간이 걸렸습니다. 그래도 이제 코드에 집중할 수 있으니 코드를 빠르게 쨔서 프론트에 넘기기만 하면 됩니다.
Restful API를 구현하기로 했기 때문에 POST to-dos
요청이 들어오면 데이터베이스에 할일 하나를 추가하고, GET to-dos
요청이 들어오면 여태까지 추가된 데이터베이스에 들어있는 할 일 리스트를 반환하도록 하기로 결정했습니다. 상황에 따라서 페이지네이션이나 요청 parameter에 따른 필터링 등을 해야하기 때문에 Django Restful Framework를 쓰는 것이 나을 것 같습니다. Restful api를 구현하는데 생산성이 아주 좋기 때문입니다. django-rest-framework 튜토리얼을 보며 API를 빠르게 구현해냈습니다. 이제 할 일이 끝났습니다. 실제 코드를 작성하는데는 30분이 채 안걸렸습니다.
‘월드톤’은 아주 성공적으로 끝났고, 심지어 수상까지 하게 되었습니다. 아이디어가 아주 좋았다는 평을 받았고, 이 참에 이걸 가지고 창업까지 하기로 했습니다.
창업을 하고 나니, 실제 유저들이 사용하는 서비스이기 때문에 서버의 안정성이 아주 중요하게 되었습니다. 먼저 중요한 데이터가 날아가면 안되니 데이터베이스를 주기적으로 백업해야 해서, crontab으로 데이터베이스를 주기적으로 dump를 떠서 저장해야 합니다. dump를 뜬 데이터도 날아가버리면 안되니 S3에 저장해야 하고, 롤백을 위한 스크립트도 작성해야 합니다. 데이터베이스에 원격으로 접속해야 하기도 하고, 모니터링, 보안 처리 등 추가적으로 고려해야 할 것들이 많습니다. 그래서 데이터베이스를 관리가 쉬운 AWS의 RDS로 분리하기로 결정했습니다. RDS 인스턴스를 하나 생성해서 엔드포인트를 django에 연결했습니다. 데이터베이스의 관리 포인트가 줄어들게 되었지만, EC2도 모니터링이나 로깅 시스템을 만들어야 합니다. 그래도 uwsgi의 기본적인 로깅이 있고 EC2도 자원은 기본적으로 모니터링 되니 일단은 코드 작성에 집중하도록 합니다.
최근 회사에서 투자를 받아서 이벤트를 열기로 했습니다. 사용자가 몰릴것으로 예상되기 때문에 현재 EC2 인스턴스 사이즈로는 충분하지 않습니다. 데이터베이스도 확장해야 할 것 같습니다. 이에 따른 모니터링과 로깅도 복잡해집니다. 이벤트가 끝난 뒤에는 비용 절감을 위해 다시 인스턴스를 축소해야 합니다. 이렇게 인프라를 관리해야 하는 포인트가 늘어나게 되고, 비용은 점점 증가합니다.
시간이 흘러 창업한 회사가 문을 닫게 되었습니다. 서비스는 더 이상 사용하지 않더라도 RDS, EC2 등 비용이 주기적으로 청구되어서 서버를 내려야 합니다. RDS 인스턴스는 중지시킬수 없으니 데이터를 백업하고 인스턴스를 삭제합니다. EC2는 정지 시켰습니다. 새로운 회사에 입사하기 위해 포트폴리오를 보여주고 싶지만, 기존에 했던건 서버를 내렸기 때문에 보여줄수가 없습니다.
이처럼 스타트업을 시작할 때 혹은 해커톤을 나갔을 때, 공통적으로 요구되는 사항들이 있습니다.
- 인프라에 최대한 신경 안쓰고 서버 구축을 하고 싶다. 난 비즈니스 로직을 구현하는 데에 집중하고 싶다.
- 요구되는 비즈니스 로직을 빠르게 충족시키면서 최대한 싸고, 사용한만큼만 돈을 내고 싶다. (안쓸때는 돈이 안나갔으면 좋겠다.)
- 서비스가 갑자기 잘되어서 사용자가 폭발적으로 늘어날 수 있는 경우도 대비가 되면 좋겠다.
- 이후에 확장 가능한 시스템이어야 한다.
- 코드를 변경했을때 반영하는게 쉬웠으면 좋겠고, downtime은 최대한 작았으면 좋겠다. (배포가 쉬웠으면.. 배포한거 내릴때도 쉬웠으면..)
- 모니터링과 로깅, 데이터베이스 자동 백업과 같은 부가적이지만 기본적인 기능들을 제공받고 싶다.(관리와 운영이 쉬웠으면)
이 얘기들은 결국 확장 가능 하면서도 구현과 배포, 관리가 쉬우면서 저렴한 시스템을 의미합니다. 마치 너무나도 많은 욕심을 부리는 것 같지만, 사실 어느 시스템에서나 필요한 요구사항이라고도 할수 있습니다. (싸면 좋고, 쉬우면 좋으니까)
특히나 안쓸때 돈이 안나간다는건 계속 켜놓고 언제든 필요할때 다시 사용할 수 있다는 점은 매우 큰 장점인듯 합니다.
이러한 문제를 해결하기 위해 서버리스(Serverless)라는 개념이 등장합니다. 서버가 없는 즉, 코드만 작성하면 되고 나머지 인프라는 AWS, GCP와 같은 클라우드 서비스에 맡기는 겁니다.
AWS에서 가장 대표적인 서버리스 서비스는 Lambda입니다. 간단한 스크립트를 쨔는 정도는 Lambda를 쓰는 방법이 아주 쉽습니다. Lambda 콘솔에서 코드를 업로드 하고, 코드를 실행시키기 위한 API Gateway 트리거를 연결하기만 하면 되죠. 하지만 이것을 코드를 로컬에서 쨔고 배포하고, 다른 프레임워크를 연결 하기 위해서는 꽤나 복잡한 작업이 필요합니다. 매번 AWS콘솔에서 코드를 업로드 할 수 없으니, aws cli가 동반되어야 하고, 권한처리, 코드를 S3에 업로드해서 배포하거나 keep warm 설정 등 여러가지를 설정하기가 매우 복잡해집니다. 따라서 서버리스 환경을 쉽게 배포/관리 하기 위한 serverless(프레임워크 이름이 serverless), zappa와 같은 툴이 등장합니다.
그 중에서도 python을 위한 툴인 Zappa라는 서비스가 있습니다. Zappa는 배포를 위한 여러가지 편리한 기능들을 제공합니다. xray를 붙이기도 쉽고, zappa tail 명령어를 사용하면 CloudWatch 콘솔에 직접 접속하지 않고도 로그를 볼수 있고, 롤백도 쉽게 할수 있습니다. 심지어 비동기로 테스크를 실행시킬수도 아주 쉽게 되어 있습니다.
그래서 저는 생산성이 좋으면서도 AWS의 serverless 기능들을 쉽게 사용할 수 있는 조합이 django-rest-framework + Zappa 조합이 좋다고 생각합니다. Django Rest Framework는 Restful API를 쨔기가 쉽게 되어 있어서 API 서버 개발에 적합합니다.
여기서 하나의 문제가 있습니다. 바로 데이터베이스는 관계형 데이터베이스(RDBMS)를 사용한다고 하면 일반적인 RDS로는 비용을 주기적으로 청구해야 하고, 서비스를 거의 사용하지 않는다면 저는 그 가격도 비싸다고 생각했습니다. 하지만 저는 사용하지 않을때는 비용을 최대한 청구하고 싶지 않았습니다. 그래서 해커톤 같이 한번 만들고 거의 쓰이지 않는 것들은 AWS에서 제공하는 Aurora의 serverless 붙이면 데이터베이스까지 서버리스 환경으로 구축할 수 있습니다. Zappa는 python을 위한 프레임워크이긴 하지만, 특정 프레임워크(django나 flask 같은)에 종속되어 있지는 않습니다. 따라서 django를 붙일때, Aurora를 붙일때 여러가지 설정해야 할 것들이 꽤 있습니다. 그래서 이러한 것들을 설정해놓은 github와 문서를 만들어놓았습니다. 이 github repository를 사용해 initial setup의 작업들만 진행하면 zappa, mysql, django의 모든 기능들을 사용할 수 있도록 했습니다.
Serverless의 단점
serverless가 장점만 존재하는 것은 아닙니다. 다음과 같은 상황에서는 serverless를 사용하지 않는 것이 나을 수 있습니다.
- 사용자가 많은 서비스를 운영할 것이다(동시 접속자 1000명 내외가 유지된다)
- 인프라를 정밀하게 운영하고 싶다.
- 요청을 처리할 때 굉장히 긴 작업이 필요하다(15분 이상)
- Lambda에서 Lambda의 VPC 내부가 아닌 외부 네트워크를 이용하는 일이 많다.(외부 네트워크를 이용할 경우 NAT 비용이 발생하는데 이게 좀 비싼편이라서 비용을 잘 측정하고 의사결정을 해야합니다.)
또한 Lambda와 Aurora는 cold start가 발생합니다. 즉, 오랫동안 접속을 안했거나 서버가 scale out될 경우, 인스턴스가 준비되는 시간이 필요하기 때문에 초반엔 매우 느릴수 있습니다.