AWS Lambda (또는 줄여서 Lambda)는 AWS에서 제공하는 서버리스 컴퓨팅 서비스입니다. 이번 장에서 우리는 Lambda를 사용하여 serverless 응용 프로그램을 구축할 것입니다. 그리고 Lambda가 어떻게 내부적으로 작동하는 것까지는 다룰 필요가 없지만 함수가 어떻게 실행되는 것인지에 대해서 고민해보는 것은 아주 중요합니다.

Lambda 스펙

AWS Lambda의 기술 사양을 빠르게 살펴보겠습니다. 우선 Lambda는 다음과 같은 런타임(Runtime)을 지원합니다.

  • Node.js: v8.10 and v6.10
  • Java 8
  • Python: 3.6 and 2.7
  • .NET Core: 1.0.1 and 2.0
  • Go 1.x
  • Ruby 2.5
  • Rust

각 기능은 64 비트의 Amazon Linux AMI가 설치된 컨테이너에서 실행됩니다. 그리고 실행 환경은 다음과 같습니다.

  • 메모리: 128MB - 3008MB, 64 MB 씩 증가
  • 임시 저장용 디스크 공간: 512MB
  • 최대 실행 시간: 900 초
  • 압축시 패키지 크기: 50MB
  • 압축을 풀었을 경우 패키지 크기: 250MB

위 내용을 보면 CPU가 컨테이너 사양의 일부로 언급되지 않은 것을 알 수 있습니다. 이는 사용자가 CPU를 직접 제어할 수 없기 때문입니다. 메모리를 늘리면 거기에 맞춰서 CPU는 자동으로 증가합니다.

임시 디스크 공간은 /tmp 디렉토리의 형태로 사용할 수 있습니다. 이후 연속적으로 호출되는 함수들에서 이 공간을 액세스할 수 없기 때문에 임시 저장 공간으로만 사용할 수 있습니다. 아래에서 Lambda 함수의 Stateless 특성에 대해 좀 더 이야기하겠습니다.

실행 시간은 Lambda 기능을 최대 900 초 또는 15 분 동안 실행할 수 있다는 것을 의미합니다. 즉, Lambda는 장기간 실행되는 프로세스를 위한 서비스가 아닙니다.

패키지 크기는 함수를 실행하는 데 필요한 모든 코드를 나타냅니다. 여기에는 함수가 가져올 수 있는 모든 의존성들(Node.js의 경우 node_modules/ 디렉토리)가 포함됩니다. 압축하지 않은 패키지의 경우 최대 250MB가 제한이며 압축된 경우 50MB 제한이 적용됩니다. 아래 패키징 과정에서 좀 더 자세히 살펴 보겠습니다.

Lambda 함수

Lambda 함수(Node.js 버전)의 모습입니다.

Lambda 함수 구성 이미지

여기서 myHandler는 Lambda 함수의 이름입니다. event 객체는 이 Lambda를 트리거 한 이벤트에 대한 모든 정보를 포함합니다. 이벤트가 HTTP 요청인 경우, 해당 HTTP 요청에 대한 모든 정보가 들어 있습니다. context 객체는 Lambda 함수가 실행되는 런타임에 대한 정보를 포함합니다. Lambda 함수 내부에서 모든 작업을 수행한 후에는 그에 대한 결과(또는 오류)와 함께 callback 함수를 호출하고 이를 AWS가 HTTP 요청에 대한 응답으로 처리합니다.

패키징 함수

Lambda 함수를 패키지화하여 AWS로 보내게 되는데, 이것은 함수와 모든 종속성을 압축하여 S3 버킷에 업로드하는 프로세스입니다. 특정 이벤트가 발생할 때 AWS에 이 패키지를 사용하고 싶다는 내용을 알려주게 되는데 이 과정을 돕기 위해서 Serverless 프레임워크를 사용합니다. 자세한 내용은 안내서에서 설명하겠습니다.

실행 모델

Lambda 함수가 실행되는 컨테이너(및 컨테이너가 사용하는 리소스)는 AWS에 의해 완벽하게 관리됩니다. 이벤트가 발생할 때 생성되고 더 이상 사용하지 않을 때는 제거됩니다. 원래 이벤트가 제공되는 동안 추가 요청이 이루어지면 새 컨테이너가 요청을 처리하기 위해 준비됩니다. 즉, 사용량이 급증할 경우 클라우드 제공 업체는 해당 요청을 처리하는 기능을 가진 컨텐이너들로 구성된 여러 인스턴스를 간단히 생성하게 됩니다.

여기에는 몇 가지 흥미로운 내용이 있습니다. 첫째, Lambda 함수는 상태를 저장하지 않습니다. 둘째, 각 요청(또는 이벤트)은 하나의 Lambda 함수를 지닌 단일 인스턴스에서 제공합니다. 즉, 코드에서 동시 요청을 처리하지 않습니다. AWS는 새로운 요청이 있을 때마다 컨테이너를 띄웁니다. 여기에서 최적화를 수행하게 되는데 몇 분(컨테이너의 부하에 따라 5분~15분) 동안 기다리면 이후에는 콜드 스타트 없이 요청에 바로 응답할 수 있습니다.

Stateless 함수

위 실행 모델은 Lambda 함수를 효과적으로 상태를 저장하지 않도록 합니다. 이것은 Lambda 함수가 이벤트에 의해 트리거 될 때마다 완전히 새로운 환경에서 호출된다는 것을 의미합니다. 이전 이벤트의 실행 컨텍스트에 대한 액세스 권한이 없습니다.

그러나 위에서 언급한 최적화로 인해 실제 Lambda 함수는 인스턴스화된 컨테이너 당 한 번만 호출됩니다. 함수는 컨테이너에서 실행된다는 점을 상기해 보세요. 따러서 함수가 처음 호출 될 때, handler 함수의 모든 코드가 실행되고 핸들러 함수가 호출됩니다. 만일 컨테이너가 후속 요청에 계속 사용할 수 있는 경우에는 해당 함수가 호출되고 주위의 코드는 호출되지 않습니다.

예를들어, 아래의 createNewDbConnection 메소드는 Lambda 함수가 호출 될 때마다가 아니라 인스턴스화된 컨테이너 당 한 번 실행됩니다. 반면에 myHandler 함수는 호출 될 때마다 실행됩니다.

var dbConnection = createNewDbConnection();

exports.myHandler = function(event, context, callback) {
  var result = dbConnection.makeQuery();
  callback(null, result);
};

컨테이너의 캐싱 효과는 앞에서 언급한 /tmp 디렉토리에도 적용됩니다. 컨테이너가 캐쉬되고 있는 동안 사용할 수 있습니다.

이제 Lambda 함수를 상태 저장(Stateful)으로 만드는데 좋은 방법이 아니라는 것을 짐작할 수 있습니다. 왜냐하면 Lambda가 호출되거나 컨테이너가 캐시 처리되는 것에 관한 기본 프로세스를 제어하지 못하기 때문입니다.

가격정책

마지막으로 Lambda 함수는 함수를 실행하는 데 걸리는 시간 동안만 비용을 청구하게 됩니다. 그리고 해당 시간은 실행을 시작할 때부터 리턴되거나 종료 될 때까지 계산됩니다. 또한 계산된 시간은 100ms 단위로 올림처리됩니다.

AWS는 실행 완료 후에도 Lambda 함수로 컨테이너를 유지할 수 있지만, 이를 청구하지는 않습니다.

Lambda는 매우 관대한 Free Tier를 제공하며, 이 가이드를 작성하는 동안에도 이러한 가격정책은 크게 벗어나지는 않을 것 같습니다.

Lambda 무료 티어에는 한 달에 1M 의 무료 요청과 한 달에 400,000GB-초의 컴퓨팅 시간이 포함됩니다. 이 기간이 지나면 100만 건당 0.20 달러, GB 초당 0.00001667 달러가 소요됩니다. GB 초는 Lambda 함수의 메모리 소비를 기반으로합니다. 자세한 내용은 Lambda 요금 페이지를 확인하십시오.

경험에 따르면, Lambda는 일반적으로 인프라 비용 중 가장 저렴한 서비스입니다.

다음으로, 데모 애플리케이션을 실행하는 데 드는 총 비용을 포함하여 서버리스의 장점에 대해 자세히 살펴 보겠습니다.