

# AWS Lambda이란 무엇인가요?
<a name="welcome"></a>

**작은 정보**  
서버리스 전문가의 무료 실습 워크숍에 참여하여 모범 사례를 통해 서버리스 애플리케이션을 구축하는 방법을 알아보세요. 등록하려면 [여기를 클릭](https://aws-experience.com/amer/smb/events/series/Get-Hands-On-With-Serverless?trk=188abe3e-9f94-4e84-aefb-398d944ad567%26sc_channel%3Del)하세요.

AWS Lambda는 서버를 관리할 필요 없이 코드를 실행하는 데 도움이 되는 컴퓨팅 서비스입니다. 코드가 실행되면 자동으로 확장 및 축소되며 사용량 기준 요금제를 사용합니다. 시작하려면 [첫 번째 함수 생성](getting-started.md)을 참조하세요.

Lambda를 다음 용도로 사용할 수 있습니다.
+ **파일 처리**: 파일을 Amazon Simple Storage Service에 업로드할 때 자동으로 처리합니다. 자세한 내용은 [파일 처리 예제](example-apps.md#examples-apps-file)를 참조하세요.
+ **장기 실행 워크플로:** [지속성 Lambda 함수](durable-functions.md)를 사용하여 최대 1년 동안 실행할 수 있는 상태 저장 다단계 워크플로를 빌드합니다. 주문 처리, 승인 워크플로, 휴먼 인 더 루프 프로세스 및 진행 상황을 기억해야 하는 복잡한 데이터 파이프라인에 적합합니다.
+ **데이터베이스 작업 및 통합 예제**: 데이터베이스 변경에 대응하고 데이터 워크플로를 자동화합니다. 자세한 내용은 [데이터베이스 예제](example-apps.md#examples-apps-database)를 참조하세요.
+ **예약 및 정기 작업**: EventBridge를 사용하여 정기적으로 자동 작업을 실행합니다. 자세한 내용은 [예약된 작업 예제](example-apps.md#examples-apps-scheduled)를 참조하세요.
+ **스트림 처리**: 분석 및 모니터링을 위해 실시간 데이터 스트림을 처리합니다. 자세한 내용은 [Kinesis Data Streams](with-kinesis.md)를 참조하세요.
+ **웹 애플리케이션**: 수요에 맞게 자동으로 조정되는 확장 가능한 웹 앱을 구축합니다.
+ **모바일 백엔드**: 모바일 및 웹 애플리케이션을 위한 보안 API 백엔드를 생성합니다.
+ **IoT 백엔드**: 웹, 모바일, IoT 및 타사 API 요청을 처리합니다. 자세한 내용은 [IoT](services-iot.md)를 참조하세요.

요금 정보는 [AWS Lambda 요금](https://aws.amazon.com/lambda/pricing/)을 참조하세요.

## Lambda 작동 방식
<a name="how-lambda-works"></a>

Lambda를 사용하면 사용자는 자신의 코드에 대해서만 책임을 갖습니다. Lambda는 고가용성 컴퓨팅 인프라에서 코드를 실행하고 서버와 운영 체제 유지 관리, 용량 프로비저닝, 자동 규모 조정, 로깅 등 모든 컴퓨팅 리소스 관리를 수행합니다.

Lambda는 서버리스 이벤트 기반 컴퓨팅 서비스이므로 기존 웹 애플리케이션과 다른 프로그래밍 패러다임을 사용합니다. 아래의 모델에서는 Lambda가 작동하는 방식을 설명합니다.

1. Lambda 애플리케이션을 생성하는 데 사용하는 기본 구성 요소인 [Lambda 함수](concepts-basics.md#gettingstarted-concepts-function)에서 코드를 작성하고 구성합니다.

1. [실행 역할](lambda-intro-execution-role.md)을 사용해 함수가 상호 작용할 수 있는 AWS 서비스를 관리하고, 코드와 상호 작용할 수 있는 리소스 정책을 관리하여 [Lambda 권한](lambda-permissions.md)을 통해 보안 및 액세스를 제어합니다.

1. 이벤트 소스 및 AWS 서비스는 Lambda 함수를 [트리거](concepts-event-driven-architectures.md)하여 함수가 처리하는 JSON 형식의 이벤트 데이터(여기에는 이벤트 소스 매핑 포함)를 전달합니다.

1. Lambda는 런타임, 계층, 확장을 패키징하는 실행 환경에서 언어별 런타임(예: Node.js 및 Python)으로 [코드를 실행](concepts-how-lambda-runs-code.md)합니다.

**작은 정보**  
**서버리스 솔루션**을 빌드하는 방법을 알아보려면 [서버리스 개발자 안내서](https://docs.aws.amazon.com/serverless/latest/devguide/)를 확인하세요.

## 주요 기능
<a name="features"></a>

**보안 애플리케이션 구성, 제어, 배포:**
+ [환경 변수](configuration-envvars.md)는 새로운 코드 배포 없이 애플리케이션 동작을 수정합니다.
+ [버전](configuration-versions.md)은 안정적인 프로덕션 환경을 유지하면서 새로운 기능을 안전하게 테스트합니다.
+ [Lambda 계층](chapter-layers.md)은 여러 함수에서 공통 구성 요소를 공유하여 코드 재사용 및 유지 관리를 최적화합니다.
+ [코드 서명](configuration-codesigning.md)은 승인된 코드만 프로덕션 시스템에 도달하도록 하여 보안 규정 준수를 적용합니다.

**안정적으로 규모 조정 및 수행:**
+ [동시성 및 규모 조정 제어](lambda-concurrency.md)는 트래픽이 급증한 동안 애플리케이션 응답성과 리소스 사용률을 정확하게 관리합니다.
+ [Lambda SnapStart](snapstart.md)는 콜드 스타트 시간을 크게 줄입니다. Lambda SnapStart는 일반적으로 함수 코드를 변경하지 않고도 1초 미만의 시작 성능을 제공할 수 있습니다.
+ [응답 스트리밍](configuration-response-streaming.md)은 실시간 처리를 위해 대용량 페이로드를 점진적으로 제공하여 함수 성능을 최적화합니다.
+ [컨테이너 이미지](images-create.md)는 컨테이너 워크플로를 사용하여 복잡한 종속성을 지닌 함수를 패키징합니다.

**원활한 연결 및 통합:**
+ [VPC 네트워크](configuration-vpc.md)는 민감한 리소스와 내부 서비스를 보호합니다.
+ [파일 시스템](configuration-filesystem.md)은 영구 데이터를 공유하고, 함수 간접 호출 전반에 걸쳐 상태 저장 작업을 관리하는 통합 기능입니다.
+ [함수 URL](urls-configuration.md)은 추가 서비스 없이 퍼블릭 경계 API와 엔드포인트를 생성합니다.
+ [Lambda 확장](lambda-extensions.md)은 모니터링, 보안, 운영 도구를 사용하여 함수를 강화합니다.

## 관련 정보
<a name="w2aab7c17"></a>
+ Lambda 작동 방식에 대한 자세한 내용은 [Lambda 작동 방식](concepts-basics.md) 섹션을 참조하세요.
+ Lambda 사용을 시작하려면 [첫 번째 Lambda 함수 생성](getting-started.md) 섹션을 참조하세요.
+ 예제 애플리케이션 목록은 [예제 애플리케이션 및 패턴 시작하기](example-apps.md) 섹션을 참조하세요.

# Lambda 작동 방식
<a name="concepts-basics"></a>

Lambda 함수는 Lambda 애플리케이션을 빌드하는 데 사용하는 기본 구성 요소입니다. 함수를 작성하려면 Lambda 프로그래밍 모델을 구성하는 핵심 개념과 구성 요소를 이해해야 합니다. 이 섹션에서는 Lambda를 사용하여 서버리스 애플리케이션 구축을 시작하려는 경우 알아야 할 기본적인 요소를 안내합니다.
+ **[Lambda 함수 및 함수 핸들러](#gettingstarted-concepts-function)** - Lambda 함수는 이벤트에 대한 응답에서 실행되는 작은 코드 블록입니다. 함수는 표준(최대 15분) 또는 [지속성](durable-functions.md)(최대 1년)일 수 있습니다. 함수는 애플리케이션을 빌드하는 데 사용하는 기본 구성 요소입니다. 함수 핸들러는 Lambda 함수 코드가 처리하는 이벤트 객체의 진입점입니다.
+ **[Lambda 실행 환경 및 런타임](#gettingstarted-concepts-runtime)** - Lambda 실행 환경은 함수를 실행하는 데 필요한 리소스를 관리합니다. [지속성 함수](durable-functions.md)의 경우 실행 환경에 자동 상태 관리 및 체크포인트 지정 기능이 포함됩니다. 런타임은 함수가 실행되는 언어별 환경입니다.
+ **[이벤트 및 트리거](#gettingstarted-concepts-event)** - 특정 이벤트에 대한 응답으로 다른 AWS 서비스에서 함수를 간접 호출할 수 있습니다. 지속성 함수의 경우 이벤트에서 일시 중지된 워크플로의 재개를 트리거할 수도 있습니다.
+ **[Lambda 권한 및 역할](#gettingstarted-concepts-permissions)** - 함수에 누가 액세스할 수 있는지 제어하고, 어떤 다른 AWS 서비스 함수가 상호 작용할 수 있는지 제어합니다. 지속성 함수에는 상태 관리 및 장기 실행을 위한 추가 권한이 필요합니다.

**작은 정보**  
서버리스 개발을 보다 일반적으로 이해하는 것부터 시작하려면 *AWS 서버리스 개발자 안내서*의 [기존 개발과 서버리스 개발의 차이점 이해](https://docs.aws.amazon.com/serverless/latest/devguide/serverless-shift-mindset.html)를 참조하세요.

## Lambda 함수 및 함수 핸들러
<a name="gettingstarted-concepts-function"></a>

Lambda에서 **함수**는 애플리케이션을 생성하는 데 사용하는 기본 구성 요소입니다. Lambda 함수는 사용자가 웹 사이트에서 버튼을 클릭하거나 Amazon Simple Storage Service(Amazon S3) 버킷에 파일을 업로드하는 것과 같은 이벤트에 대한 응답으로 실행되는 코드입니다. 지속성 함수를 사용하면 코드가 단계 간 실행을 일시 중지하여 상태를 자동으로 유지하므로, 주문 처리 또는 콘텐츠 조정과 같은 장기 실행 워크플로에 이상적입니다. 함수는 다음 속성을 갖는 일종의 독립 프로그램으로 생각할 수 있습니다.

Lambda **함수 핸들러**는 이벤트를 처리하는 함수 코드의 메서드입니다. 이벤트에 대한 응답으로 함수가 실행되면 Lambda는 함수 핸들러를 실행합니다. 함수를 실행한 이벤트에 대한 데이터는 핸들러에 직접 전달됩니다. Lambda 함수의 코드에는 둘 이상의 메서드나 함수를 포함할 수 있지만 Lambda 함수에는 핸들러가 하나만 있을 수 있습니다.

Lambda 함수를 생성하려면 함수 코드와 해당 종속성을 배포 패키지로 묶으세요. Lambda는 [.zip 파일 아카이브](configuration-function-zip.md) 및 [컨테이너 이미지](images-create.md)의 두 가지 배포 패키지를 지원합니다.
+ 함수에는 하나의 특정 작업 또는 목적이 있음
+ 특정 이벤트에 대한 응답으로 필요할 때만 실행됨
+ 완료되면 자동으로 실행을 중지함

## Lambda 실행 환경 및 런타임
<a name="gettingstarted-concepts-runtime"></a>

Lambda 함수는 Lambda가 관리하는 안전하고 격리된 *[실행 환경](lambda-runtime-environment.md)* 내에서 실행됩니다. [지속성 함수](durable-functions.md)의 경우 실행 환경에 상태 관리 및 워크플로 조정을 위한 추가 구성 요소가 포함됩니다. 실행 환경은 함수를 실행하는 데 필요한 프로세스와 리소스를 관리합니다. 함수가 처음 간접적으로 호출되면 Lambda는 함수가 실행될 새 실행 환경을 생성합니다. 함수 실행이 완료된 후에도 Lambda는 실행 환경을 곧바로 중지하지 않습니다. 함수가 다시 간접적으로 호출되면 Lambda는 기존 실행 환경을 재사용할 수 있습니다.

Lambda 실행 환경에는 Lambda와 함수 간에 이벤트 정보 및 응답을 릴레이하는 언어별 환경인 *런타임*도 포함되어 있습니다. Lambda는 가장 인기 있는 프로그래밍 언어에 대한 여러 [관리형 런타임](lambda-runtimes.md#runtimes-supported)을 제공하거나 직접 생성할 수 있습니다.

관리형 런타임의 경우 Lambda는 런타임을 사용하는 함수에 보안 업데이트와 패치를 자동으로 적용합니다.

## 이벤트 및 트리거
<a name="gettingstarted-concepts-event"></a>

Lambda 콘솔, [AWS CLI](https://aws.amazon.com/cli/) 또는 [AWS 소프트웨어 개발 키트(SDK)](https://aws.amazon.com/developer/tools/) 중 하나를 사용하여 Lambda 함수를 직접 호출할 수도 있습니다. 프로덕션 애플리케이션에서는 특정 이벤트에 대한 응답으로 다른 AWS 서비스에서 함수를 간접적으로 호출하는 경우가 더 일반적입니다. 예를 들어 Amazon DynamoDB 테이블에 항목이 추가될 때마다 함수가 실행되도록 할 수 있습니다.

함수가 이벤트에 응답하도록 하려면 **트리거**를 설정합니다. 트리거는 함수를 이벤트 소스에 연결하며, 함수에는 여러 가지 트리거가 존재할 수 있습니다. 이벤트가 발생하면 Lambda는 이벤트 데이터를 JSON 문서로 수신한 후 해당 문서를 코드가 처리할 수 있는 객체로 변환합니다. 이벤트에 대해 다음과 같은 JSON 형식을 정의할 수 있으며, Lambda 런타임은이 JSON을 함수의 핸들러에 전달하기 전에 객체로 변환합니다.

**Example 사용자 지정 Lambda 이벤트**  

```
{
  "Location": "SEA",
  "WeatherData":{
    "TemperaturesF":{
      "MinTempF": 22,
      "MaxTempF": 78
    },
    "PressuresHPa":{
      "MinPressureHPa": 1015,
      "MaxPressureHPa": 1027
    }
  }
}
```

Amazon Kinesis 또는 Amazon SQS 같은 스트림 및 대기열 서비스는 표준 트리거 대신 [이벤트 소스 매핑](invocation-eventsourcemapping.md)을 사용합니다. 이벤트 소스 매핑은 소스를 폴링하여 새 데이터, 배치 레코드가 있는지 함께 확인한 다음, 배치 이벤트를 활용하여 함수를 간접적으로 호출합니다. 자세한 내용은 [이벤트 소스 매핑과 직접 트리거의 차이점](invocation-eventsourcemapping.md#eventsourcemapping-trigger-difference) 섹션을 참조하세요.

트리거의 작동 방식을 이해하려면 우선 [Amazon S3 트리거 사용](with-s3-example.md) 자습서를 완료하세요. 또는 트리거 사용에 대한 일반적인 개요를 확인하고, Lambda 콘솔을 사용하여 트리거를 생성하는 방법에 대한 지침을 확인하려면 [다른 서비스 통합](lambda-services.md) 섹션을 참조하세요.

## Lambda 권한 및 역할
<a name="gettingstarted-concepts-permissions"></a>

Lambda의 경우 구성해야 하는 [권한](permissions-granting-access.md)에는 두 가지 주요 유형이 있습니다.
+ 함수가 다른 AWS 서비스에 액세스하는 데 필요한 권한
+ 다른 사용자 및 AWS 서비스가 함수에 액세스하는 데 필요한 권한

다음 섹션에서는 이러한 두 가지 권한 유형을 모두 설명하고 최소 권한을 적용하는 모범 사례를 설명합니다.

### 함수가 다른 AWS 리소스에 액세스할 수 있는 권한
<a name="gettingstarted-concepts-permissions-role"></a>

Lambda 함수는 다른 AWS 리소스에 액세스하고 해당 리소스에 대한 작업을 수행해야 하는 경우가 많습니다. 예를 들어 함수는 DynamoDB 테이블에서 항목을 읽거나, S3 버킷에 객체를 저장하거나, Amazon SQS 대기열에 쓰기 작업을 수행할 수 있습니다. 이러한 작업을 수행하는 데 필요한 권한을 함수에 부여하기 위해 *[실행 역할](lambda-intro-execution-role.md)*을 사용합니다.

Lambda 실행 역할은 *정책*에 정의된 특정 권한과 연결된 계정에서 생성하는 자격 증명인 AWS Identity and Access Management(IAM) [역할](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html)의 특수한 종류입니다.

모든 Lambda 함수에는 실행 역할이 있어야 하며, 한 역할을 둘 이상의 함수에서 사용할 수 있습니다. 함수가 간접적으로 호출되면 Lambda는 함수의 실행 역할을 수임하고 역할의 정책에 정의된 작업을 수행할 수 있는 권한이 부여됩니다.

Lambda 콘솔에서 함수를 생성하면 Lambda는 자동으로 함수에 대한 실행 역할을 생성합니다. 역할의 정책은 Amazon CloudWatch Logs에 로그 출력을 쓸 수 있는 기본 권한을 함수에 부여합니다. 함수에 다른 AWS 리소스에 대한 작업을 수행할 수 있는 권한을 부여하려면 역할을 편집하여 추가 권한을 추가해야 합니다. 권한을 추가하는 가장 쉬운 방법은 AWS [관리형 정책](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#aws-managed-policies)을 사용하는 것입니다. 관리형 정책은 AWS에서 생성 및 관리하며 많은 일반적인 사용 사례에 대한 권한을 제공합니다. 예를 들어 함수가 DynamoDB 테이블에서 CRUD 작업을 수행하는 경우 [AmazonDynamoDBFullAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonDynamoDBFullAccess.html) 정책을 역할에 추가할 수 있습니다.

### 다른 사용자 및 리소스가 함수에 액세스할 수 있는 권한
<a name="gettingstarted-concepts-permissions-resource-based"></a>

다른 AWS 서비스에 Lambda 함수에 액세스할 수 있는 권한을 부여하려면 *[리소스 기반 정책](access-control-resource-based.md)*을 사용합니다. IAM에서 리소스 기반 정책은 리소스(이 경우 Lambda 함수)에 연결되어 리소스에 액세스할 수 있는 사용자와 수행할 수 있는 작업을 정의합니다.

다른 AWS 서비스에서 트리거를 통해 함수를 간접적으로 호출하려면 함수의 리소스 기반 정책이 해당 서비스에 `lambda:InvokeFunction` 작업을 사용할 수 있는 권한을 부여해야 합니다. 콘솔을 사용하여 트리거를 생성하면 Lambda가 자동으로 이 권한을 추가합니다.

다른 AWS 사용자에게 함수에 액세스할 수 있는 권한을 부여하려면 함수의 리소스 기반 정책에서 다른 AWS 서비스 또는 리소스와 정확히 동일한 방식으로 이를 정의할 수 있습니다. 사용자와 연결된 *[자격 증명 기반 정책](access-control-identity-based.md)*을 사용할 수도 있습니다.

### Lambda 권한 모범 사례
<a name="gettingstarted-concepts-permissions-best-practice"></a>

IAM 정책을 사용하여 권한을 설정하는 경우 [보안 모범 사례](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html)는 작업을 수행하는 데 필요한 권한만 부여하는 것입니다. 이를 *최소 권한* 원칙이라고 합니다. 함수에 대한 권한 부여를 시작하려면 AWS 관리형 정책을 사용하도록 선택할 수 있습니다. 관리형 정책은 작업을 수행할 수 있는 권한을 부여하는 가장 빠르고 쉬운 방법일 수 있지만 필요하지 않은 다른 권한도 포함할 수 있습니다. 초기 개발에서 테스트 및 프로덕션으로 전환함에 따라 자체 [고객 관리형 정책](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#customer-managed-policies)을 정의하여 필요한 권한으로만 권한을 줄이는 것이 좋습니다.

리소스 기반 정책을 사용하여 함수에 액세스할 수 있는 권한을 부여할 때도 동일한 원칙이 적용됩니다. 예를 들어 Amazon S3에 함수를 간접적으로 호출할 수 있는 권한을 부여하려면 S3 서비스에 블랭킷 권한을 부여하는 대신 개별 버킷 또는 특정 AWS 계정의 버킷에 대한 액세스를 제한하는 것이 모범 사례입니다.

# Lambda를 사용하여 코드 실행
<a name="concepts-how-lambda-runs-code"></a>

Lambda 함수를 작성할 경우, 고유한 서버리스 환경에서 실행되는 코드를 생성하게 됩니다. Lambda가 실제로 코드를 실행하는 방법을 이해하려면 두 가지 주요 측면, 즉 코드가 Lambda와 상호 작용하는 방식을 정의하는 프로그래밍 모델과 Lambda가 코드의 런타임 환경을 관리하는 방법을 결정하는 실행 환경 수명 주기를 알아야 합니다.

## Lambda 프로그래밍 모델
<a name="concepts-progmodel-overview"></a>

프로그래밍 모델은 Python, Java로 작성하거나 지원되는 다른 언어로 작성하는 경우와 무관하게 Lambda가 코드와 작동하는 방식에 대한 공통 규칙 세트로 작동합니다. 프로그래밍 모델에는 런타임과 핸들러가 포함됩니다.

**표준 함수:**

1. Lambda는 이벤트를 수신합니다.

1. Lambda는 런타임을 사용하여 코드가 사용할 수 있는 형식으로 이벤트를 준비합니다.

1. 런타임은 형식이 지정된 이벤트를 핸들러로 전송합니다.

1. 핸들러는 작성한 코드를 사용하여 이벤트를 처리합니다.

**지속성 함수:**

1. Lambda의 이벤트 수신

1. 런타임은 이벤트와 DurableContext를 모두 준비

1. 핸들러가 수행할 수 있는 작업은 다음과 같습니다.
   + 자동 체크포인트 지정을 통한 단계 처리
   + 리소스를 사용하지 않고 실행 일시 중지
   + 마지막으로 성공한 체크포인트에서 재개
   + 단계 사이에 상태 유지

이 모델의 필수 요소는 Lambda가 코드에서 처리할 이벤트를 보내는 *핸들러*입니다. 이를 코드의 진입점으로 생각하세요. Lambda가 이벤트를 수신하면 이 이벤트와 일부 컨텍스트 정보가 핸들러에 전달됩니다. 그런 다음, 핸들러는 코드를 실행하여 이러한 이벤트를 처리합니다. 예를 들어 Amazon S3에 업로드되면 파일을 읽거나, 이미지를 분석하거나, 데이터베이스를 업데이트할 수 있습니다. 코드가 이벤트 처리를 마치면 핸들러가 다음 이벤트를 처리할 준비가 된 것입니다.

## Lambda 실행 모델
<a name="concepts-exec-env-overview"></a>

프로그래밍 모델은 Lambda가 코드와 상호 작용하는 방식을 정의하지만, 실행 환경은 Lambda가 함수를 실제로 실행하는 곳입니다. 이는 함수에 사용하도록 특별히 생성된 안전하고 격리된 컴퓨팅 공간입니다.

**각 환경은 표준 함수와 지속성 함수에 따라 달라지는 수명 주기를 따릅니다.**

**표준 함수(최대 15분):**

1. **초기화:** 환경 설정 및 코드 로드

1. **간접 호출:** 함수 코드의 단일 실행

1. **종료:** 환경 정리

**지속성 함수(최대 1년):**

1. **초기화:** 환경 및 지속성 상태 설정

1. **간접 호출:** 자동 체크포인트 지정을 포함한 여러 단계

1. **대기 상태:** 리소스 소비 없이 실행 일시 중지

1. **재개:** 마지막 체크포인트에서 다시 시작

1. **종료:** 지속성 상태 정리

이 환경은 함수 실행의 중요한 측면을 처리합니다. 이는 함수에 메모리와 임시 스토리지용 `/tmp` 디렉터리를 제공합니다. **지속성 함수의 경우 다음도 관리합니다.**
+ 단계 간 자동 상태 지속성
+ 체크포인트 스토리지 및 복구
+ 대기 상태 조정
+ 장기 실행에서의 진행 상황 추적

# Lambda 프로그래밍 모델에 대한 이해
<a name="foundation-progmodel"></a>

Lambda는 최대 15분 동안 실행되는 표준 함수와 최대 1년 동안 실행되는 지속성 함수라는 2가지 프로그래밍 모델을 제공합니다. 2가지 모두 핵심 개념을 공유하지만 지속성 함수는 장기 실행 상태 저장 워크플로를 위한 기능을 추가합니다.

Lambda는 모든 런타임에 공통적인 프로그래밍 모델을 제공합니다. 프로그래밍 모델은 코드와 Lambda 시스템 간의 인터페이스를 정의합니다. 함수 구성에서 *핸들러*를 정의하여 Lambda에게 함수의 진입점을 알려줍니다. 런타임은 호출 *이벤트*와 *컨텍스트*(예: 함수 이름, 요청 ID)를 포함하는 핸들러로 객체를 전달합니다.

**지속성 함수의 경우 핸들러는 다음을 제공하는 DurableContext 객체도 수신합니다.**
+ step()을 통한 체크포인트 지정 기능
+ wait() 및 waitForCallback()을 통한 대기 상태 관리
+ 간접 호출 간 자동 상태 지속성

핸들러가 첫 번째 이벤트 처리를 완료하면 런타임이 다른 이벤트를 보냅니다. 지속성 함수의 경우 핸들러는 단계 간 실행을 일시 중지할 수 있으며, Lambda는 함수가 재개될 때 상태를 자동으로 저장 및 복원합니다. 함수의 클래스가 메모리에 유지되므로, *초기화 코드*에서 핸들러 메서드 외부에서 선언된 클라이언트 및 변수를 재사용할 수 있습니다. 후속 이벤트에 대한 처리 시간을 절약하려면 초기화 중에 AWS SDK 클라이언트와 같은 재사용 가능한 리소스를 생성합니다. 초기화된 후에는 함수의 각 인스턴스가 수천 개의 요청을 처리할 수 있습니다.

또한 함수는 여러 간접 호출에 사용할 수 있는 임시 캐시인 `/tmp` 디렉터리의 로컬 스토리지에 액세스할 수 있습니다. 자세한 내용은 [실행 환경](lambda-runtime-environment.md) 섹션을 참조하세요.

[AWS X-Ray 추적](services-xray.md)이 활성화된 경우 런타임이 초기화와 실행에 대해 별도의 하위 세그먼트를 기록합니다.

런타임은 함수에서 로깅 출력을 캡처하여 Amazon CloudWatch Logs로 전송합니다. 런타임은 함수의 출력을 로깅하는 것 외에도 호출이 시작되고 끝날 때 항목을 로깅합니다. 여기에는 요청 ID, 요금이 청구되는 소요 시간, 초기화 소요 시간 및 기타 세부 정보가 들어 있는 보고서 로그가 포함됩니다. 함수에서 오류가 발생하는 경우, 런타임은 해당 오류를 간접 호출자에게 반환합니다.

**참고**  
로깅에는 [CloudWatch Logs 할당량](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/cloudwatch_limits_cwl.html)이 적용됩니다.. 로그 데이터는 조절로 인해, 또는 경우에 따라 함수의 인스턴스가 중지될 때 손실될 수 있습니다.

**지속성 함수의 주요 차이점:**
+ 단계 간에 상태가 자동으로 유지
+ 함수는 리소스를 사용하지 않고 실행의 일시 중지 가능
+ 실패 시 단계가 자동으로 재시도
+ 체크포인트를 통해 진행 상황 추적

Lambda는 수요가 증가하면 추가 인스턴스를 실행하고 수요가 감소하면 인스턴스를 중지하여 함수 규모를 조정합니다. 이 모델은 다음과 같은 애플리케이션 아키텍처의 변형을 초래합니다.
+ 달리 지정되지 않는 한, 수신 요청은 비순차적으로, 또는 동시에 처리될 수 있습니다.
+ 오래 지속되는 함수의 인스턴스를 사용하지 말고 대신 애플리케이션의 상태를 다른 곳에 저장하세요.
+ 로컬 스토리지 및 클래스 수준 객체를 사용하여 성능을 강화할 수 있지만, 실행 환경으로 전송하는 배포 패키지의 크기와 데이터의 양을 최소로 유지하세요.

다음 장에서는 선호하는 프로그래밍 언어의 프로그래밍 모델을 실습 과정을 겸하여 소개합니다.
+ [Node.js를 사용하여 Lambda 함수 빌드](lambda-nodejs.md)
+ [Python을 사용하여 Lambda 함수 빌드](lambda-python.md)
+ [Ruby를 사용하여 Lambda 함수 빌드](lambda-ruby.md)
+ [Java를 사용하여 Lambda 함수 빌드](lambda-java.md)
+ [Go를 사용하여 Lambda 함수 빌드](lambda-golang.md)
+ [C\$1을 사용하여 Lambda 함수 빌드](lambda-csharp.md)
+ [PowerShell을 사용하여 Lambda 함수 빌드](lambda-powershell.md)

# Lambda 실행 환경 수명 주기 이해
<a name="lambda-runtime-environment"></a>

Lambda 실행 환경은 표준 함수(최대 15분)와 지속성 함수(최대 1년)를 모두 지원합니다. 둘 다 동일한 기본 수명 주기를 공유하지만 지속성 함수는 장기 실행 워크플로의 상태 관리 기능을 추가합니다.

 Lambda는 안전하고 격리된 런타임 환경을 제공하는 실행 환경에서 함수를 호출합니다. 실행 환경은 함수를 실행하는 데 필요한 리소스를 관리합니다. 또한 실행 환경은 함수의 런타임 및 함수와 관련된 모든 [외부 익스텐션](lambda-extensions.md)에 대한 수명 주기 지원을 제공합니다.

**지속성 함수의 경우 실행 환경에 포함되는 추가 구성 요소:**
+ 단계 간 상태 지속성
+ 체크포인트 관리
+ 대기 상태 조정
+ 진행 상황 추적

**Lambda 관리형 인스턴스 실행 환경**  
[Lambda 관리형 인스턴스](lambda-managed-instances-execution-environment.md)를 사용하는 경우 실행 환경은 Lambda(기본값) 함수와 비교할 때 중요한 차이가 있습니다. 관리형 인스턴스는 동시 간접 호출을 지원하고, 다른 수명 주기 모델을 사용하고, 고객 소유 인프라에서 실행됩니다. 관리형 인스턴스 실행 환경에 대한 자세한 내용은 [Lambda 관리형 인스턴스 실행 환경 이해](lambda-managed-instances-execution-environment.md) 항목을 참조하세요.

함수의 런타임은 [런타임 API](runtimes-api.md)를 사용하여 Lambda와 통신합니다. 익스텐션은 [익스텐션 API](runtimes-extensions-api.md)를 사용하여 Lambda와 통신합니다. 또한 확장은 [텔레메트리 API](telemetry-api.md)를 사용하여 함수의 로그 메시지와 기타 텔레메트리 데이터를 수신할 수 있습니다.



![\[실행 환경의 아키텍처 다이어그램.\]](http://docs.aws.amazon.com/ko_kr/lambda/latest/dg/images/telemetry-api-concept-diagram.png)


Lambda 함수를 생성할 때 함수에서 허용된 메모리 용량 및 최대 실행 시간 같은 구성 정보를 지정합니다. Lambda는 이 정보를 사용하여 실행 환경을 설정합니다.

함수의 런타임 및 각 외부 익스텐션은 실행 환경 내에서 실행되는 프로세스입니다. 권한, 리소스, 자격 증명 및 환경 변수는 함수와 익스텐션 간에 공유됩니다.

**Topics**
+ [

## Lambda 실행 환경 수명 주기
](#runtimes-lifecycle)
+ [

## 콜드 스타트 및 지연 시간
](#cold-start-latency)
+ [

## 프로비저닝된 동시성으로 콜드 스타트 감소
](#cold-starts-pc)
+ [

## 정적 초기화 최적화
](#static-initialization)

## Lambda 실행 환경 수명 주기
<a name="runtimes-lifecycle"></a>

![\[Lambda 수명 주기 단계: 초기화, 간접 호출, 종료\]](http://docs.aws.amazon.com/ko_kr/lambda/latest/dg/images/Overview-Successful-Invokes.png)


각 단계는 Lambda가 런타임 및 등록된 모든 익스텐션에 전송하는 이벤트로 시작됩니다. 런타임 및 각 익스텐션이 `Next` API 요청을 전송하여 완료를 나타냅니다. 런타임 및 각 익스텐션이 완료되고 대기 중인 이벤트가 없으면 Lambda는 실행 환경을 중지합니다.

**다음은 지속성 함수의 수명 주기 단계입니다.**
+ **초기화:** 표준 초기화 및 지속 상태 설정
+ **간접 호출:** 자동 체크포인트 지정을 사용하여 여러 단계 실행 포함 가능
+ **대기:** 함수는 리소스를 사용하지 않고 실행의 일시 중지 가능
+ **재개:** 함수가 마지막 체크포인트에서 다시 시작
+ **종료:** 지속 상태 및 리소스 정리

**Topics**
+ [

### 초기화 단계
](#runtimes-lifecycle-ib)
+ [

### Init 단계 중 실패
](#runtimes-lifecycle-init-errors)
+ [

### 복원 단계(Lambda SnapStart만 해당)
](#runtimes-lifecycle-restore)
+ [

### 간접 호출 단계
](#runtimes-lifecycle-invoke)
+ [

### 간접 호출 단계 중 실패
](#runtimes-lifecycle-invoke-with-errors)
+ [

### 종료 단계
](#runtimes-lifecycle-shutdown)

### 초기화 단계
<a name="runtimes-lifecycle-ib"></a>

`Init` 단계에서 Lambda는 다음 세 가지 작업을 수행합니다.
+ 모든 익스텐션 시작(`Extension init`)
+ 런타임 부트스트랩(`Runtime init`)
+ 함수의 정적 코드 실행(`Function init`)
+ 모든 체크포인트 전 [런타임 후크](snapstart-runtime-hooks.md) 실행(Lambda SnapStart만 해당)

`Init` 단계는 런타임 및 모든 익스텐션이 `Next` API 요청을 전송하여 준비되었음을 알린 후에 종료됩니다. `Init` 단계는 10초로 제한됩니다. 세 작업이 모두 10초 이내에 완료되지 않으면 Lambda는 첫 번째 함수 호출 시 구성된 함수 타임아웃으로 `Init` 단계를 다시 시도합니다.

[Lambda SnapStart](snapstart.md)가 활성화되면 함수 버전을 게시할 때 `Init` 단계가 발생합니다. Lambda는 초기화된 실행 환경의 메모리 및 디스크 상태 스냅샷을 저장하고 암호화된 스냅샷을 유지하며 짧은 지연 시간으로 액세스할 수 있도록 스냅샷을 캐싱합니다. 체크포인트 이전의 [런타임 후크](snapstart-runtime-hooks.md)가 있는 경우 코드는 `Init` 단계가 끝날 때 실행됩니다.

**참고**  
10초 제한 시간은 프로비저닝 동시성, SnapStart 또는 Lambda 관리형 인스턴스를 사용하는 함수에는 적용되지 않습니다. 프로비저닝 동시성, SnapStart 및 관리형 인스턴스 함수의 경우 초기화 코드를 최대 15분 동안 실행할 수 있습니다. 시간 제한은 130초 또는 구성된 함수 제한 시간(최대 900초) 중 더 높은 값입니다.

[프로비저닝된 동시성](https://docs.aws.amazon.com/lambda/latest/dg/provisioned-concurrency.html)을 사용하면 함수에 대한 PC 설정을 구성할 때 Lambda가 실행 환경을 초기화합니다. 또한 Lambda는 간접 호출에 앞서 초기화된 실행 환경을 항상 사용할 수 있도록 합니다. 함수의 간접 호출 단계와 초기화 단계 사이에 시간 격차가 발생할 수 있습니다. 함수의 런타임 및 메모리 구성에 따라 초기화된 실행 환경에서 첫 번째 간접 호출 시 가변적 지연 시간이 나타날 수도 있습니다.

온디맨드 동시성을 사용하는 함수의 경우 Lambda는 간접 호출 요청에 앞서 실행 환경을 초기화하는 경우가 있습니다. 이 경우 함수의 초기화 단계와 간접 호출 단계 사이에 시간 격차가 발생할 수 있습니다. 이 동작에 의존하지 않는 것이 좋습니다.

### Init 단계 중 실패
<a name="runtimes-lifecycle-init-errors"></a>

`Init` 단계 중에 함수가 충돌하거나 시간이 초과되면 Lambda는 `INIT_REPORT` 로그에 오류 정보를 생성합니다.

**Example — 타임아웃에 대한 INIT\$1REPORT 로그**  

```
INIT_REPORT Init Duration: 1236.04 ms Phase: init Status: timeout
```

**Example — 확장 실패에 대한 INIT\$1REPORT 로그**  

```
INIT_REPORT Init Duration: 1236.04 ms Phase: init Status: error Error Type: Extension.Crash
```

`Init` 단계가 성공하면 [SnapStart](snapstart.md) 또는 [프로비저닝된 동시성](provisioned-concurrency.md)이 활성화되지 않은 한 Lambda는 `INIT_REPORT` 로그를 내보내지 않습니다. SnapStart 및 프로비저닝된 동시성 함수는 항상 `INIT_REPORT`를 내보냅니다. 자세한 내용은 [Lambda SnapStart 모니터링](snapstart-monitoring.md) 섹션을 참조하세요.

### 복원 단계(Lambda SnapStart만 해당)
<a name="runtimes-lifecycle-restore"></a>

[SnapStart](snapstart.md) 함수를 처음 간접 호출하고 함수가 스케일 업되면 Lambda는 이 함수를 처음부터 초기화하는 대신 유지된 스냅샷에서 새 실행 환경을 재개합니다. 복원 후 [런타임 후크](snapstart-runtime-hooks.md)가 있는 경우 코드는 `Restore` 단계가 끝날 때 실행됩니다. 복원 후 런타임 후크 지속 시간에 대해 요금이 청구됩니다. 런타임이 로드되고 복원 후 런타임 후크가 제한 시간(10초) 내에 완료되어야 합니다. 그렇지 않으면 SnapStartTimeoutException이 발생합니다. `Restore` 단계가 완료되면 Lambda가 함수 핸들러([간접 호출 단계](#runtimes-lifecycle-invoke))를 간접적으로 간접 호출합니다.

#### 복원 단계 중 실패
<a name="runtimes-lifecycle-restore-errors"></a>

`Restore` 단계가 실패하면 Lambda는 `RESTORE_REPORT` 로그에 오류 정보를 생성합니다.

**Example — 타임아웃에 대한 RESTORE\$1REPORT 로그**  

```
RESTORE_REPORT Restore Duration: 1236.04 ms Status: timeout
```

**Example — 런타임 후크 실패에 대한 RESTORE\$1REPORT 로그**  

```
RESTORE_REPORT Restore Duration: 1236.04 ms Status: error Error Type: Runtime.ExitError
```

`RESTORE_REPORT` log에 대한 자세한 내용은 [Lambda SnapStart 모니터링](snapstart-monitoring.md)을 참조하십시오.

### 간접 호출 단계
<a name="runtimes-lifecycle-invoke"></a>

`Next` API 요청에 대한 응답으로 Lambda 함수가 간접 호출되면 Lambda는 런타임과 각 익스텐션에 `Invoke` 이벤트를 전송합니다.

함수의 제한 시간 설정은 전체 `Invoke` 단계의 기간을 제한합니다. 예를 들어 함수 제한 시간을 360초로 설정하면 함수와 모든 익스텐션이 360초 내에 완료되어야 합니다. 독립적인 간접 호출 후 단계는 없습니다. 기간은 모든 호출 시간(런타임 \$1 익스텐션)의 합계이며 함수와 모든 익스텐션의 실행이 완료될 때까지 계산되지 않습니다.

간접 호출 단계는 런타임 및 모든 익스텐션이 `Next` API 요청을 전송하여 완료되었음을 알린 후에 종료됩니다.

### 간접 호출 단계 중 실패
<a name="runtimes-lifecycle-invoke-with-errors"></a>

`Invoke` 단계 중에 Lambda 함수가 충돌하거나 시간이 초과되면 Lambda는 실행 환경을 재설정합니다. 다음 다이어그램은 간접 호출 실패 시 Lambda 실행 환경 동작을 보여줍니다.

![\[실행 환경 예시: 초기화, 간접 호출, 오류가 있는 간접 호출, 간접 호출, 종료\]](http://docs.aws.amazon.com/ko_kr/lambda/latest/dg/images/Overview-Invoke-with-Error.png)


이전 다이어그램에서
+ 첫 번째 단계는 오류 없이 실행되는 **INIT** 단계입니다.
+ 두 번째 단계는 오류 없이 실행되는 **INVOKE** 단계입니다.
+ 어느 시점에서 함수에 간접 호출 실패가 발생한다고 가정해 보겠습니다. 일반적인 원인으로는 함수 시간 초과, 런타임 오류, 메모리 부족, VPC 연결 문제, 권한 오류, 동시성 제한, 다양한 구성 문제 등이 있습니다. 가능한 간접 호출 실패의 전체 목록은 [Lambda의 호출 문제 해결](troubleshooting-invocation.md) 섹션을 참조하세요. **INVOKE WITH ERROR**라고 표시된 세 번째 단계가 이 시나리오를 보여줍니다. 이 경우 Lambda 서비스가 재설정을 수행합니다. 재설정은 `Shutdown` 이벤트처럼 동작합니다. 먼저 Lambda는 런타임을 종료한 다음 등록된 각 외부 익스텐션에 `Shutdown` 이벤트를 전송합니다. 이벤트에는 종료 이유가 포함됩니다. 이 환경이 새 호출에 사용되는 경우 Lambda는 익스텐션과 런타임을 다음 호출과 함께 다시 초기화합니다.

  Lambda 재설정으로 다음 초기화 단계 전에 `/tmp` 디렉터리의 내용이 지워지지 않는다는 점에 유의하세요. 이 동작은 일반 종료 단계와 동일합니다.
**참고**  
AWS는 현재 Lambda 서비스에 대한 변경 사항을 구현하고 있습니다. 이러한 변경으로 인해, AWS 계정의 여러 Lambda 함수에서 내보내는 시스템 로그 메시지와 추적 세그먼트의 구조와 내용 간에 약간의 차이가 있을 수 있습니다.  
함수의 시스템 로그 구성이 일반 텍스트로 설정된 경우, 이 변경은 함수에서 간접 호출 실패가 발생할 때 CloudWatch Logs에 캡처되는 로그 메시지에 영향을 줍니다. 다음 예는 이전 형식과 새 형식의 로그 출력을 모두 보여줍니다.  
이러한 변경 사항은 앞으로 몇 주 동안 구현되며, 중국 및 GovCloud 리전을 제외한 모든 AWS 리전의 모든 기능은 새로운 형식의 로그 메시지 및 추적 세그먼트를 사용하도록 전환됩니다.

    
**Example CloudWatch Logs 로그 출력(런타임 또는 확장 충돌) - 이전 스타일**  

  ```
  START RequestId: c3252230-c73d-49f6-8844-968c01d1e2e1 Version: $LATEST
  RequestId: c3252230-c73d-49f6-8844-968c01d1e2e1 Error: Runtime exited without providing a reason
  Runtime.ExitError
  END RequestId: c3252230-c73d-49f6-8844-968c01d1e2e1
  REPORT RequestId: c3252230-c73d-49f6-8844-968c01d1e2e1 Duration: 933.59 ms Billed Duration: 934 ms Memory Size: 128 MB Max Memory Used: 9 MB
  ```  
**Example CloudWatch Logs 로그 출력(함수 제한 시간) - 이전 스타일**  

  ```
  START RequestId: b70435cc-261c-4438-b9b6-efe4c8f04b21 Version: $LATEST
  2024-03-04T17:22:38.033Z b70435cc-261c-4438-b9b6-efe4c8f04b21 Task timed out after 3.00 seconds
  END RequestId: b70435cc-261c-4438-b9b6-efe4c8f04b21
  REPORT RequestId: b70435cc-261c-4438-b9b6-efe4c8f04b21 Duration: 3004.92 ms Billed Duration: 3117 ms Memory Size: 128 MB Max Memory Used: 33 MB Init Duration: 111.23 ms
  ```

  CloudWatch 로그의 새 형식에는 `REPORT` 줄에 `status` 필드가 추가로 포함됩니다. 런타임 또는 확장 충돌이 발생하는 경우, 해당 `REPORT` 줄에는 `ErrorType` 필드도 포함됩니다.

    
**Example CloudWatch Logs 로그 출력(런타임 또는 확장 충돌) - 새 스타일**  

  ```
  START RequestId: 5b866fb1-7154-4af6-8078-6ef6ca4c2ddd Version: $LATEST
  END RequestId: 5b866fb1-7154-4af6-8078-6ef6ca4c2ddd
  REPORT RequestId: 5b866fb1-7154-4af6-8078-6ef6ca4c2ddd Duration: 133.61 ms Billed Duration: 214 ms Memory Size: 128 MB Max Memory Used: 31 MB Init Duration: 80.00 ms Status: error Error Type: Runtime.ExitError
  ```  
**Example CloudWatch Logs 로그 출력(함수 제한 시간) - 새 스타일**  

  ```
  START RequestId: 527cb862-4f5e-49a9-9ae4-a7edc90f0fda Version: $LATEST
  END RequestId: 527cb862-4f5e-49a9-9ae4-a7edc90f0fda
  REPORT RequestId: 527cb862-4f5e-49a9-9ae4-a7edc90f0fda Duration: 3016.78 ms Billed Duration: 3101 ms Memory Size: 128 MB Max Memory Used: 31 MB Init Duration: 84.00 ms Status: timeout
  ```
+ 네 번째 단계는 간접 호출 실패 직후의 **간접 호출** 단계를 나타냅니다. 여기서 Lambda는 **INIT** 단계를 다시 실행하여 환경을 다시 초기화합니다. 이를 억제된 초기화라고 합니다.** 억제된 초기화가 발생하는 경우 Lambda는 CloudWatch 로그에 추가 **INIT** 단계를 명시적으로 보고하지는 않습니다. 대신 REPORT 줄의 지속 시간에 추가 **INIT **기간 \$1 간접 호출**** 기간이 포함되어 있음을 알 수 있습니다. 예를 들어 CloudWatch에 다음과 같은 로그가 표시되어 있다고 가정하겠습니다.

  ```
  2022-12-20T01:00:00.000-08:00 START RequestId: XXX Version: $LATEST 
  2022-12-20T01:00:02.500-08:00 END RequestId: XXX 
  2022-12-20T01:00:02.500-08:00 REPORT RequestId: XXX Duration: 3022.91 ms 
  Billed Duration: 3000 ms Memory Size: 512 MB Max Memory Used: 157 MB
  ```

  이 예제에서 REPORT 타임스탬프와 START 타임스탬프 간의 차이는 2.5초입니다. 이는 Lambda가 수행한 추가 **INIT**(억제된 초기화)를 고려하지 않기 때문에 보고된 지속 시간인 3022.91 밀리초와 일치하지 않습니다. 이 예시에서는 실제 **간접 호출** 단계에 2.5초가 걸렸다고 추론할 수 있습니다.

  이 동작에 대해 더 자세히 알아보려면 [텔레메트리 API를 사용하여 확장의 실시간 텔레메트리 데이터에 액세스](telemetry-api.md)을 사용하면 됩니다. Telemetry API는 간접 호출 단계 사이에 억제된 초기화가 발생할 때마다 `INIT_START`, `INIT_RUNTIME_DONE`, `INIT_REPORT`, `phase=invoke` 이벤트를 내보냅니다.
+ 다섯 번째 단계는 오류 없이 실행되는 **SHUTDOWN** 단계를 나타냅니다.

### 종료 단계
<a name="runtimes-lifecycle-shutdown"></a>

Lambda는 런타임을 종료하려고 할 때 `Shutdown` 이벤트를 등록된 각 외부 익스텐션에 전송합니다. 익스텐션은 이 시간 동안 최종 정리 작업을 수행할 수 있습니다. `Shutdown` 이벤트는 `Next` API 요청에 대한 응답입니다.

**기간 제한**: `Shutdown` 단계의 최대 기간은 등록된 익스텐션 구성에 따라 다릅니다.
+ 0밀리초 - 등록된 익스텐션이 없는 함수
+ 500밀리초 - 등록된 내부 익스텐션이 하나 있는 함수
+ 2,000밀리초 - 등록된 외부 익스텐션이 하나 이상 있는 함수

런타임 또는 익스텐션이 제한 시간 내에 `Shutdown` 이벤트에 응답하지 않는 경우 Lambda는 `SIGKILL` 신호를 사용하여 프로세스를 종료합니다.

함수와 모든 익스텐션이 완료된 후 Lambda는 다른 함수 호출을 예상하여 일정 시간 동안 실행 환경을 유지합니다. 그러나 Lambda는 몇 시간마다 실행 환경을 종료하여 런타임 업데이트 및 유지 관리를 허용하며, 이는 지속적으로 간접 호출되는 함수에 대해서도 동일합니다. 실행 환경이 무기한 지속될 것이라고 가정하면 안 됩니다. 자세한 내용은 [함수에서 상태 비저장 구현](concepts-application-design.md#statelessness-functions) 섹션을 참조하세요.

함수가 다시 간접적으로 호출되면 Lambda는 재사용을 위해 환경을 재개합니다. 실행 환경을 재사용하는 것은 다음과 같은 의미를 가집니다.
+ 함수의 핸들러 메서드 외부에서 선언된 객체는 함수가 다시 간접 호출될 때 추가로 최적화가 되도록 초기화된 상태로 유지됩니다. 예를 들어 Lambda 함수가 연결을 재설정하는 대신 데이터베이스 연결을 설정하면 원래 연결이 후속 호출에 사용됩니다. 코드에 로직을 추가하여 연결을 새로 생성하기에 앞서 연결이 이미 존재하는지 확인하는 것이 좋습니다.
+ 각 실행 환경은 `/tmp` 디렉터리에 512MB에서 10,240MB 사이 1MB 단위로 디스크 공간을 제공합니다. 디렉터리 콘텐츠는 실행 환경이 일시 중지되어도 그대로 유지되기 때문에 일시적인 캐시를 여러 호출에서 사용할 수 있습니다. 코드를 추가하여 캐시에 저장한 데이터가 포함되어 있는지 확인할 수 있습니다. 배포 크기 제한에 대한 자세한 내용은 [Lambda 할당량Lambda 할당량](gettingstarted-limits.md) 섹션을 참조하세요.
+ Lambda 함수에 의해 초기화되었고 함수 종료 시 완료되지 않은 백그라운드 프로세스 또는 콜백은 Lambda가 실행 환경을 재사용하는 경우에 재개됩니다. 코드가 종료되려면 먼저 코드의 백그라운드 프로세스 또는 콜백이 완료되어야 합니다.

## 콜드 스타트 및 지연 시간
<a name="cold-start-latency"></a>

Lambda가 Lambda API를 통해 함수를 실행하라는 요청을 수신하면 서비스는 먼저 실행 환경을 준비합니다. 이 초기화 단계에서 서비스는 코드를 다운로드하고, 환경을 시작하고, 기본 핸들러 외부에서 모든 초기화 코드를 실행합니다. 마지막으로 Lambda는 핸들러 코드를 실행합니다.

![\[성능 최적화 그림 1\]](http://docs.aws.amazon.com/ko_kr/lambda/latest/dg/images/perf-optimize-figure-1.png)


이 다이어그램에서 코드를 다운로드하고 환경을 설정하는 처음 두 단계는 '콜드 스타트'라고 불리기도 합니다. [이 기간에는 요금이 부과되며](https://aws.amazon.com/blogs/compute/aws-lambda-standardizes-billing-for-init-phase/) 전체 간접 호출 기간에 지연 시간이 추가됩니다.

간접 호출이 완료되면 실행 환경이 동결됩니다. 리소스 관리 및 성능을 개선하기 위해 Lambda는 일정 기간 동안 실행 환경을 유지합니다. 이 기간 동안 동일한 함수에 대해 또 다른 요청이 도착하면 Lambda가 환경을 재사용할 수 있습니다. 실행 환경이 이미 완전히 설정되어 있으므로 이 두 번째 요청은 일반적으로 더 빨리 완료됩니다. 이를 '웜 스타트'라고 합니다.

콜드 스타트는 일반적으로 간접 호출의 1% 미만에서 발생합니다. 콜드 스타트 지속 시간은 100밀리초 미만에서 1초 넘게까지 다양합니다. 일반적으로 콜드 스타트는 프로덕션 워크로드보다 개발 및 테스트 함수에서 더 흔합니다. 일반적으로 개발 및 테스트 함수에서 간접 호출 횟수가 더 적기 때문입니다.

## 프로비저닝된 동시성으로 콜드 스타트 감소
<a name="cold-starts-pc"></a>

워크로드에 대해 예측 가능한 함수 시작 시간이 필요한 경우 가능한 지연 시간을 최소화하려면 [프로비저닝된 동시성](provisioned-concurrency.md)을 사용하는 것이 좋습니다. 이 기능은 실행 환경을 미리 초기화하여 콜드 스타트를 줄입니다.

예를 들어 프로비저닝된 동시성이 6인 함수에서는 6개의 실행 환경이 미리 워밍됩니다.

![\[성능 최적화 그림 4\]](http://docs.aws.amazon.com/ko_kr/lambda/latest/dg/images/perf-optimize-figure-4.png)


## 정적 초기화 최적화
<a name="static-initialization"></a>

정적 초기화는 함수에서 핸들러 코드 실행이 시작되기 전에 수행됩니다. 이는 기본 핸들러 외부에 있는 사용자가 제공하는 초기화 코드입니다. 이 코드는 라이브러리 및 종속성을 가져오고 구성을 설정하며 다른 서비스에 대한 연결을 초기화하는 데 자주 사용됩니다.

다음 Python 예제에서는 간접 호출 중 `lambda_handler` 함수가 실행되기 전에 초기화 단계에서 모듈을 가져오고 구성하며 Amazon S3 클라이언트를 생성하는 방법을 보여줍니다.

```
import os
import json
import cv2
import logging
import boto3

s3 = boto3.client('s3')
logger = logging.getLogger()
logger.setLevel(logging.INFO)

def lambda_handler(event, context):

  # Handler logic...
```

함수 실행 전 지연 시간에 가장 많이 기여하는 요인은 초기화 코드입니다. 이 코드는 새 실행 환경이 처음 생성될 때 실행됩니다. 간접 호출이 웜 실행 환경을 사용하는 경우 초기화 코드가 다시 실행되지 않습니다. 초기화 코드 지연 시간에 영향을 미치는 요인은 다음과 같습니다.
+ 가져온 라이브러리 및 종속 항목과 Lambda 계층 관점에서 함수 패키지의 크기.
+ 코드 및 초기화 작업의 양.
+ 연결 및 기타 리소스를 설정할 때 라이브러리 및 기타 서비스의 성능.

정적 초기화 지연 시간을 최적화하기 위해 개발자가 수행할 수 있는 여러 단계가 있습니다. 함수에 객체 및 연결이 많은 경우 단일 함수를 여러 특수 함수로 리아키텍팅할 수 있습니다. 이들은 개별적으로 더 작으며 각각 초기화 코드가 적습니다.

함수는 필요한 라이브러리 및 종속 항목만 가져와야 합니다. 예를 들어 AWS SDK에서 Amazon DynamoDB만 사용하는 경우 전체 SDK 대신 개별 서비스가 필요할 수 있습니다. 다음 세 가지 예제를 비교합니다.

```
// Instead of const AWS = require('aws-sdk'), use:
const DynamoDB = require('aws-sdk/clients/dynamodb')

// Instead of const AWSXRay = require('aws-xray-sdk'), use:
const AWSXRay = require('aws-xray-sdk-core')

// Instead of const AWS = AWSXRay.captureAWS(require('aws-sdk')), use:
const dynamodb = new DynamoDB.DocumentClient()
AWSXRay.captureAWSClient(dynamodb.service)
```

정적 초기화는 함수가 동일한 실행 환경에 대한 여러 간접 호출을 통해 연결을 재사용할 수 있도록 데이터베이스 연결을 여는 데 가장 적합한 위치이기도 합니다. 그러나 함수의 특정 실행 경로에서만 사용되는 객체가 많을 수 있습니다. 이 경우 전역 범위에서 변수를 지연 로드하여 정적 초기화 지속 시간을 줄일 수 있습니다.

컨텍스트별 정보에 대해서는 전역 변수를 사용하지 마세요. 함수에 단일 간접 호출의 수명 동안에만 사용되고 다음 간접 호출을 위해 재설정되는 전역 변수가 있는 경우 핸들러에 로컬로 존재하는 변수 범위를 사용합니다. 그러면 여러 간접 호출에서 전역 변수 누출을 방지하고 정적 초기화 성능도 개선됩니다.

# Lambda를 사용하여 이벤트 기반 아키텍처 생성
<a name="concepts-event-driven-architectures"></a>

이벤트는 Lambda 함수가 실행되도록 트리거하는 모든 요소입니다. 이벤트는 다이렉트 간접 호출(푸시)과 이벤트 소스 매핑(풀)의 두 가지 방식으로 Lambda 함수를 트리거할 수 있습니다.

많은 AWS 서비스는 Lambda 함수를 다이렉트로 간접 호출할 수 있습니다. 이러한 서비스는 이벤트를 Lambda 함수로 *푸시*합니다. 함수를 트리거하는 이벤트로는 거의 모든 것이 가능하며, API Gateway를 통한 HTTP 요청, EventBridge 규칙으로 관리되는 일정, AWS IoT 이벤트 또는 Amazon S3 이벤트 등이 있습니다. 이벤트 소스 매핑을 사용할 경우, Lambda는 대기열 또는 스트림에서 이벤트를 능동적으로 가져옵니다(또는 *끌어옵니다*). 지원되는 서비스의 이벤트를 확인하도록 Lambda를 구성하면 Lambda가 함수의 폴링 및 간접 호출을 처리합니다.

함수에 전달되면 이벤트는 JSON 형식으로 구조화됩니다. JSON 구조는 생성하는 서비스와 이벤트 유형에 따라 달라집니다. 표준 Lambda 함수 간접 호출은 최대 15분(또는 [지속성 함수](durable-functions.md)의 경우 최대 1년) 동안 지속될 수 있지만 Lambda는 1초 이하 동안 지속되는 짧은 간접 호출에 가장 적합합니다. 특히 이벤트 기반 아키텍처에서 그러하며, 각 Lambda 함수는 마이크로서비스로 취급되며, 이는 좁은 특정 지침 세트를 수행하는 역할을 합니다.

**참고**  
이벤트 중심 아키텍처는 네트워크를 사용하여 여러 시스템에서 통신하므로 지연 시간이 가변적입니다. 실시간 거래 시스템과 같이 지연 시간이 매우 짧은 워크로드의 경우 이 설계가 최선의 선택이 아닐 수 있습니다. 그러나 확장성 및 가용성이 뛰어난 워크로드이나 예측할 수 없는 트래픽 패턴이 있는 워크로드의 경우 이벤트 중심 아키텍처는 이러한 요구 사항을 충족하는 효과적인 방법을 제공할 수 있습니다.

**Topics**
+ [

## 이벤트 중심 아키텍처의 이점
](#event-driven-benefits)
+ [

## 이벤트 중심 아키텍처의 장단점
](#event-driven-tradeoffs)
+ [

## Lambda 기반 이벤트 기반 애플리케이션에서의 안티 패턴
](#event-driven-anti-patterns)

## 이벤트 중심 아키텍처의 이점
<a name="event-driven-benefits"></a>

Lambda는 이벤트 기반 아키텍처에서 두 가지 간접 호출 메서드를 지원합니다.

1. 다이렉트 간접 호출(푸시 메서드): AWS 서비스는 Lambda 함수를 직접적으로 트리거합니다. 예제:
   + Amazon S3는 파일이 업로드될 때 함수를 트리거합니다.
   + API Gateway는 HTTP 요청을 수신할 때 함수를 트리거합니다.

1. 이벤트 소스 매핑(풀 메서드): Lambda는 이벤트를 검색하고 함수를 간접적으로 호출합니다. 예제:
   + Lambda는 Amazon SQS 대기열에서 메시지를 검색하고 함수를 간접적으로 호출합니다.
   + Lambda는 DynamoDB 스트림에서 레코드를 읽고 함수를 간접적으로 호출합니다.

아래 설명과 같이 두 가지 메서드 모두 이벤트 기반 아키텍처의 이점에 기여합니다.

### 폴링 및 웹후크를 이벤트로 대체
<a name="polling-webhooks-events"></a>

많은 기존 아키텍처는 폴링 및 웹후크 메커니즘을 사용하여 여러 구성 요소 사이에서 상태를 통신합니다. 폴링은 새 데이터가 사용 가능하게 되는 시점과 다운스트림 서비스와의 동기화 사이에 지연이 있기 때문에 업데이트를 가져오는 데 매우 비효율적일 수 있습니다. 웹후크는 통합하려는 다른 마이크로서비스에서 항상 지원되지는 않습니다. 사용자 지정 권한 부여 및 인증 구성이 필요할 수도 있습니다. 두 경우 모두 개발 팀의 추가 작업 없이 온디맨드 방식으로 조정하기가 어렵습니다.

![\[이벤트 중심 아키텍처 그림 7\]](http://docs.aws.amazon.com/ko_kr/lambda/latest/dg/images/event-driven-architectures-figure-7.png)


이 두 메커니즘은 이벤트로 대체될 수 있으며, 이 이벤트는 필터링 및 라우팅되고 소비 마이크로서비스로 푸시될 수 있습니다. 이 접근 방식을 사용하면 대역폭 소비, CPU 사용률 그리고 잠재적으로 비용이 감소할 수 있습니다. 또한 이러한 아키텍처는 각 기능 단위가 작고 종종 코드가 적기 때문에 복잡성을 줄일 수 있습니다.

![\[이벤트 중심 아키텍처 그림 8\]](http://docs.aws.amazon.com/ko_kr/lambda/latest/dg/images/event-driven-architectures-figure-8.png)


이벤트 중심 아키텍처를 사용하면 거의 실시간에 가까운 시스템을 더 쉽게 설계할 수 있으므로 조직이 배치 기반 처리에서 벗어날 수 있습니다. 이벤트는 애플리케이션의 상태가 변경될 때 생성되므로 마이크로서비스의 사용자 지정 코드는 단일 이벤트 처리를 수행하도록 설계되어야 합니다. 규모 조정은 Lambda 서비스에서 처리되므로 이 아키텍처에서는 사용자 지정 코드를 변경하지 않고도 트래픽의 상당한 증가를 처리할 수 있습니다. 이벤트가 스케일 업되면 이벤트를 처리하는 컴퓨팅 계층도 스케일 업됩니다.

### 복잡성 감소
<a name="complexity"></a>

마이크로서비스를 사용하면 개발자 및 아키텍트가 복잡한 워크플로를 단순화할 수 있습니다. 예를 들어 전자 상거래 모놀리스는 별도의 인벤토리, 주문 이행 및 회계 서비스에서 주문 수락 및 결제 프로세스로 분류될 수 있습니다. 모놀리스에서 관리 및 오케스트레이션하기 복잡한 요소는 이벤트와 비동기식으로 통신하는 일련의 분리된 서비스가 됩니다.

![\[이벤트 중심 아키텍처 그림 9\]](http://docs.aws.amazon.com/ko_kr/lambda/latest/dg/images/event-driven-architectures-figure-9.png)


또한 이 접근 방식을 사용하면 서로 다른 속도로 데이터를 처리하는 서비스를 통합할 수 있습니다. 이 경우 주문 수락 마이크로서비스는 메시지를 Amazon SQS 대기열에서 버퍼링하여 대량의 수신 주문을 저장할 수 있습니다.

결제 처리 서비스(결제 처리의 복잡성으로 인해 일반적으로 속도가 느림)는 Amazon SQS 대기열에서 메시지 스트림을 안정적으로 가져올 수 있습니다. AWS Step Functions 항목을 사용하여 복잡한 재시도 및 오류 처리 로직을 오케스트레이션하고 수십만 건의 주문에 대해 활성 결제 워크플로를 조정할 수 있습니다.

**대안 접근 방식:** 표준 프로그래밍 언어를 사용한 오케스트레이션의 경우 [Lambda 지속성 함수](durable-functions.md)를 사용할 수 있습니다. 지속성 함수를 사용하면 주문 접수, 결제 처리, 알림 로직을 코드로 작성하고 자동 체크포인팅 및 재시도 기능을 활용할 수 있습니다. 이 접근 방식은 워크플로가 주로 Lambda 함수를 포함하고 코드에 오케스트레이션 로직을 유지하는 것을 선호하는 경우 매우 효과적입니다.

### 확장성 개선
<a name="scalability-extensibility"></a>

마이크로서비스는 일반적으로 Amazon SNS 및 Amazon SQS와 같은 메시징 서비스에 게시되는 이벤트를 생성합니다. 이는 마이크로서비스 사이에서 탄력적 버퍼와 같이 작동하며 트래픽이 증가할 때 조정을 처리하는 데 도움이 됩니다. 그런 다음, Amazon EventBridge와 같은 서비스에서 규칙에 정의된 대로 이벤트의 콘텐츠에 따라 메시지를 필터링 및 라우팅할 수 있습니다. 따라서 이벤트 중심 애플리케이션은 모놀리식 애플리케이션보다 확장성이 뛰어나고 중복성을 더 많이 제공할 수 있습니다.

또한 이 시스템은 확장성이 매우 뛰어나 주문 처리 및 결제 처리 마이크로서비스에 영향을 주지 않고 다른 팀에서 기능을 확장하고 추가할 수 있습니다. EventBridge를 사용하여 이벤트를 게시하면 이 애플리케이션은 인벤토리 마이크로서비스와 같은 기존 시스템과 통합되지만 향후 모든 애플리케이션이 이벤트 소비자로 통합될 수도 있습니다. 이벤트 생산자는 이벤트 소비자에 대한 지식이 없습니다. 이러한 지식을 보유하면 마이크로서비스 로직을 단순화하는 데 도움이 될 수 있습니다.

## 이벤트 중심 아키텍처의 장단점
<a name="event-driven-tradeoffs"></a>

### 가변 지연 시간
<a name="variable-latency"></a>

단일 디바이스에서 동일한 메모리 공간 내 모든 항목을 처리할 수 있는 모놀리식 애플리케이션과 달리 이벤트 중심 애플리케이션은 여러 네트워크 사이에서 통신합니다. 이 설계에서는 가변 지연 시간이 도입됩니다. 지연 시간을 최소화하도록 애플리케이션을 엔지니어링할 수 있지만 모놀리식 애플리케이션은 확장성 및 가용성을 희생하면서 지연 시간을 줄이도록 거의 항상 최적화될 수 있습니다.

은행에서 높은 빈도의 거래 애플리케이션 또는 창고에서 밀리초 미만의 로봇 자동화와 같이 일관되게 지연 시간이 짧은 성능이 필요한 워크로드는 이벤트 중심 아키텍처에 적합한 후보가 아닙니다.

### 최종 일관성
<a name="eventual-consistency"></a>

이벤트는 상태의 변화를 나타내고, 주어진 시점에 아키텍처의 다양한 서비스를 통해 많은 이벤트가 진행되는데 이러한 워크로드는 종종 [최종적으로 일관](https://en.wikipedia.org/wiki/Eventual_consistency)된다고 간주합니다. 따라서 트랜잭션을 처리하거나 중복을 처리하거나 시스템의 정확한 전체 상태를 결정하는 것이 더 복잡해집니다.

일부 워크로드에 최종적으로 일관(예: 현재 시간의 총 주문 수) 또는 강력하게 일관(예: 현재 인벤토리)과 같은 요구 사항의 조합이 포함되어 있습니다. 강력한 데이터 일관성이 요구되는 워크로드의 경우 이를 지원하는 아키텍처 패턴이 있습니다. 예제:
+ DynamoDB는 경우에 따라 지연 시간이 높을 때 [강력하게 일관된 읽기](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadConsistency.html)를 제공하여 기본 모드보다 더 높은 처리량을 소비합니다. DynamoDB는 [ 트랜잭션을 지원](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transactions.html)하여 데이터 일관성을 유지할 수도 있습니다.
+ 관계형 데이터베이스는 DynamoDB와 같은 NoSQL 데이터 저장소보다 일반적으로 확장성이 낮지만 [ACID 속성](https://en.wikipedia.org/wiki/ACID)이 필요한 기능에 대해 Amazon RDS를 사용할 수 있습니다. [Amazon RDS Proxy](https://aws.amazon.com/rds/proxy/)는 Lambda 함수와 같은 임시 소비자의 연결 풀링 및 규모 조정을 관리하는 데 도움이 될 수 있습니다.

이벤트 중심 아키텍처는 일반적으로 대규모 데이터 배치 대신 개별 이벤트를 중심으로 설계됩니다. 일반적으로 워크플로는 여러 이벤트에서 동시에 작동하는 대신 개별 이벤트 또는 실행 흐름의 단계를 관리하도록 설계되었습니다. 서버리스에서는 배치 처리보다 실시간 이벤트 처리가 선호되며, 이때 배치를 더 작은 증분 업데이트로 대체합니다. 그러면 워크로드의 가용성 및 확장성이 증가하지만 이벤트가 다른 이벤트를 인식하기가 더 어려워집니다.

### 직접 호출자에게 값 반환
<a name="values-callers"></a>

대부분의 경우 이벤트 중심 애플리케이션은 비동기식입니다. 즉, 직접 호출자 서비스는 다른 작업을 계속 진행하기 전에 다른 서비스의 요청을 기다리지 않습니다. 이는 확장성 및 유연성을 지원하는 이벤트 중심 아키텍처의 기본적인 특성입니다. 즉, 반환 값 또는 워크플로 결과를 전달하는 것이 동기식 실행 흐름보다 더 복잡하다는 뜻입니다.

프로덕션 시스템에서 대부분의 Lambda 간접 호출은 [비동기식](invocation-async.md)으로 Amazon S3 또는 Amazon SQS와 같은 서비스의 이벤트에 응답합니다. 이러한 경우 이벤트 처리의 성공 또는 실패 여부가 값을 반환하는 것보다 더 중요하기도 합니다. Lambda에서 [Dead Letter Queue](https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html)(DLQ)와 같은 기능이 제공되므로 직접 호출자에게 알리지 않고도 실패한 이벤트를 식별 및 재시도할 수 있습니다.

### 서비스 및 함수에서 디버깅
<a name="services-functions"></a>

또한 이벤트 중심 시스템을 디버깅하는 작업은 모놀리식 애플리케이션과 비교해도 다릅니다. 오류가 발생하는 경우 이벤트를 전달하는 여러 시스템 및 서비스에서 여러 서비스의 정확한 상태를 기록하고 재현하는 것이 불가능합니다. 각 서비스 및 함수 간접 호출에는 별도의 로그 파일이 있기 때문에 오류를 일으킨 특정 이벤트에 발생한 상황을 확인하는 것이 더 복잡할 수 있습니다.

이벤트 중심 시스템에서 성공적인 디버깅 접근 방식을 빌드하려는 경우 세 가지 중요한 요구 사항이 있습니다. 첫째, 강력한 로깅 시스템이 중요합니다. 이는 AWS 서비스 전반에 제공되고 Amazon CloudWatch에 의해 Lambda 함수에 임베드됩니다. 둘째, 이러한 시스템에서는 로그를 검색할 때 도움이 되도록 모든 이벤트의 트랜잭션 식별자가 전체 트랜잭션 동안 각 단계에서 로깅되어야 합니다.

마지막으로, AWS X-Ray 항목과 같은 디버깅 및 모니터링 서비스를 사용하여 로그의 구문 분석 및 분석을 자동화하는 것이 좋습니다. 그러면 여러 Lambda 간접 호출 및 서비스에서 로그를 사용할 수 있으므로 문제의 근본 원인을 훨씬 더 쉽게 파악할 수 있습니다. 문제 해결을 위해 X-Ray를 사용하는 방법에 대한 자세한 내용은 [ 문제 해결 연습](lambda-troubleshooting.md)을 참조하세요.

## Lambda 기반 이벤트 기반 애플리케이션에서의 안티 패턴
<a name="event-driven-anti-patterns"></a>

Lambda를 사용하여 이벤트 중심 아키텍처를 구축할 때는 다음과 같은 일반적인 안티 패턴을 방지하세요. 이러한 패턴은 작동하지만 비용과 복잡성을 높일 수 있습니다.

### Lambda 모놀리스
<a name="monolith"></a>

기존 서버, Amazon EC2 인스턴스 또는 Elastic Beanstalk 애플리케이션에서 마이그레이션된 많은 애플리케이션에서 개발자는 기존 코드를 '리프트 앤 시프트'합니다. 이로 인해 모든 이벤트에 대해 트리거되는 모든 애플리케이션 로직을 포함하는 단일 Lambda 함수가 생성되기도 합니다. 기본 웹 애플리케이션의 경우 모놀리식 Lambda 함수는 모든 API Gateway 경로를 처리하고 필요한 모든 다운스트림 리소스와 통합됩니다.

![\[이벤트 중심 아키텍처 그림 13\]](http://docs.aws.amazon.com/ko_kr/lambda/latest/dg/images/event-driven-architectures-figure-13.png)


이 접근 방식에는 몇 가지 단점이 있습니다.
+  **패키지 크기**-Lambda 함수에는 모든 경로에 대해 가능한 모든 코드가 포함되어 있어 Lambda 서비스의 실행 속도가 느려지기 때문에 Lambda 함수가 훨씬 더 클 수 있습니다.
+  **적용하기 어려운 최소 권한** – 함수의 [실행 역할](lambda-intro-execution-role.md)은 모든 경로에 필요한 모든 리소스에 대한 권한을 허용하여 매우 포괄적인 권한을 구성해야 합니다. 이는 보안 문제입니다. 기능적 모놀리스의 많은 경로에 부여된 모든 권한이 필요한 것은 아닙니다.
+  **더 어려운 업그레이드**-프로덕션 시스템에서 단일 함수에 대한 업그레이드가 더 위험하며 전체 애플리케이션이 작동하지 않을 수 있습니다. Lambda 함수에서 단일 경로를 업그레이드하는 작업은 전체 함수에 대한 업그레이드입니다.
+  **더 어려운 유지 관리**-모놀리식 코드 리포지토리이기 때문에 여러 개발자가 서비스에서 작업하기 더 어렵습니다. 또한 개발자의 인지 부담이 늘어나고 코드에 대한 적절한 테스트 범위를 생성하기가 더 어렵습니다.
+  **더 어려운 코드 재사용**-재사용 가능한 라이브러리를 모놀리스와 분리하는 것이 더 어려워져 코드 재사용이 더 까다로워질 수 있습니다. 더 많은 프로젝트를 개발하고 지원하는 경우 코드를 지원하고 팀의 속도를 조정하는 것이 더 어려울 수 있습니다.
+  **더 어려운 테스트**-코드 줄이 증가함에 따라 코드 베이스에서 입력과 진입점의 가능한 모든 조합을 통합하는 것이 더 어렵습니다. 일반적으로 더 적은 코드로 더 작은 서비스에 대한 유닛 테스트를 구현하는 것이 더 쉽습니다.

선호되는 대안은 모놀리식 Lambda 함수를 개별 마이크로서비스로 분해하여 단일 Lambda 함수를 잘 정의된 단일 태스크에 매핑하는 것입니다. 몇 가지 API 엔드포인트를 사용하는 이 간단한 웹 애플리케이션에서 결과로 생성된 마이크로서비스 기반 아키텍처는 API Gateway 경로에 기반할 수 있습니다ㅣ.를 기반으로 할 수 있습니다.

![\[이벤트 중심 아키텍처 그림 14\]](http://docs.aws.amazon.com/ko_kr/lambda/latest/dg/images/event-driven-architectures-figure-14.png)


### 런어웨이 Lambda 함수를 유발하는 재귀 패턴
<a name="recursive-runaway"></a>

AWS 서비스는 Lambda 함수를 간접 호출하는 이벤트를 생성하고 Lambda 함수는 AWS 서비스로 메시지를 전송할 수 있습니다. 일반적으로 Lambda 함수를 간접 호출하는 서비스나 리소스는 함수가 출력하는 서비스나 리소스와 달라야 합니다. 이를 관리하지 못하면 무한 루프가 발생할 수 있습니다.

예를 들어 Lambda 함수는 Amazon S3 객체에 객체를 쓰고, 차례로 put 이벤트를 통해 동일한 Lambda 함수를 간접 호출합니다. 이 간접 호출로 인해 버킷에 두 번째 객체를 쓰고 이때 동일한 Lambda 함수를 간접 호출합니다.

![\[이벤트 중심 아키텍처 그림 15\]](http://docs.aws.amazon.com/ko_kr/lambda/latest/dg/images/event-driven-architectures-figure-15.png)


대부분의 프로그래밍 언어에는 무한 루프의 가능성이 존재하지만 이 안티 패턴은 서버리스 애플리케이션에서 더 많은 리소스를 소비할 수 있습니다. Lambda 및 Amazon S3 모두 트래픽에 따라 자동으로 조정되므로 루프로 인해 Lambda 규모가 조정되어 사용 가능한 모든 동시성을 소비할 수 있으며 Amazon S3에서는 객체를 계속 쓰고 Lambda에 대한 더 많은 이벤트를 생성합니다.

이 예제에서는 S3를 사용하지만 재귀 루프의 위험은 Amazon SNS, Amazon SQS, DynamoDB 및 기타 서비스에도 존재합니다. [재귀 루프 감지](invocation-recursion.md)를 사용하여 이러한 패턴 방지를 찾고 방지할 수 있습니다.

### Lambda 함수를 직접 호출하는 Lambda 함수
<a name="functions-calling-functions"></a>

함수에서 캡슐화 및 코드 재사용을 활성화합니다. 대부분의 프로그래밍 언어는 코드 베이스 내에서 동기식으로 함수를 직접 호출하는 코드 개념을 지원합니다. 이 경우 직접 호출자는 함수가 응답을 반환할 때까지 기다립니다.

**참고**  
Lambda 함수가 다른 Lambda 함수를 직접 호출하는 것은 일반적으로 비용 및 복잡성 문제로 인한 안티 패턴이지만, 다른 함수를 호출하여 다단계 워크플로를 오케스트레이션하도록 특별히 설계된 [지속성 함수](durable-functions.md)에는 적용되지 않습니다.

기존 서버 또는 가상 인스턴스에서 이러한 상황이 나타나면 운영 체제 스케줄러는 사용 가능한 다른 작업으로 전환됩니다. 사용자는 서버 소유 및 운영에 대한 고정 비용을 지불하므로 CPU가 0%로 실행되는지 또는 100%로 실행되는지 여부는 애플리케이션의 전체 비용에 영향을 주지 않습니다.

이 모델은 종종 서버리스 개발에 적합하지 않을 수도 있습니다. 예를 들어 주문을 처리하는 세 가지 Lambda 함수로 구성된 간단한 전자 상거래 애플리케이션을 고려합니다.

![\[이벤트 중심 아키텍처 그림 16\]](http://docs.aws.amazon.com/ko_kr/lambda/latest/dg/images/event-driven-architectures-figure-16.png)


이 경우 *주문 생성* 함수는 *결제 처리* 함수를 직접 호출하고, 차례로 *송장 생성* 함수를 직접 호출합니다. 이 동기식 흐름은 서버의 단일 애플리케이션 내에서 작동할 수 있지만 분산 서버리스 아키텍처에서 방지할 수 있는 몇 가지 문제가 발생합니다.
+  **비용**-Lambda를 사용하면 간접 호출 지속 시간 동안 비용을 지불합니다. 이 예제에서는 *송장 생성* 함수가 실행되는 동안 대기 상태(다이어그램에 빨간색으로 표시됨)의 다른 두 함수도 실행됩니다.
+  **오류 처리**-중첩된 간접 호출에서는 오류 처리가 훨씬 더 복잡해질 수 있습니다. 예를 들어 *송장 생성*의 오류로 인해 *결제 처리* 함수에서 요금을 되돌리거나 대신 *송장 생성* 프로세스를 재시도할 수도 있습니다.
+  **긴밀한 결합** – 결제 처리는 일반적으로 송장 생성보다 오래 걸립니다. 이 모델에서 전체 워크플로의 가용성은 가장 느린 함수로 제한됩니다.
+  **규모 조정** – 모든 세 함수의 [동시성](lambda-concurrency.md)이 동일해야 합니다. 사용량이 많은 시스템에서는 필요한 것보다 더 많은 동시성을 사용합니다.

서버리스 애플리케이션에는 이 패턴을 방지하기 위한 두 가지 일반적인 접근 방식이 있습니다. 첫 번째 방법에서는 Lambda 함수 사이에서 Amazon SQS 대기열을 사용합니다. 다운스트림 프로세스가 업스트림 프로세스보다 느린 경우 대기열은 메시지를 지속적으로 유지하고 두 함수를 분리합니다. 이 예제에서는 *주문 생성* 함수가 메시지를 Amazon SQS 대기열에 게시하고 *결제 처리* 함수가 대기열의 메시지를 사용합니다.

두 번째 접근 방식은 AWS Step Functions 항목을 사용하는 것입니다. 여러 유형의 실패 및 재시도 로직을 포함하는 복잡한 프로세스의 경우 Step Functions는 워크플로를 오케스트레이션하는 데 필요한 사용자 지정 코드의 양을 줄이는 데 도움이 될 수 있습니다. 따라서 Step Functions는 작업을 오케스트레이션하고 오류 및 재시도를 강력하게 처리합니다. Lambda 함수에는 비즈니스 로직만 포함됩니다.

### 단일 Lambda 함수 내에서 동기식 대기
<a name="synchronous-waiting"></a>

잠재적인 동시 활동이 단일 Lambda 함수 내에서 동기식으로 예약되지 않도록 합니다. 예를 들어 Lambda 함수는 S3 버킷에 쓴 다음, DynamoDB 테이블에 쓸 수 있습니다.

![\[이벤트 중심 아키텍처 그림 17\]](http://docs.aws.amazon.com/ko_kr/lambda/latest/dg/images/event-driven-architectures-figure-17.png)


이 설계에서는 활동이 순차적이기 때문에 대기 시간이 복잡해집니다. 두 번째 태스크가 첫 번째 태스크의 완료에 종속된 경우 두 가지 별도의 Lambda 함수를 갖고 총 대기 시간과 실행 비용을 줄일 수 있습니다.

![\[이벤트 중심 아키텍처 그림 19\]](http://docs.aws.amazon.com/ko_kr/lambda/latest/dg/images/event-driven-architectures-figure-19.png)


이 설계에서 첫 번째 Lambda 함수는 객체를 Amazon S3 버킷에 넣은 직후 응답합니다. S3 서비스는 두 번째 Lambda 함수를 간접 호출하고, 차례로 DynamoDB 테이블에 데이터를 씁니다. 이 접근 방식은 Lambda 함수 실행에서 총 대기 시간을 최소화합니다.

# Lambda 애플리케이션 설계
<a name="concepts-application-design"></a>

잘 설계된 이벤트 중심 애플리케이션은 AWS 서비스 및 사용자 지정 코드의 조합을 사용하여 요청과 데이터를 처리 및 관리합니다. 이 장에서는 애플리케이션 설계에서 Lambda 관련 주제에 중점을 둡니다. 사용량이 많은 프로덕션 시스템에 대한 애플리케이션을 설계하는 경우 서버리스 아키텍트에게 중요한 고려 사항이 많이 포함되어 있습니다.

소프트웨어 개발 및 분산 시스템에 적용되는 많은 모범 사례가 서버리스 애플리케이션 개발에도 적용됩니다. 전반적인 목표는 다음과 같은 워크로드를 개발하는 것입니다.
+  **신뢰성**-최종 사용자에게 높은 수준의 가용성을 제공합니다. AWS 서버리스 서비스는 장애와 관련하여 설계되었기 때문에 안정적입니다.
+  **내구성**-워크로드의 내구성 요구 사항을 충족하는 스토리지 옵션을 제공합니다.
+  **보안**-모범 사례를 따르고 제공된 도구를 사용하여 워크로드에 대한 액세스를 보호하고 영향을 받는 반경을 제한합니다.
+  **성능**-컴퓨팅 리소스를 효율적으로 사용하고 최종 사용자의 성능 요구 사항을 충족합니다.
+  **비용 효율성**-과도한 지출 없이 규모를 조정할 수 있어 불필요한 비용을 방지하고 상당한 오버헤드 없이 해체할 수 있는 아키텍처를 설계합니다.

다음 설계 원칙은 이러한 목표를 충족하는 워크로드를 구축하는 데 도움이 될 수 있습니다. 모든 아키텍처에 모든 원칙이 적용되는 것은 아니지만 일반적인 아키텍처 결정에 도움이 될 수 있습니다.

**Topics**
+ [

## 사용자 지정 코드 대신 서비스 사용
](#services-custom-code)
+ [

## Lambda 추상화 수준 이해
](#level-abstraction)
+ [

## 함수에서 상태 비저장 구현
](#statelessness-functions)
+ [

## 결합 최소화
](#minimize-coupling)
+ [

## 배치 대신 온디맨드 데이터 빌드
](#on-demand-batches)
+ [

## 복잡한 워크플로에 대한 오케스트레이션 옵션 선택
](#orchestration)
+ [

## 멱등성 실행
](#retries-failures)
+ [

## 할당량 관리를 위해 여러 AWS 계정 사용
](#multiple-accounts)

## 사용자 지정 코드 대신 서비스 사용
<a name="services-custom-code"></a>

서버리스 애플리케이션은 일반적으로 Lambda 함수에서 실행되는 사용자 지정 코드와 통합된 여러 AWS 서비스로 구성됩니다. Lambda는 대부분의 AWS 서비스와 통합할 수 있지만 서버리스 애플리케이션에서 가장 일반적으로 사용되는 서비스는 다음과 같습니다.


| 카테고리 | AWS 서비스 | 
| --- | --- | 
|  컴퓨팅  |  AWS Lambda  | 
|  데이터 스토리지  |  Amazon S3 Amazon DynamoDB Amazon RDS  | 
|  API  |  Amazon API Gateway  | 
|  애플리케이션 통합  |  Amazon EventBridge Amazon SNS  Amazon SQS  | 
|  오케스트레이션  |  Lambda 지속성 함수 AWS Step Functions  | 
|  스트리밍 데이터 및 분석  |  Amazon Data Firehose  | 

**참고**  
DynamoDB 및 Amazon S3를 비롯한 많은 서버리스 서비스에서는 여러 리전에 대한 복제 및 지원을 제공합니다. Lambda 함수는 배포 파이프라인의 일부로 여러 리전에 배포할 수 있으며 이 구성을 지원하도록 API Gateway를 구성할 수 있습니다. 이를 달성할 수 있는 방법을 보여주는 이 [ 예제 아키텍처](https://d1.awsstatic.com/architecture-diagrams/ArchitectureDiagrams/serverless-architecture-for-global-applications-ra.pdf?did=wp_card&trk=wp_card)를 참조하세요.

분산 아키텍처에는 직접 빌드하거나 AWS 서비스를 사용하여 구현할 수 있는 잘 정립된 일반적인 패턴이 많이 있습니다. 대부분의 고객에게는 이러한 패턴을 처음부터 개발하는 데 시간을 투자할 상업적 가치가 거의 없습니다. 애플리케이션에 이러한 패턴 중 하나가 필요한 경우 해당 AWS 서비스를 사용합니다.


| 패턴 | AWS 서비스 | 
| --- | --- | 
|  대기열  |   Amazon SQS  | 
|  이벤트 버스  |  Amazon EventBridge  | 
|  게시/구독(팬아웃)  |  Amazon SNS  | 
|  오케스트레이션  |  Lambda 지속성 함수 AWS Step Functions  | 
|  API  |  Amazon API Gateway  | 
|  이벤트 스트림  |  Amazon Kinesis  | 

이러한 서비스는 Lambda와 통합되도록 설계되었으며 코드형 인프라(IaC)를 사용하여 서비스에서 리소스를 생성 및 취소할 수 있습니다. 애플리케이션을 설치하거나 서버를 구성하지 않고도 [AWS SDK](https://aws.amazon.com/tools/)를 통해 이러한 서비스를 사용할 수 있습니다. Lambda 함수의 코드를 통해 이러한 서비스를 사용하는 데 능숙해지는 것이야말로 설계된 서버리스 애플리케이션을 생성하는 중요한 단계입니다.

## Lambda 추상화 수준 이해
<a name="level-abstraction"></a>

Lambda 서비스는 Lambda 함수를 실행하는 기본 운영 체제, 하이퍼바이저 및 하드웨어에 대한 액세스를 제한합니다. 이 서비스는 인프라를 지속적으로 개선하고 변경하여 기능을 추가하고 비용을 절감하며 서비스의 효율성을 높입니다. 코드에서는 Lambda의 설계 방식에 대한 자식이 없으며 하드웨어 선호도도도 높지 않다고 가정해야 합니다.

마찬가지로 Lambda와 다른 서비스의 통합은 소수의 구성 옵션만 공개한 상태로 AWS에서 관리합니다. 예를 들어 API Gateway와 Lambda가 상호 작용할 때는 서비스에서 완전히 관리하므로 로드 밸런싱 개념이 없습니다. 또한 언제든지 함수를 간접 호출할 때 서비스가 사용하는 [가용 영역](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/) 또는 Lambda 실행 환경을 스케일 업하거나 다운하는 방법과 시기를 직접적으로 제어하지도 않습니다.

이러한 추상화는 애플리케이션의 통합 측면, 데이터 흐름, 워크로드가 최종 사용자에게 가치를 제공하는 비즈니스 로직에 집중하는 데 도움이 됩니다. 서비스에서 기본 메커니즘을 관리하도록 허용하면 유지 관리할 사용자 지정 코드가 적어 애플리케이션을 더 빠르게 개발할 수 있습니다.

## 함수에서 상태 비저장 구현
<a name="statelessness-functions"></a>

표준 Lambda 함수의 경우 환경이 단일 간접 호출에만 존재한다고 가정해야 합니다. 함수는 처음 시작할 때 필요한 상태를 초기화해야 합니다. 예를 들어 함수에서 DynamoDB 테이블에서 데이터를 가져와야 할 수 있습니다. 나가기 전에 Amazon S3, DynamoDB 또는 Amazon SQS와 같은 지속적인 저장소로 영구적인 데이터 변경을 커밋해야 합니다. 기존 데이터 구조나 임시 파일 또는 여러 간접 호출로 관리되는 내부 상태에 의존해서는 안 됩니다.

지속성 함수를 사용할 때 간접 호출 사이에 상태가 자동으로 유지되므로 외부 스토리지에 상태를 수동으로 유지할 필요가 없습니다. 하지만 DurableContext를 통해 명시적으로 관리되지 않는 데이터의 경우 여전히 상태 비저장 원칙을 따라야 합니다.

데이터베이스 연결 및 라이브러리 또는 로드 상태를 초기화하려면 [정적 초기화](lambda-runtime-environment.md#static-initialization)를 활용할 수 있습니다. 실행 환경은 성능을 개선하기 위해 가능한 경우 재사용되므로 여러 간접 호출을 통해 이러한 리소스를 초기화하는 데 걸리는 시간을 일부 분할할 수 있습니다. 그러나 이 글로벌 범위 내에서 함수에 사용된 변수나 데이터를 저장해서는 안 됩니다.

## 결합 최소화
<a name="minimize-coupling"></a>

대부분의 아키텍처는 수가 더 적고 크기가 더 큰 함수보다 더 짧고 많은 함수를 선호해야 합니다. 각 함수의 목적은 트랜잭션 볼륨 또는 전체 워크플로에 대한 지식이나 예상 정보 없이도 함수에 전달된 이벤트를 처리하는 것이어야 합니다. 그러면 함수가 다른 서비스에 대해 최소의 연결을 사용하며 이벤트 소스의 구애를 받지 않습니다.

자주 변경되지 않는 전역 범위 상수는 배포 없이 업데이트할 수 있는 환경 변수로 구현해야 합니다. 모든 보안 암호 또는 민감한 정보는 [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html) 또는 [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/)에 저장하고 함수로 로드해야 합니다. 이러한 리소스는 계정별로 다르므로, 여러 계정에 걸쳐 빌드 파이프라인을 생성할 수 있습니다. 파이프라인은 환경에 따라 적절한 보안 암호를 로드하므로 이를 개발자에게 공개하거나 코드를 변경하지 않아도 됩니다.

## 배치 대신 온디맨드 데이터 빌드
<a name="on-demand-batches"></a>

많은 기존 시스템이 주기적으로 실행되고 시간 경과에 따라 빌드된 트랜잭션 배치를 처리하도록 설계되었습니다. 예를 들어 뱅킹 애플리케이션은 중앙 원장으로 ATM 트랜잭션을 처리하기 위해 1시간마다 실행될 수 있습니다. Lambda 기반 애플리케이션에서 서비스가 필요에 따라 동시성을 스케일 업하여 트랜잭션을 거의 실시간으로 처리할 수 있도록 사용자 지정 처리는 모든 이벤트에 의해 트리거되어야 합니다.

표준 Lambda 함수는 15분으로 실행 시간이 제한되지만 지속성 함수는 최대 1년 동안 실행할 수 있으므로 더 장기적으로 실행되는 처리 요구에 적합합니다. 하지만 가능하면 배치 처리보다 이벤트 기반 처리를 선호해야 합니다.

Amazon EventBridge에서 규칙에 대해 [예약된 표현식을 사용](https://docs.aws.amazon.com/eventbridge/latest/userguide/scheduled-events.html)하여 서버리스 애플리케이션에서 [cron](https://en.wikipedia.org/wiki/Cron) 태스크를 실행할 수 있지만, 이러한 방법은 최대한 사용을 피하거나 최후의 수단으로 사용해야 합니다. 배치를 처리하는 모든 예약된 작업에서는 15분의 Lambda 시간 제한 내에 처리할 수 있는 수준을 초과하여 트랜잭션 볼륨이 증가할 가능성이 존재합니다. 외부 시스템의 제한으로 인해 스케줄러를 사용해야 하는 경우 일반적으로 가장 짧은 합리적인 반복 기간을 예약해야 합니다.

예를 들어 Lambda 함수를 트리거하여 새 Amazon S3 객체 목록을 가져오는 배치 프로세스를 사용하는 것은 모범 사례가 아닙니다. 서비스가 15분의 Lambda 함수 내에서 처리할 수 있는 것보다 배치 사이에 더 많은 새 객체를 수신할 수 있기 때문입니다.

![\[이벤트 중심 아키텍처 그림 10\]](http://docs.aws.amazon.com/ko_kr/lambda/latest/dg/images/event-driven-architectures-figure-10.png)


대신 새 객체를 버킷에 넣을 때마다 Amazon S3에서 Lambda 함수를 간접적으로 호출해야 합니다. 이 접근 방식은 특히 확장성이 더 뛰어나며 거의 실시간으로 작동합니다.

![\[이벤트 중심 아키텍처 그림 11\]](http://docs.aws.amazon.com/ko_kr/lambda/latest/dg/images/event-driven-architectures-figure-11.png)


## 복잡한 워크플로에 대한 오케스트레이션 옵션 선택
<a name="orchestration"></a>

분기 로직, 여러 가지 유형의 장애 모델 및 재시도 로직을 포함하는 워크플로는 일반적으로 오케스트레이터를 사용하여 전체 실행 상태를 추적합니다. 표준 Lambda 함수에서 임시 오케스트레이션을 구축하지 마세요. 이로 인해 강한 결합이 발생하고 라우팅 코드가 복잡해지며 자동 상태 복구가 불가능해집니다.

대신, 다음과 같은 목적별 오케스트레이션 옵션 중 하나를 사용합니다.
+ **[Lambda 지속성 함수](durable-functions.md):** 표준 프로그래밍 언어를 사용한 애플리케이션 중심 오케스트레이션으로 자동 체크포인팅, 기본 제공 재시도, 실행 복구를 제공합니다. Lambda 내에서 워크플로 로직을 비즈니스 로직과 함께 코드 내에 유지하는 것을 선호하는 개발자에게 적합합니다.
+ **[AWS Step Functions](with-step-functions.md):** 220개 이상의 AWS 서비스와 기본적으로 통합되는 시각적 워크플로 오케스트레이션입니다. 다중 서비스 조정, 제로 유지 관리 인프라, 시각적 워크플로 설계에 적합합니다.

이러한 옵션 중에서 선택하는 방법에 대한 지침은 [지속성 함수 또는 Step Functions](durable-step-functions.md)를 참조하세요.

[ Step Functions](https://aws.amazon.com/step-functions/)에서는 상태 머신을 사용하여 오케스트레이션을 관리합니다. 그러면 코드에서 오류 처리, 라우팅 및 분기 로직을 추출하여 JSON을 사용해 이를 선언된 상태 머신으로 대체합니다. 워크플로의 내구성과 관찰성을 강화하는 것 외에도, 워크플로에 버전 관리를 추가하고 상태 머신을 코드 리포지토리에 추가할 수 있는 코드화된 리소스로 구성할 수도 있습니다.

Lambda 함수의 더 간단한 워크플로는 시간이 지남에 따라 더 복잡해지는 것이 일반적입니다. 프로덕션 서버리스 애플리케이션을 작동할 때는 이 로직을 상태 머신 또는 지속성 함수로 마이그레이션할 수 있도록 이러한 상황이 언제 발생하는지 식별하는 것이 중요합니다.

## 멱등성 실행
<a name="retries-failures"></a>

Lambda를 포함하여 AWS 서버리스 서비스는 내결함성이 뛰어나고 장애를 처리하도록 설계되었습니다. 예를 들어 서비스가 Lambda 함수를 간접 호출하고 서비스 중단이 발생하면 Lambda는 다른 가용 영역에서 함수를 간접 호출합니다. 함수에서 오류가 발생하면 Lambda는 간접 호출을 다시 시도합니다.

동일한 이벤트가 두 번 이상 수신될 수 있으므로 함수는 [멱등성](https://en.wikipedia.org/wiki/Idempotence)을 고려하여 설계되어야 합니다. 즉, 동일한 이벤트를 여러 번 수신해도 이벤트를 처음 수신한 이후 결과가 변경되지 않습니다.

DynamoDB 테이블을 사용하여 최근에 처리된 식별자를 추적해 트랜잭션이 이전에 처리되었는지 확인함으로써 Lambda 함수의 멱등성을 구현할 수 있습니다. DynamoDB 테이블은 일반적으로 [Time To Live(TTL)](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TTL.html) 값을 구현하여 사용되는 스토리지 공간을 제한하도록 항목을 만료시킵니다.

## 할당량 관리를 위해 여러 AWS 계정 사용
<a name="multiple-accounts"></a>

AWS의 많은 [Service Quotas](gettingstarted-limits.md)가 계정 수준에서 설정됩니다. 즉, 더 많은 워크로드를 추가하면 제한을 빠르게 소진할 수 있습니다.

이 문제를 해결하는 효과적인 방법은 여러 AWS 계정을 사용하여 각각의 워크로드를 해당 계정에 전용으로 사용하는 것입니다. 그러면 할당량이 다른 워크로드나 비프로덕션 리소스와 공유되지 않습니다.

 또한 [AWS Organizations](https://aws.amazon.com/organizations/)를 사용하면 이러한 계정의 결제, 규정 준수 및 보안을 중앙에서 관리할 수 있습니다. 사용자 지정 스크립트 및 수동 프로세스를 방지하기 위해 계정 그룹에 정책을 연결할 수 있습니다.

이때 한 가지 일반적인 접근 방식은 각 개발자에게 AWS 계정을 제공한 다음, 베타 배포 단계 및 프로덕션에 대해 별도의 계정을 사용하는 것입니다.

![\[애플리케이션 설계 그림 3\]](http://docs.aws.amazon.com/ko_kr/lambda/latest/dg/images/application-design-figure-3.png)


이 모델에서는 각 개발자는 계정에 대한 자체 제한 세트가 있으므로 해당 개발자의 사용은 프로덕션 환경에 영향을 주지 않습니다. 또한 이 접근 방식을 통해 개발자는 개별 계정의 라이브 클라우드 리소스에 대해 개발 시스템에서 Lambda 함수를 로컬로 테스트할 수 있습니다.