로켓펀치에서는 기본적인 웹 서비스 외에 제휴를 통해 로켓펀치의 채용 공고를 위젯 형식으로 노출하는 경우가 있습니다. (예 : 플래텀 오른쪽 사이드바 위젯) 이런 위젯들을 운영하다 보니 몇 가지 추가적인 요구 사항이 생겼는데요. 주로 아래의 두 가지로 요약할 수 있습니다.
- 제휴를 맺은 곳의 갑작스러운 트래픽 증가가 로켓펀치 웹 서비스에 영향을 주지 않을 것
- 로켓펀치에서 일시적인 오류가 발생하더라도 제휴를 맺은 곳에서 가능하면 오류가 발생하지 않을 것
이 두 가지를 만족하기 위해 최초에 기존의 서버와 분리하여 별도의 서버를 구축하는 방안을 생각했습니다. 다만 이 서버를 구축하고 유지하는 여러 가지 비용의 문제로 쉽사리 진행되지 않고 있었습니다. 그러던 중 로켓펀치에서는 AWS Lambda를 통해 이를 손쉽게 구축할 수 있다는 것을 알았고 다음과 같은 이점을 기대할 수 있었습니다.
- 서버리스 아키텍처(Severless Architecture)를 통해 서버의 배포 및 유지에 대한 비용을 대폭 감소
- 필요할 때만 노출되기 때문에 불필요한 자원을 소모하지 않음
- 기존의 서버와 분리하여 혹시 모를 트래픽 증가에 기존의 서버가 영향받지 않음
AWS Lambda는 더욱 많은 장점이 있으나 위에 언급된 내용만으로도 저희가 원하던 것을 손쉽게 얻을 수 있었기 때문에 큰 고민 없이 기존의 채용 공고 위젯을 AWS Lambda로 옮기는 것을 결정했습니다.
Zappa – Serverless Python
AWS Lambda로 채용 공고 위젯을 옮기는 것을 결정하고 몇 가지 고민 끝에 최종적으로 Zappa를 사용하기로 했습니다. Zappa는 Python 기반으로 AWS Lambda를 손쉽게 사용할 수 있게 하고 거기에 더해서 API Gateway까지 자동으로 설정해주어서 최종적으로 저희가 원하는 웹 서버를 간단하게 구축할 수 있는 도구입니다. 물론 원래 AWS에서 제공하는 것처럼 필요한 파일들을 압축하여 업로드하고 관련된 내용을 CLI 또는 웹 콘솔을 통해서 설정하여 구현할 수 있지만, 디버깅, 환경 설정, 배포 등의 이유로 프레임워크를 사용하는 게 좋습니다. Zappa 이외에 사용 가능한 서버리스 프레임워크는 다양하게 있습니다.
- Serverless: 가장 유명하고 제공하는 기능이 많습니다. 문서화도 잘 되어 있는 편이고 Node.js, Python, Java, Scala를 지원합니다.
- Apex: express.js를 개발한 TJ Holowaychuk이 만든 프레임워크. 배포 시 멱등성을 보장하며 가장 다양한 언어를 지원합니다. Node.js, Golang, Python, Java, Rust, Clojure를 지원합니다.
- Chalice: AWS에서 개발한 프레임워크. Python을 지원하며 AWS Lambda와 API Gateway를 자동으로 설정해줍니다.
위의 프레임워크 외에도 더 많은 것들이 있으나 저희는 아래와 같은 이유로 Zappa를 사용하는 것으로 결정했습니다.
– 위에서 언급한 데로 API Gateway까지 설정을 해주기 때문에 배포 후 바로 웹에서 확인 가능합니다.
– 저희는 이미 Django 와 Flask를 사용 중이고 바로 활용할 수 있습니다. 이는 디버깅도 기존에 사용하던 방식을 거의 그대로 사용할 수 있음을 의미합니다. Zappa로 개발 시 실제로 구축된 내용 중 일부는 기존의 내용을 거의 그대로 사용하여 큰 변경 없이 개발이 진행되기도 했습니다.
– C 확장 패키지들을 바로 사용 가능합니다. (AWS Lambda에서 Python을 사용하는 경우 C 확장 패키지들은 반드시 Amazon Linux에서 컴파일된 파일을 사용해야 합니다. 이런 부분이 개발 및 배포 시 불편할 수 있는데 Zappa에서는 이를 미리 컴파일된 파일을 자동으로 가져와서 배포 시 사용합니다)
– 재 수행 시 수행 시간을 느리게 만드는 원인 중 하나인 Cold Start를 방지할 수 있습니다. (설정 시 기본적으로 4분에 한 번씩 호출. 다만 저희는 그렇게 오랫동안 호출되지 않을 일이 없어서 최종적으로는 사용하지 않았습니다)
개발 및 AWS Lambda에 배포하기
Zappa로 개발하는 것은 아주 간단했습니다. 저희가 사용하던 내용 중 채용 공고 위젯의 내용을 일부 가져와서 동일하게 구현(Flask로 구현)하고 같은 개발 환경에서 테스트까지 완료되면 `zappa_settings.json` 파일만 설정하고 배포할 수 있습니다. 여기서는 `zappa_settings.json`에서 설정 가능한 일부 항목들만 간단히 소개하겠습니다.
{ // API Gateway에서 사용하는 Stage 명입니다. "name": { // 배포 시 Zip 파일을 업로드할 S3 bucket의 이름입니다. "s3_bucket": "bucket-name", // 사용할 AWS Region을 설정합니다. 설정 전 반드시 AWS Lambda, API Gateway 그리고 CloudFormation이 올바르게 사용 가능한지 확인해야 합니다. // 작년까지 Seoul Region에서는 AWS Lambda, API Gateway는 올바르게 사용 가능하나 CloudFormation을 통해서 API Gateway를 설정하는 데 문제가 있었기 때문에 배포가 올바르게 진행되지 않았습니다. "aws_region": "ap-northeast-2", // WSGI 애플리케이션 함수. Flask, Django 등에 따라서 내용이 다릅니다. zappa init으로 보통 자동 설정됩니다. "app_function": "app.app", // Django 로 개발 시 사용되는 Django setting 파일의 위치입니다. "django_settings": "your_project.settings" // 배포 시 압축 파일에 포함되지 않을 내용을 설정합니다. "exclude": ["*.gz", "*.rar", ".git", ".gitignore"], // 배포 시 설정될 환경 변수입니다. `os.environ.get`으로 애플리케이션 내에서 간단히 사용 가능합니다. "environment_variables": {"your_key": "your_value"}, // true로 설정 시 자동으로 CloudWatch 이벤트를 추가하여 Cold Start를 방지합니다. "keep_warm": true, // AWS Lambda에서 사용할 메모리 크기를 결정합니다. AWS Lambda 비용을 결정하는 가장 큰 요소 중 하나입니다. "memory_size": 128, // AWS Lambda 함수가 수행을 완료할 수 있는 최대 시간을 설정합니다. "timeout_seconds": 30, // AWS Lambda에 VPC를 설정합니다. 이를 통해 AWS 내의 다른 자원에 대한 접근이 가능합니다. "vpc_config": { "SubnetIds": ["subnet-12345678"], "SecurityGroupIds": ["sg-12345678"] } } }
위 내용을 설정 후 Zappa의 deploy(또는 update) 명령어를 사용하는 것으로 배포가 완료되었습니다.
Calling update for environment name.. Downloading and installing dependencies.. 100%|██████████████████████████████████| 39/39 [00:10<00:00, 5.27pkg/s] Packaging project as zip.. Uploading file.zip (11.0MiB).. 100%|██████████████████████████████████| 11.5M/11.5M [00:00<00:00, 21.1MB/s] Updating Lambda function code.. Updating Lambda function configuration.. Uploading template.json (2.8KiB).. 100%|██████████████████████████████████| 2.83K/2.83K [00:00<00:00, 37.0KB/s] Deploying API Gateway.. Your deployed Zappa deployment is live!: https://abcd1234.ap-northeast-2.amazonaws.com/name
배포 후에는 url을 통해 바로 확인할 수 있으며 수정이 필요한 경우 수정 후 `zappa update {name}`을 통해 바로 업데이트할 수 있습니다. 저희가 실제로 배포하여 사용 중인 내용 중 하나는 https://widget.rocketpunch.com/banner로 Custom Domain과 SSL을 추가로 설정하여 배포하였으며 언제든 바로 확인할 수 있습니다. AWS Lambda를 사용하기로 하고 약 3일간의 작업을 통해서 개발 및 배포까지 완전히 끝낼 수 있었으며 아래에 기술되는 내용과 더불어 아주 큰 효과를 볼 수 있었습니다.
개발 완료 후
위에 언급한 것 이외에도 AWS Lambda 사용 시 추가적으로 기대하던 것이 하나가 있었습니다. 그것은 비용 절감입니다. AWS Lambda는 자원을 사용한 만큼 지불하기 때문에 저희가 사용 중인 간단한 위젯 화면의 경우는 자원을 매우 적게 사용하기 때문에 요청이 많더라도 일반적인 서버 구축과 비교하면 비용이 매우 적을 것으로 기대했습니다.
실제로 최근 한 달간 193만 Request가 있었고 이때 AWS Lambda의 비용은 $0.19였습니다. 이는 한화로 단돈 300원에 해당합니다.
추가로 API Gateway까지 사용한 금액은 총액 $6.95로 약 8,000원에 월 200만뷰 가까이 소화하는 것을 확인했습니다.
이는 기존의 간단한 서버 구축을 위해서도 사용되는 월 몇만 원의 비용, 트래픽이 몰리는 경우 자원 사용의 문제, 거기에 더해 서버 관리를 위해 소모되는 시간까지 생각하면 아주 적은 비용으로 원하는 내용을 모두 만족하게 되었습니다. 로켓펀치에서는 현재 채용 공고 위젯 외에 비동기로 수행되는 내용의 일부를 AWS Lambda를 사용하여 구현 중이며 기대만큼의 효과를 거두고 있어 앞으로 그 활용 영역을 더욱 넓힐 예정입니다.