서버리스 컴퓨팅은 서버 관리와 프로비저닝 작업을 클라우드 제공업체에 위임할 수 있게 해주는 기술로, 최근 대부분의 개발 팀에서 빠르게 표준으로 자리 잡고 있습니다. AWS Lambda는 많은 기술 팀이 사용하는 대표적인 서버리스 기술이며, Node.js, Java, Python, Ruby 등 주요 프로그래밍 언어를 폭넓게 지원합니다. 하지만 핵심 언어가 지원된다 해도, 해당 언어로 만들어진 프레임워크의 기능에 의존하는 서버리스 함수를 실행하고 싶은 경우가 종종 있습니다. 이 글에서는 Rails 애플리케이션을 AWS Lambda에서 실행하는 방법을 살펴보겠습니다. 독자 여러분은 이미 서버리스 컴퓨팅과 AWS Lambda에 대한 기본 지식이 있고, Rails를 Lambda에서 구동하는 방법을 알고 싶어 한다고 가정합니다. 다행히 Lamby라는 도구를 사용하면 Rails를 AWS Lambda에서 거의 손쉽게 운영할 수 있으며, 이 글에서는 Lamby를 활용해 Rails 앱을 빌드하고 Lambda에 배포하는 전 과정을 다룹니다. 편의상 이를 "Rails on Lambda"라고 부르겠습니다.
Lamby란 무엇인가?
Lambda를 사용하면 서버를 직접 유지 관리하지 않고도 코드를 배포하고 어떤 규모에서든 실행할 수 있습니다. 코드를 AWS에 업로드하기만 하면, 사용자가 웹 페이지를 요청하거나 작업이 큐에 등록되는 등의 이벤트가 발생할 때마다 자동으로 실행됩니다.
다만 Lambda는 코드가 특정한 방식으로 구조화되기를 기대합니다. 따라서 Rails 앱 같은 것을 호스팅하려면 Lamby와 같은 어댑터가 필요합니다.
Lamby는 간단한 Rack 어댑터입니다. Rails 앱과 AWS Lambda 사이에서 동작하며, API Gateway나 애플리케이션 로드 밸런서 같은 다양한 AWS 소스에서 발생하는 Lambda 호출 이벤트를 Rails 앱이 처리할 수 있는 Rack 이벤트로 변환해 줍니다.

Rails Lambda 아키텍처 (출처: Lamby 공식 문서)
Lamby는 Docker와 AWS SAM을 활용하여 Rails 앱을 빌드, 패키징하고 Lambda에 배포합니다.
AWS Serverless Application Model(AWS SAM)은 AWS에서 서버리스 애플리케이션을 구축할 때 사용할 수 있는 오픈소스 프레임워크입니다. 서버리스 애플리케이션은 작업을 수행하기 위해 함께 동작하는 Lambda 함수, 이벤트 소스 및 기타 리소스의 조합입니다. 서버리스 애플리케이션은 단순히 하나의 Lambda 함수 그 이상이라는 점에 유의하세요. API, 데이터베이스, 이벤트 소스 매핑 같은 추가 리소스도 포함될 수 있습니다.
-- AWS SAM 공식 문서
Lamby를 시작하려면 Docker 설치, AWS 계정 생성, 그리고 AWS 계정에 대한 프로그래밍 방식 접근(programmatic access) 설정이 필요합니다.
Docker 설치
AWS SAM은 Docker를 사용해 Lambda 런타임 환경을 시뮬레이션합니다. 또한 Docker는 Python에 의존하는 AWS CLI와 SAM CLI의 설치 복잡성도 줄여 줍니다. 아직 Docker가 설치되어 있지 않다면 공식 웹사이트에서 내려받아 설치하면 되므로 매우 간단합니다. Docker가 정상적으로 설치되었는지 확인하려면 터미널에서 아래 명령어를 실행하세요. 설치되어 있다면 아래와 비슷한 버전 번호와 빌드 정보가 출력됩니다.
$ docker --version

Docker 설치 확인 화면
AWS 계정 설정
아직 AWS 계정이 없다면 먼저 생성해야 합니다. Amazon은 무료 티어(Free Tier) 플랜을 제공하므로, Lambda에서 Rails 앱을 만들고 테스트하는 데 드는 비용을 충분히 커버할 수 있습니다. AWS 계정 생성 및 활성화 방법에 대한 공식 가이드를 참고해 계정을 설정하세요.
AWS 프로그래밍 방식 접근 설정
AWS 계정을 만들었다면, 이제 계정의 AWS Access Key ID와 AWS Secret Access Key를 사용해 프로그래밍 방식 접근을 구성해야 합니다. 아직 키가 없다면 다음 절차에 따라 생성할 수 있습니다.
- AWS 계정에 로그인합니다.
- AWS Management Console 상단 툴바에서 "Services(서비스)"를 클릭합니다.
- "IAM"을 검색하여 선택합니다.
- 왼쪽 탐색 메뉴에서 "Users(사용자)"를 클릭합니다.
- 기존 IAM 사용자가 있다면 해당 사용자 이름을 선택합니다.
- "Security credentials(보안 자격 증명)" 탭을 클릭합니다.
- "Create access key(액세스 키 생성)" 버튼을 클릭합니다.
- 발급된 키 ID와 시크릿 키를 안전한 곳에 보관합니다.
- IAM 사용자가 없다면,
- "Add user(사용자 추가)"를 클릭합니다.
- 사용자 이름을 입력하고 "Programmatic access(프로그래밍 방식 액세스)" 옵션을 선택합니다.
- 안내에 따라 나머지 과정을 완료합니다.
이제 Docker를 사용해 CLI 프로그래밍 방식 접근을 구성해 보겠습니다. 아래 코드를 터미널에 붙여 넣으세요. AWS Access Key ID와 AWS Secret Access Key 입력을 요구하는 프롬프트가 뜨면, 앞 단계에서 발급받은 키를 입력합니다.
$ docker run \
--interactive \
--tty \
--rm \
--volume "${HOME}/.aws:/root/.aws" \
"amazon/aws-cli" \
configure

새 Rails 애플리케이션 생성
SAM CLI를 사용해 Rails 프로젝트를 부트스트랩(bootstrap)하겠습니다. AWS SAM CLI는 일반적으로 쿠키커터(cookiecutter)라고 불리는 GitHub 저장소 템플릿으로부터 새 프로젝트를 초기화할 수 있게 해줍니다. 새 SAM 프로젝트를 시작하기 위해 Docker 컨테이너에서 sam init을 실행하며, 이때 Lamby Cookiecutter 프로젝트 템플릿을 활용해 새 프로젝트 폴더를 손쉽게 만듭니다. 프로젝트 이름 입력을 요구하는데, 여기서는 "rails_on_lambda"를 사용했습니다.
$ docker run \
--rm \
--interactive \
--volume "${PWD}:/var/task:delegated" \
lambci/lambda:build-ruby2.7 \
sam init --location "gh:customink/lamby-cookiecutter"

새로 생성된 SAM 프로젝트 폴더에는 Rails on Lambda 프로젝트에 필요한 모든 것이 들어 있습니다. 높은 수준에서 살펴보면 다음과 같은 항목들이 생성됩니다.
- Dockerfile과 docker-compose를 모두 갖춘 Docker 설정
- lib 디렉터리, bundler, 테스트를 포함하는 동작 가능한 Ruby 프로젝트
- SAM
template.yaml파일
셋업 및 배포
새 Rails 앱을 만들었으니, 이제 Lambda 배포를 위한 준비 작업이 필요합니다. 아래 두 명령어는 Docker 개발 이미지를 빌드하고 gem을 번들링하는 스크립트를 실행합니다. bootstrap 명령은 한 번만 수행하면 되고, setup 명령은 새 프로젝트 의존성을 추가할 때마다 실행하면 됩니다.
$ ./bin/bootstrap
$ ./bin/setup
위 명령들이 성공적으로 실행되면 프로젝트를 SAM을 통해 배포할 준비가 된 것입니다. 배포는 Rails 애플리케이션을 빌드, 패키징, 배포하는 Lamby 스크립트를 통해 수행됩니다.
./bin/deploy
deploy 명령은 현재 프로젝트 디렉터리를 로컬의 .lamby 디렉터리로 복제한 뒤, 애플리케이션 배포에 필요한 세 가지 SAM 명령을 실행하는 Lamby 빌드 스크립트를 구동합니다.
- sam build
- sam package
- sam deploy
스크립트가 정상적으로 실행되면 SAM의 CloudFormation 배포 작업 출력이 표시되며, 마지막에 아래와 비슷한 결과를 확인할 수 있습니다.

터미널 출력에 URL도 함께 표시됩니다. 이 URL은 Rack을 통해 Rails 애플리케이션을 호출하는 API Gateway HTTP API 엔드포인트입니다. 브라우저에서 열어 보면 익숙한 "Rails 시작 페이지(welcome aboard)" 화면을 확인할 수 있습니다.

AWS 콘솔에서 Rails 앱 호출하기
Lambda 대시보드에서도 앱을 테스트할 수 있습니다. AWS Management Console에 로그인한 후:
- 상단 툴바에서 "Services(서비스)"를 클릭합니다.
- 검색창에 "Lambda"를 입력하고 선택합니다.
이 페이지에서 방금 배포한 "RailsOnLambda" 프로젝트를 확인할 수 있습니다.

- "RailsOnLambda" 함수를 엽니다.
- 오른쪽 상단의 "Test(테스트)" 버튼을 클릭합니다.
- "Amazon API Gateway Proxy" 이벤트 템플릿을 사용합니다(아래 JSON 템플릿으로 해당 필드를 업데이트하세요).
- 이벤트 이름을 "RailsOnLambdaTest"로 지정합니다.
- "Create(생성)" 버튼을 클릭합니다.
- "Test" 버튼을 클릭해 Lambda를 호출합니다.
{
"body": "",
"path": "/",
"httpMethod": "GET",
"queryStringParameters": {},
"multiValueQueryStringParameters": {},
"pathParameters": {
"proxy": "/"
},
"stageVariables": {},
"requestContext": {
"path": "/",
"httpMethod": "GET"
}
}
모든 과정이 순조롭게 진행되었다면 아래와 비슷한 출력 결과를 볼 수 있습니다.

축하합니다! 이제 Rails on Lambda를 성공적으로 구축했습니다. 물론 Lambda 위의 Rails 애플리케이션도 본질적으로는 일반적인 Rails 애플리케이션입니다. 유일한 차이점은 Lamby 젬이 API Gateway HTTP API, API Gateway REST API, 애플리케이션 로드 밸런서 타깃 이벤트를 Rack 호환 env 객체로 변환해 Rails에 전달한다는 것입니다. 그러면 Rails는 이벤트 처리 결과를 프로젝트에 정의된 Lambda 핸들러로 되돌려 줍니다.
def handler(event:, context:)
Lamby.handler $app, event, context
end
Rails on Lambda의 성능은 어떠한가?
Rails on Lambda는 배포 직후 첫 번째 요청에서 응답 시간이 느려지는 현상을 겪습니다. 이를 흔히 "콜드 스타트(cold start)"라고 부릅니다. 하지만 첫 요청 이후에는 성능이 매우 우수하여 EC2에 필적하거나 능가할 수도 있습니다. 첫 요청 이후 추가 요청이 없으면, Rails 앱을 서빙하던 서버 리소스는 약 5~7분 후 다른 Lambda 함수에 동적으로 할당됩니다. 이로 인해 새로운 요청이 들어올 때 다시 콜드 스타트가 발생할 수 있습니다. 콜드 스타트를 피하고 Rails 앱을 따뜻하게(warm) 유지하는 방법은 몇 가지가 있습니다.
CloudWatch 타이머
매분마다 Rails on Lambda 함수를 핑(ping)하도록 설정하여 함수를 따뜻하게 유지할 수 있습니다. AWS 콘솔을 열고 CloudWatch를 검색한 뒤, Events(이벤트)로 이동하여 Create rule(규칙 생성)을 클릭합니다. 이벤트 유형을 Schedule(일정)로 설정하고, 1분마다 이 이벤트가 실행되도록 구성합니다.

프로비저닝된 동시성(Provisioned Concurrency)
프로비저닝된 동시성은 AWS가 유휴 상태의 컨테이너를 항상 실행 상태로 유지하도록 설정하고, 그에 대한 추가 비용을 지불하는 데 동의하는 기능입니다. Rails 앱에 프로비저닝된 동시성을 구성하려면 AWS 콘솔을 열고 Lambda 서비스 페이지로 이동합니다.
- 함수(rails-on-lambda)를 선택합니다.
- Configuration(구성)을 선택한 뒤 Concurrency(동시성)를 선택합니다.
- Provisioned concurrency configurations(프로비저닝된 동시성 구성)에서 Add configuration(구성 추가)을 클릭합니다.
- 별칭(alias) 또는 버전(version) 중 하나를 선택합니다.
- 할당할 프로비저닝된 동시성 수치(예: 500)를 입력합니다.
- 변경 사항을 저장합니다.
프로비저닝된 동시성은 AWS CLI를 통해서도 다음 명령어로 구성할 수 있습니다.
aws lambda put-provisioned-concurrency-config --function-name my-function \
--qualifier BLUE --provisioned-concurrent-executions 100
AWS Lambda의 비용은 얼마인가?
AWS Lambda는 사용한 만큼만 비용을 지불하면 됩니다. 비용은 요청 수와 코드 실행 시간의 조합으로 결정되며, 실행 시간 단가는 함수에 할당한 메모리 양에 따라 달라집니다. 메모리 크기는 128MB부터 10,240MB까지 다양하며, 필요에 따라 원하는 용량을 할당할 수 있습니다. 아래 차트는 다양한 실행 시간에 대해 Lambda 함수를 100,000회 호출했을 때의 비용을 보여 줍니다.

Lambda 비용
Rails on Lambda를 사용하면 안 되는 경우
지금까지 Rails 앱을 AWS Lambda에서 실행할 수 있다는 것을 확인했습니다. 하지만 모든 Rails 애플리케이션이 Lambda에 적합할까요? Rails는 전통적으로 애플리케이션이 서버리스가 아닌 일반 서버에서 실행된다고 가정합니다. 따라서 기존 Rails 서버 환경에서는 쉽게 동작하던 특정 작업이 서버리스 환경에서는 제대로 작동하지 않을 수 있습니다. 예를 들어 파일이나 이미지 업로드는 영구 파일 시스템에 접근할 수 없기 때문에 Rails on Lambda 앱에서는 동작하지 않습니다. 또한 WebSocket 통신도 요청이 없을 때는 서버 자체가 존재하지 않기 때문에 Lambda에서는 작동하지 않습니다.
결론
이 글에서는 기본적인 Rails 애플리케이션을 배포하는 방법만 보여 드렸지만, 대규모 애플리케이션도 동일한 절차를 따릅니다. 컨트롤러와 라우트를 자유롭게 추가하고, 콘솔이나 Postman 등 다른 HTTP 클라이언트를 통해 테스트해 보세요.