AWS Lambda는 오버헤드를 최소화하면서도 확장성 있는 함수를 구축할 수 있게 해주는 강력한 서비스입니다. Ruby on Rails 앱 전체를 작성하고 호스팅하고 유지보수하는 대신, Lambda 함수를 활용하면 개별 이벤트에 독립적으로 대응하는 코드를 실행할 수 있습니다. 이 글에서는 AWS가 처음인 분도 자신만의 Lambda 함수를 Ruby로 작성할 수 있도록 기초부터 차근차근 안내합니다.
Lambda는 서버를 직접 관리할 필요 없이 이벤트에 반응하여 코드를 실행할 수 있게 해줍니다. 이러한 이벤트 기반 아키텍처 덕분에 코드가 실제로 동작하는 시간에만 비용을 지불하고, 유휴 상태일 때는 비용이 발생하지 않습니다. Lambda는 S3 버킷에서 파일이 삭제되는 것 같은 AWS 생태계 내부의 이벤트에 대응하는 용도로 가장 많이 사용되지만, AWS API Gateway와 함께 구성하면 API로도 동작하게 할 수 있습니다.
Lambda는 Cron Job처럼 시간 기반 작업을 자동화하거나, 특정 이벤트에 대한 응답 처리에 활용할 수 있습니다. 나아가 DynamoDB 같은 다른 AWS 서비스와 연동한 데이터 처리, 심지어 확장성 있는 API 구축까지 가능합니다. 예를 들어 아래 Amazon 공식 문서의 다이어그램은 모바일 클라이언트가 HTTP 요청을 보내 데이터베이스에 CRUD 작업을 수행하는 간단한 아키텍처를 보여줍니다. API Gateway가 요청을 해당 Lambda 함수로 라우팅하고(Rails가 HTTP 요청을 컨트롤러로 라우팅하는 것과 유사), 함수는 비즈니스 로직을 수행하며 AWS DynamoDB와 통신하여 요청을 처리합니다.

코드는 컨테이너에서 실행되기 때문에, 사용하지 않을 때는 Amazon 인프라가 자동으로 함수를 일종의 절전 모드로 전환합니다. 새로운 요청이 들어오면 컨테이너는 콜드 스테이트(cold state)에서 시작해야 하며, 이로 인해 실행 시간이 최대 2000ms까지 늘어날 수 있습니다. 이는 응답 속도 측면에서 서비스 품질을 저하시킬 뿐만 아니라 비용 증가로도 이어질 수 있습니다. 따라서 사용자 이메일 발송이나 UI 이벤트 대응처럼 시간에 민감한 작업에는 병목 현상이 발생할 수 있습니다. AWS CloudWatch로 주기적으로 요청을 스케줄링해 함수를 '따뜻하게(warm)' 유지하는 방법으로 완화할 수 있지만, 이 경우 호스팅 비용이 늘어난다는 점을 감안해야 합니다.
AWS Lambda를 사용해야 하는 이유
Amazon Web Services(AWS)는 세계에서 가장 널리 사용되는 클라우드 컴퓨팅 서비스입니다. 개인 개발자도 부담 없이 사용할 수 있을 만큼 간단하면서도, 세계 최대 규모 기업들의 인프라로 활용될 수 있을 만큼 강력하고 확장성이 뛰어납니다.
AWS Lambda는 Amazon이 제공하는 '서버리스 컴퓨팅 서비스' 중 하나로, 이벤트에 대한 응답으로만 코드를 실행할 수 있게 해줍니다. 이를 통해 오버헤드를 크게 줄이고, 전체 서버를 호스팅하거나 앱 전체를 구축하지 않고도 API 호출 같은 이벤트에 프로그래밍 방식으로 대응할 수 있습니다.
적합한 사용 사례에 적용한다면, 이 서버리스 아키텍처는 상당한 비용 절감 효과를 제공합니다. 요금은 요청 건수당 비용과 컴퓨팅 시간당 비용으로 산정됩니다. 월 100만 건의 무료 요청 이후에는 백만 요청당 $0.20에 더해 함수가 사용하는 GB-초당 $0.0000166667가 부과됩니다. 이런 종량제 요금 체계 덕분에 소규모 서비스를 Lambda에서 운영하는 비용은 놀랍도록 저렴하면서도, 동일한 단가로 무한히 확장할 수 있는 옵션을 그대로 유지할 수 있습니다.
Ruby 개발자는 이 클라우드 서비스를 API 호출이나 다른 AWS 이벤트에 상태 비저장(stateless) 방식으로 대응하는 수단으로 활용해 많은 이점을 얻을 수 있습니다.
AWS 평가판 계정 만들기
AWS는 꽤 넉넉한 무료 등급(free tier)을 제공합니다. AWS Lambda의 경우 매월 100만 건의 무료 요청과 최대 320만 초의 컴퓨팅 시간이 포함됩니다! 이미 계정이 있다면 이 단계는 건너뛰어도 되지만, 계정 생성 자체는 매우 간단합니다.
회원가입 페이지로 이동해 필요한 정보를 입력하면 바로 시작할 수 있습니다.

그다음 계정 유형과 연락처 정보 등 추가 정보를 입력하라는 안내가 표시되며, 무료 등급 범위를 벗어나는 사용량을 결제하기 위해 신용/직불 카드 정보도 입력해야 합니다. 이 글에서 진행하는 간단한 Lambda 사용은 무료 등급에 포함되지만, 실수로 인한 과다 사용이 걱정된다면 예산(Budget)을 설정해 사용량을 관리하고 예상치 못한 청구를 방지할 수 있습니다.
Ruby로 Lambda 함수 생성하기
가입을 마쳤다면 products(제품)에 마우스를 올리고 compute(컴퓨팅)를 선택한 뒤 Lambda를 클릭합니다.

Lambda 콘솔에 접속하면('get started' 버튼을 눌러야 할 수도 있습니다) 빈 함수 목록과 주황색 "Create Function" 버튼이 보입니다. 짐작하셨겠지만, 우리는 저 주황색 "Create Function" 버튼을 누르면 됩니다.

그다음 "Author from Scratch"를 선택합니다. Ruby용 템플릿 함수는 아직 없고, 처음부터 직접 작성하는 것이 학습에도 가장 좋기 때문입니다.
함수 이름을 적절히 지정하고 사용할 Ruby 버전을 선택하세요. 저는 유명한 프로그래밍 문제의 이름을 따 FizzBuzz라고 지었습니다.
탐색 창에서 lambda_function.rb 파일을 더블클릭해야 소스 코드가 표시될 수 있습니다.
함수는 lambda_handler라는 이름으로 미리 작성되어 있습니다. 현재 상태로 호출하면 아래 화면에서 볼 수 있듯이 "Hello From Lambda!"라는 텍스트와 함께 200 응답을 반환합니다.

테스트 트리거로 Lambda 함수 실행하기
앞서 말했듯이 Lambda 함수는 다양한 방식으로 트리거될 수 있습니다. 가장 흔한 방식 중 하나는 API 호출인데, 이를 위해서는 AWS API Gateway를 설정해야 하며 이는 이 글의 범위를 조금 벗어납니다. API Gateway는 Lambda와 훌륭하게 연동되어 최소한의 설정으로 무한 확장 가능한 API를 만들 수 있습니다.
다행히 함수 콘솔에서 API 호출을 시뮬레이션하는 것은 어렵지 않고, 테스트 이벤트가 이미 준비되어 있습니다.
함수 개요(Overview) 아래에는 현재 "Code"가 선택된 도구 모음이 있습니다. 마지막 스크린샷에서 볼 수 있듯이 "Code" 바로 옆에 "Test" 탭이 있습니다. "Test"를 선택하면 코드 소스 영역 대신 테스트 콘솔이 나타납니다.

미리 구성된 테스트 이벤트는 Lambda 함수에 event 객체로 전달되는 JSON 객체입니다. 함수는 이 객체를 파라미터로 받습니다. API Gateway를 통해 엔드포인트를 호출한다면 이것이 곧 요청 본문(body)에 해당합니다.
기본 제공되는 Lambda 함수는 event를 읽지 않으므로 어떤 본문을 보내든 결과에는 큰 차이가 없습니다. 따라서 그대로 진행해 주황색 "Invoke" 버튼을 누르면 됩니다.
함수를 올바르게 설정했다면 "Execution Succeeded"라는 녹색 박스가 표시되고, 이를 펼치면 함수가 반환한 JSON 응답을 확인할 수 있습니다.
FizzBuzz 구현하기
Lambda 함수가 정상 동작하는 것을 확인했으니, 이제 직접 작성한 Ruby 코드로 커스터마이징해 보겠습니다. 이번 예제에서는 유명한 FizzBuzz 문제를 풀도록 Lambda 함수를 만들어 보겠습니다. FizzBuzz는 면접에서 단골로 출제되는 문제로, 문제의 요구 사항은 대략 다음과 같습니다.
1부터 50까지의 숫자를 출력하는 프로그램을 작성하세요. 단, 3의 배수에서는 숫자 대신 "Fizz"를, 5의 배수에서는 "Buzz"를 출력합니다. 3과 5의 공배수인 경우에는 "FizzBuzz"를 출력합니다.
Lambda 함수의 코드를 아래 제 FizzBuzz 솔루션으로 교체해 보세요 -
require 'json'
def lambda_handler(event:, context:)
max_val = event['max_val']
textResponse = ''
1.upto(max_val) do |i|
if i % 5 == 0 and i % 3 == 0
textResponse += "FizzBuzz"
elsif i % 5 == 0
textResponse += "Buzz"
elsif i % 3 == 0
textResponse += "Fizz"
else
textResponse += i.to_s
end
end
{ statusCode: 200, body: JSON.generate(textResponse) }
end
이 코드는 일반적인 FizzBuzz에 약간의 변형을 더한 것입니다. 단순히 50까지 반복하는 대신, 이벤트와 함께 전달된 숫자만큼 반복합니다. event 객체는 딕셔너리처럼 전달되므로 event['max_val']을 호출하면 max_val 키에 해당하는 값을 얻을 수 있습니다. 마지막으로 FizzBuzz 결과를 출력하는 대신 문자열에 누적한 뒤 JSON 객체로 반환합니다.
다음으로, 새 코드로 Lambda 함수를 업데이트하려면 주황색 "Deploy" 버튼을 반드시 눌러야 합니다.
솔루션을 작성하고 배포했다면 다시 테스트 콘솔로 돌아갑니다. 테스트 이벤트를 max_val 키/값 쌍만 전달하도록 수정하세요. 아래와 같이 만들면 됩니다:

JSON은 다음과 같습니다.
{
"max_val": 70
}
마지막으로 "Invoke"를 눌러 테스트를 실행하세요! 결과를 펼쳐 보면 함수가 입력값을 정상적으로 읽고 FizzBuzz 문제의 결과를 반환했음을 확인할 수 있습니다.
더 쉬운 개발 환경 구축하기
학습 목적으로는 웹 콘솔에서 작업하는 것이 편리하지만, 콘솔에만 의존해야 한다면 개발이 고될 수밖에 없습니다. AWS Lambda 개발에서 가장 널리 쓰이는 방법 중 하나는 CLI(Command Line Interface, 명령줄 인터페이스)를 활용하는 것입니다.
IAM 역할을 통해 필요한 권한을 생성한 뒤, CLI를 로컬 머신에 설치하고 자격 증명으로 설정을 완료하세요. 그러면 원하는 IDE에서 로컬로 개발하면서 Lambda CLI로 함수를 테스트하고, 명령줄을 통해 변경 사항을 배포할 수 있습니다.
또 하나 인기 있는 개발 방식은 Serverless 같은 프레임워크를 활용하는 것입니다. Serverless는 AWS의 번거로운 설정 작업 대부분을 대신 처리해 주며, 필요하다면 API Gateway 설정까지 포함됩니다. 또한 로깅 기능을 향상시키고, Ruby Gem 관리를 쉽게 해주며, CI/CD 구성도 지원해서 저장소의 파이프라인 기반 자동 배포가 가능합니다.
Serverless나 유사한 프레임워크를 사용하지 않으면 Ruby Gem을 포함시키는 데 여러 단계를 거쳐야 합니다. 함수를 폴더 구조로 확장한 뒤, 루트 디렉터리에 .bundle/config 파일을 만들어 아래 초기화 코드를 넣어 bundler에게 설치한 gem의 위치를 알려줘야 합니다.
---
BUNDLE_PATH: "vendor/bundle"
그다음 CLI로 bundle add 명령으로 필요한 gem을 추가하고, 코드에서 바로 require하여 사용할 수 있습니다.
AWS Lambda의 한계
축하합니다. 방금 Ruby로 첫 번째 AWS Lambda 함수를 작성했습니다! 이전까지 Ruby로 API를 운영하려면 Rails 앱 전체를 만드는 것이 거의 유일한 현실적인 방법이었습니다. 이제는 엔드포인트를 하나씩 만들어가며, 애플리케이션 전체에 따르는 불필요한 무게를 걱정하지 않아도 됩니다. Lambda는 마이크로초 단위로 사용량을 과금하기 때문에 빠른 솔루션 구축에 놀랍도록 경제적입니다. 게다가 이 클라우드 서비스를 활용하면 낮은 비용으로 운영하면서도 매우 빠른 확장이 가능합니다. Netflix가 피크 타임에도 최대 용량의 서버 대역폭을 상시 비용으로 지불하지 않고 서비스를 유지할 수 있는 것도 AWS 덕분입니다.
이런 장점에도 불구하고 AWS Lambda는 만능 해결책이 아닙니다. 단독으로 API 역할을 할 수 없고 상태(state) 관리 능력도 제한적입니다. Lambda 함수는 실행 시간이 15분을 넘길 수 없으며, 메모리도 6GB로 제한됩니다. 또한 Lambda 함수 테스트는 다소 까다롭습니다. 별도 환경에서 인프라 전체를 복제해야 하는 경우가 많기 때문입니다.
24시간 내내 실행될 필요가 없는 앱이나 기능이라면 Lambda가 잘 맞을 수 있습니다. 반면 함수가 어떤 형태로든 상태를 유지해야 하거나 AWS 생태계 외부의 데이터를 갱신해야 한다면 Lambda는 적합하지 않습니다. Lambda는 기본적으로 동시 접속 1,000개로 제한되므로, 이보다 지속적으로 많은 트래픽이 발생하는 애플리케이션은 Lambda에서 매우 불안정하게 동작합니다. 결국 Lambda는 영구적인 상태 유지가 필요 없는, 수명이 짧은 이벤트 기반 자동화 작업에 가장 적합합니다.
Lambda 함수는 강력한 도구가 될 수 있으며, 특히 여러분 같은 Ruby 개발자의 손에서 그 진가를 발휘합니다.