

# Rust를 사용하여 Lambda 함수 빌드
<a name="lambda-rust"></a>

Rust는 네이티브 코드로 컴파일되므로 Lambda에서 Rust 코드를 실행하는 데 전용 런타임이 필요하지 않습니다. 대신 [Rust 런타임 클라이언트](https://github.com/aws/aws-lambda-rust-runtime)를 사용하여 로컬에서 프로젝트를 빌드한 다음 [OS 전용 런타임](runtimes-provided.md)을 사용하여 Lambda에 배포합니다. OS 전용 런타임을 사용하면 Lambda는 최신 패치를 통해 자동으로 운영 체제를 최신 상태로 유지합니다.

**Rust용 도구 및 라이브러리**
+ [AWS SDK for Rust](https://docs.aws.amazon.com/sdk-for-rust/latest/dg/getting-started.html): AWS SDK for Rust는 Amazon Web Services 인프라 서비스와 상호 작용할 수 있는 Rust API를 제공합니다.
+  [Lambda용 Rust 런타임 클라이언트](https://github.com/aws/aws-lambda-rust-runtime): Rust 런타임 클라이언트를 사용하면 Rust로 작성된 Lambda 함수를 쉽게 실행할 수 있습니다.
+ [Cargo Lambda](https://www.cargo-lambda.info/guide/what-is-cargo-lambda.html): Rust Lambda 함수 빌드 및 배포를 간소화하는 Cargo 명령줄 도구의 타사 오픈 소스 확장입니다.
+ [Lambda HTTP](https://github.com/aws/aws-lambda-rust-runtime/tree/main/lambda-http): 이 라이브러리는 HTTP 이벤트와 함께 작동하는 래퍼를 제공합니다.
+  [Lambda 확장](https://github.com/aws/aws-lambda-rust-runtime/tree/main/lambda-extension): 이 라이브러리는 Rust로 Lambda 확장을 작성할 수 있도록 지원합니다.
+ [AWS Lambda 이벤트](https://crates.io/crates/aws_lambda_events): 이 라이브러리는 일반적인 이벤트 소스 통합을 위한 유형 정의를 제공합니다.

**Rust용 샘플 Lambda 애플리케이션**
+ [기본 Lambda 함수](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/basic-lambda): 기본 이벤트를 처리하는 방법을 보여주는 Rust 함수입니다.
+ [오류 처리가 포함된 Lambda 함수](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/basic-error-handling): Lambda에서 사용자 지정 Rust 오류를 처리하는 방법을 보여주는 Rust 함수입니다.
+ [공유 리소스가 포함된 Lambda 함수](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/basic-shared-resource): Lambda 함수를 생성하기 전에 공유 리소스를 초기화하는 Rust 프로젝트입니다.
+ [Lambda HTTP 이벤트](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/http-basic-lambda): HTTP 이벤트를 처리하는 Rust 함수입니다.
+ [CORS 헤더가 포함된 Lambda HTTP 이벤트](https://github.com/aws/aws-lambda-rust-runtime/blob/main//examples/http-cors): Tower를 사용하여 CORS 헤더를 삽입하는 Rust 함수입니다.
+ [Lambda REST API](https://github.com/aws/aws-lambda-rust-runtime/tree/main/examples/http-axum-diesel): Axum과 Diesel을 사용하여 PostgreSQL 데이터베이스에 연결하는 REST API입니다.
+ [서버리스 Rust 데모](https://github.com/aws-samples/serverless-rust-demo/): Lambda의 Rust 라이브러리, 로깅, 환경 변수, AWS SDK의 사용법을 보여주는 Rust 프로젝트입니다.
+ [기본 Lambda 확장](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/extension-basic): 기본 확장 이벤트를 처리하는 방법을 보여주는 Rust 확장입니다.
+ [Lambda 로그 Amazon Data Firehose 확장](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/extension-logs-kinesis-firehose): Lambda 로그를 Firehose로 전송하는 방법을 보여주는 Rust 확장입니다.

**Topics**
+ [

# Rust에서 Lambda 함수 핸들러 정의
](rust-handler.md)
+ [

# Lambda 컨텍스트 객체를 사용하여 Rust 함수 정보 검색
](rust-context.md)
+ [

# Rust로 HTTP 이벤트 처리
](rust-http-events.md)
+ [

# .zip 파일 아카이브를 사용하여 Rust Lambda 함수 배포
](rust-package.md)
+ [

# Rust Lambda 함수를 위한 계층 작업
](rust-layers.md)
+ [

# Rust Lambda 함수 기록 및 모니터링
](rust-logging.md)

# Rust에서 Lambda 함수 핸들러 정의
<a name="rust-handler"></a>

Lambda 함수의 *핸들러*는 이벤트를 처리하는 함수 코드의 메서드입니다. 함수가 간접 호출되면 Lambda는 핸들러 메서드를 실행합니다. 함수는 핸들러가 응답을 반환하거나 종료하거나 제한 시간이 초과될 때까지 실행됩니다.

이 페이지에서는 프로젝트 초기화, 이름 지정 규칙, 모범 사례를 포함하여 Rust에서 Lambda 함수 핸들러를 사용하는 방법을 설명합니다. 이 페이지에는 주문에 대한 정보를 가져와서 텍스트 파일 영수증을 생성하고 해당 파일을 Amazon Simple Storage Service(Amazon S3) 버킷에 넣는 Rust Lambda 함수의 예제도 포함되어 있습니다. 함수를 작성한 후 배포하는 방법에 대한 자세한 내용은 [.zip 파일 아카이브를 사용하여 Rust Lambda 함수 배포](rust-package.md) 섹션을 참조하세요.

**Topics**
+ [

## Rust 핸들러 프로젝트 설정
](#rust-handler-setup)
+ [

## 예제 Rust Lambda 함수 코드
](#rust-example-code)
+ [

## Rust 핸들러에 유효한 클래스 정의
](#rust-handler-signatures)
+ [

## 핸들러 이름 지정 규칙
](#rust-example-naming)
+ [

## 입력 이벤트 객체 정의 및 액세스
](#rust-handler-input)
+ [

## Lambda 컨텍스트 객체 액세스 및 사용
](#rust-example-context)
+ [

## 핸들러에서 AWS SDK for Rust 사용
](#rust-example-sdk-usage)
+ [

## 환경 변수에 액세스
](#rust-example-envvars)
+ [

## 공유 상태 사용
](#rust-shared-state)
+ [

## Rust Lambda 함수의 코드 모범 사례
](#rust-best-practices)

## Rust 핸들러 프로젝트 설정
<a name="rust-handler-setup"></a>

Rust에서 Lambda 함수를 사용할 경우 프로세스에는 코드를 작성한 후 컴파일하고, 컴파일된 아티팩트를 Lambda에 배포하는 작업이 포함됩니다. Rust에서 Lambda 핸들러 프로젝트를 설정하는 가장 간단한 방법은 [Rust용 AWS Lambda 런타임](https://github.com/aws/aws-lambda-rust-runtime)을 사용하는 것입니다. Rust용 AWS Lambda 런타임은 Python, Java 또는 Node.js용 Lambda와 이름이 비슷하지만 동일한 의미의 관리형 런타임은 아닙니다. 대신 Rust용 AWS Lambda 런타임은 Rust로 Lambda 함수를 작성하고 AWS Lambda의 실행 환경과 인터페이스할 수 있도록 지원하는 크레이트(`lambda_runtime`)입니다.

다음 명령을 사용하여 Cargo 명령줄 도구에 Rust Lambda 함수 빌드 및 배포를 간소화하는 타사 오픈 소스 확장인 [Cargo Lambda](https://www.cargo-lambda.info/guide/what-is-cargo-lambda.html)를 설치합니다.

```
cargo install cargo-lambda
```

`cargo-lambda`를 성공적으로 설치한 후 다음 명령을 사용하여 새 Rust Lambda 함수 핸들러 프로젝트를 초기화합니다.

```
cargo lambda new example-rust
```

이 명령을 실행하면 명령줄 인터페이스(CLI)가 Lambda 함수에 대해 다음과 같은 몇 가지 질문을 합니다.
+ **HTTP 함수** - [API Gateway](services-apigateway.md) 또는 [함수 URL](urls-configuration.md)을 통해 함수를 간접적으로 호출하려는 경우 **예**라고 답합니다. 그렇지 않으면 **아니요**라고 답합니다. 이 페이지의 예제 코드에서는 사용자 지정 JSON 이벤트로 함수를 간접적으로 호출하므로 **아니요**라고 답합니다.
+ **이벤트 유형** - 사전 정의된 이벤트 셰이프를 사용하여 함수를 간접적으로 호출하려는 경우 올바른 예상 이벤트 유형을 선택합니다. 나머지 경우에는 이 옵션 필드를 비워둡니다. 이 페이지의 예제 코드에서는 사용자 지정 JSON 이벤트로 함수를 간접적으로 호출하므로 이 옵션을 비워 둡니다.

명령이 성공적으로 실행되면 프로젝트의 기본 디렉터리를 입력합니다.

```
cd example-rust
```

이 명령은 `src` 디렉터리에 `generic_handler.rs` 파일과 `main.rs` 파일을 생성합니다. `generic_handler.rs`를 사용하여 일반 이벤트 핸들러를 사용자 지정할 수 있습니다. `main.rs` 파일에는 기본 애플리케이션 로직이 들어있습니다. `Cargo.toml` 파일에는 패키지에 대한 메타데이터와 외부 종속성 목록이 들어 있습니다.

## 예제 Rust Lambda 함수 코드
<a name="rust-example-code"></a>

다음 예제 Rust Lambda 함수 코드는 주문에 대한 정보를 입력으로 가져와서 텍스트 파일 영수증을 생성하고 해당 파일을 Amazon S3 버킷에 넣습니다.

**Example `main.rs` Lambda 함수**  

```
use aws_sdk_s3::{Client, primitives::ByteStream};
use lambda_runtime::{run, service_fn, Error, LambdaEvent};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::env;

#[derive(Deserialize, Serialize)]
struct Order {
    order_id: String,
    amount: f64,
    item: String,
}

async fn function_handler(event: LambdaEvent<Value>) -> Result<String, Error> {
    let payload = event.payload;

    // Deserialize the incoming event into Order struct
    let order: Order = serde_json::from_value(payload)?;

    let bucket_name = env::var("RECEIPT_BUCKET")
        .map_err(|_| "RECEIPT_BUCKET environment variable is not set")?;

    let receipt_content = format!(
        "OrderID: {}\nAmount: ${:.2}\nItem: {}",
        order.order_id, order.amount, order.item
    );
    let key = format!("receipts/{}.txt", order.order_id);

    let config = aws_config::load_defaults(aws_config::BehaviorVersion::latest()).await;
    let s3_client = Client::new(&config);

    upload_receipt_to_s3(&s3_client, &bucket_name, &key, &receipt_content).await?;

    Ok("Success".to_string())
}

async fn upload_receipt_to_s3(
    client: &Client,
    bucket_name: &str,
    key: &str,
    content: &str,
) -> Result<(), Error> {
    client
        .put_object()
        .bucket(bucket_name)
        .key(key)
        .body(ByteStream::from(content.as_bytes().to_vec()))  // Fixed conversion
        .content_type("text/plain")
        .send()
        .await?;

    Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    run(service_fn(function_handler)).await
}
```

`main.rs` 파일은 다음 코드 섹션을 포함하고 있습니다.
+ `use` 문: Lambda 함수에 필요한 Rust 크레이트와 메서드를 가져오는 데 사용합니다.
+ `#[derive(Deserialize, Serialize)]`: 이 Rust 구조체에 예상 입력 이벤트의 셰이프를 정의합니다.
+ `async fn function_handler(event: LambdaEvent<Value>) -> Result<String, Error>`: 기본 애플리케이션 논리를 포함한 **기본 핸들러 메서드**입니다.
+ `async fn upload_receipt_to_s3 (...)`: 기본 `function_handler` 메서드에서 참조하는 도우미 메서드입니다.
+ `#[tokio::main]`: Rust 프로그램의 진입점을 표시하는 매크로입니다. 또한 [Tokio 런타임](https://docs.rs/tokio/latest/tokio/runtime/index.html)을 설정하여 `main()` 메서드가 `async`/`await`를 사용하고 비동기적으로 실행될 수 있도록 합니다.
+ `async fn main() -> Result<(), Error>`: `main()` 함수는 코드의 진입점입니다. 그 안에서 `function_handler`를 주요 핸들러 메서드로 지정합니다.

### 샘플 Cargo.toml 파일
<a name="rust-cargo-toml"></a>

다음 `Cargo.toml` 파일은 이 함수와 함께 제공됩니다.

```
[package]
name = "example-rust"
version = "0.1.0"
edition = "2024"

[dependencies]
aws-config = "1.5.18"
aws-sdk-s3 = "1.78.0"
lambda_runtime = "0.13.0"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tokio = { version = "1", features = ["full"] }
```

이 함수가 제대로 작동하려면 [실행 역할](lambda-intro-execution-role.md)이 `s3:PutObject` 작업을 허용해야 합니다. 또한 `RECEIPT_BUCKET` 환경 변수를 정의해야 합니다. 성공적으로 간접 호출되면 Amazon S3 버킷은 영수증 파일을 포함합니다.

## Rust 핸들러에 유효한 클래스 정의
<a name="rust-handler-signatures"></a>

대부분의 경우 Rust에서 정의하는 Lambda 핸들러 서명의 형식은 다음과 같습니다.

```
async fn function_handler(event: LambdaEvent<T>) -> Result<U, Error>
```

이 핸들러의 경우
+ 이 핸들러의 이름은 `function_handler`입니다.
+ 핸들러에 대한 단일 입력은 이벤트이며 `LambdaEvent<T>` 유형입니다.
  + `LambdaEvent`는 `lambda_runtime` 크레이트에서 제공되는 래퍼입니다. 이 래퍼를 사용하면 간접 호출의 요청 ID 등의 Lambda 관련 메타데이터가 포함된 컨텍스트 객체에 액세스할 수 있습니다.
  + `T`는 역직렬화된 이벤트 유형입니다. 예를 들어, 이는 핸들러가 모든 일반 JSON 입력을 받을 수 있도록 하는 `serde_json::Value`일 수 있습니다. 또는 함수가 사전 정의된 특정 입력 유형을 예상하는 경우 `ApiGatewayProxyRequest`와 같은 유형일 수 있습니다.
+ 핸들러의 반환 유형은 `Result<U, Error>`입니다.
  + `U`는 역직렬화된 출력 유형입니다. `U`는 Lambda가 반환 값을 JSON으로 변환할 수 있도록 `serde::Serialize` 특성을 구현해야 합니다. 예를 들어 `U`는 `Serialize`를 구현하는 한 `String`, `serde_json::Value` 또는 사용자 지정 구조체와 같은 단순한 유형일 수 있습니다. 코드가 Ok(U) 문에 도달하면 실행이 성공한 것이며 함수는 `U` 유형의 값을 반환합니다.
  + 코드에 오류(예: `Err(Error)`)가 발생하면 함수는 Amazon CloudWatch에 오류를 기록하고 `Error` 유형의 오류 응답을 반환합니다.

이 예제에서 핸들러 서명은 다음과 같습니다.

```
async fn function_handler(event: LambdaEvent<Value>) -> Result<String, Error>
```

다른 유효한 핸들러 서명은 다음과 같은 특징이 있습니다.
+ `LambdaEvent` 래퍼 생략 - `LambdaEvent`를 생략하면 함수 내의 Lambda 컨텍스트 객체에 대한 액세스 권한을 잃게 됩니다. 다음은 이러한 유형의 서명 예입니다.

  ```
  async fn handler(event: serde_json::Value) -> Result<String, Error>
  ```
+ 입력으로 단위 유형 사용 - Rust의 경우 단위 유형을 사용하여 빈 입력을 나타낼 수 있습니다. 주기적으로 예약된 간접 호출이 있는 함수에 주로 사용됩니다. 다음은 이러한 유형의 서명 예입니다.

  ```
  async fn handler(_: ()) -> Result<Value, Error>
  ```

## 핸들러 이름 지정 규칙
<a name="rust-example-naming"></a>

Rust의 Lambda 핸들러에는 엄격한 이름 지정 제한이 없습니다. 핸들러에 어떤 이름이든 사용할 수 있지만 Rust에서는 함수 이름을 일반적으로 `snake_case`로 지정합니다.

이 예제와 같은 소규모 애플리케이션의 경우 단일 `main.rs` 파일을 사용하여 모든 코드를 포함할 수 있습니다. 대규모 프로젝트의 경우 `main.rs`에는 함수에 대한 진입점이 포함되어야 하지만 코드를 논리적 모듈로 구분하기 위한 추가 파일이 있을 수 있습니다. 예를 들어, 다음과 같은 파일 구조가 있을 수 있습니다.

```
/example-rust
│── src/
│   ├── main.rs        # Entry point
│   ├── handler.rs     # Contains main handler
│   ├── services.rs    # [Optional] Back-end service calls
│   ├── models.rs      # [Optional] Data models
│── Cargo.toml
```

## 입력 이벤트 객체 정의 및 액세스
<a name="rust-handler-input"></a>

JSON은 Lambda 함수의 가장 일반적인 표준 입력 형식입니다. 이 예제에서 함수는 다음과 유사한 입력을 예상합니다.

```
{
    "order_id": "12345",
    "amount": 199.99,
    "item": "Wireless Headphones"
}
```

Rust에서는 구조체에 예상 입력 이벤트의 셰이프를 정의할 수 있습니다. 이 예제에서는 `Order`를 나타내는 다음 구조체를 정의합니다.

```
#[derive(Deserialize, Serialize)]
struct Order {
    order_id: String,
    amount: f64,
    item: String,
}
```

이 구조체는 예상 입력 형태와 일치합니다. 이 예제에서 `#[derive(Deserialize, Serialize)]` 매크로는 직렬화 및 역직렬화를 위한 코드를 자동으로 생성합니다. 즉, `serde_json::from_value()` 메서드를 사용하여 일반 입력 JSON 유형을 구조체로 역직렬화할 수 있습니다. 이는 핸들러의 처음 몇 줄에 설명되어 있습니다.

```
async fn function_handler(event: LambdaEvent<Value>) -> Result<String, Error> {
    let payload = event.payload;

    // Deserialize the incoming event into Order struct
    let order: Order = serde_json::from_value(payload)?;
    ...
}
```

그런 다음, 객체의 필드에 액세스할 수 있습니다. 예를 들어 `order.order_id`는 원래 입력에서 `order_id`의 값을 검색합니다.

### 사전 정의된 입력 이벤트 유형
<a name="rust-input-event-types"></a>

`aws_lambda_events` 크레이트에는 사전 정의된 입력 이벤트 유형이 많이 있습니다. 다음 가져오기를 포함하여 API Gateway로 함수를 간접적으로 호출하려는 경우를 예로 들 수 있습니다.

```
use aws_lambda_events::event::apigw::ApiGatewayProxyRequest;
```

그런 다음 기본 핸들러가 다음 서명을 사용하는지 확인합니다.

```
async fn handler(event: LambdaEvent<ApiGatewayProxyRequest>) -> Result<String, Error> {
    let body = event.payload.body.unwrap_or_default();
    ...
}
```

기타 사전 정의된 입력 이벤트 유형에 대한 자세한 내용은 [aws\$1lambda\$1events 크레이트](https://crates.io/crates/aws_lambda_events)를 참조하세요.

## Lambda 컨텍스트 객체 액세스 및 사용
<a name="rust-example-context"></a>

Lambda [컨텍스트 객체](rust-context.md)에는 호출, 함수, 실행 환경에 관한 정보가 포함되어 있습니다. Rust에서 `LambdaEvent` 래퍼에는 컨텍스트 객체가 포함됩니다. 예를 들어 컨텍스트 객체를 사용하여 다음 코드로 현재 간접 호출의 요청 ID를 검색할 수 있습니다.

```
async fn function_handler(event: LambdaEvent<Value>) -> Result<String, Error> {
    let request_id = event.context.request_id;
    ...
}
```

컨텍스트 객체에 대한 자세한 내용은 [Lambda 컨텍스트 객체를 사용하여 Rust 함수 정보 검색](rust-context.md) 섹션을 참조하세요.

## 핸들러에서 AWS SDK for Rust 사용
<a name="rust-example-sdk-usage"></a>

종종 Lambda 함수를 사용하여 다른 AWS 리소스와 상호 작용하거나 업데이트하는 경우가 있습니다. 이러한 리소스와 상호 작용하는 가장 간단한 방법은 [AWS SDK for Rust](https://docs.aws.amazon.com/sdk-for-rust/latest/dg/welcome.html)를 사용하는 것입니다.

함수에 SDK 종속성을 추가하려면 `Cargo.toml` 파일에 추가합니다. 함수에 필요한 라이브러리만 추가하는 것이 좋습니다. 이전의 예제 코드에서는 `aws_sdk_s3::Client`를 사용했습니다. `Cargo.toml` 파일에서 `[dependencies]` 섹션 아래에 다음 줄을 추가하여 이 종속성을 추가할 수 있습니다.

```
aws-sdk-s3 = "1.78.0"
```

**참고**  
이는 최신 버전이 아닐 수 있습니다. 애플리케이션에 적합한 버전을 선택합니다.

그런 다음 코드에서 직접 종속성을 가져옵니다.

```
use aws_sdk_s3::{Client, primitives::ByteStream};
```

이렇게 하면 예제 코드가 다음과 같이 Amazon S3 클라이언트를 초기화합니다.

```
let config = aws_config::load_defaults(aws_config::BehaviorVersion::latest()).await;
let s3_client = Client::new(&config);
```

SDK 클라이언트를 초기화한 후에는 이를 사용하여 다른 AWS 서비스와 상호 작용할 수 있습니다. 예제 코드는 `upload_receipt_to_s3` 도우미 함수에서 Amazon S3 `PutObject` API를 직접적으로 호출합니다.

## 환경 변수에 액세스
<a name="rust-example-envvars"></a>

핸들러 코드에서 `env::var` 메서드를 사용하여 모든 [환경 변수](configuration-envvars.md)를 참조할 수 있습니다. 이 예제에서는 다음 코드 줄을 사용하여 정의된 `RECEIPT_BUCKET` 환경 변수를 참조합니다.

```
let bucket_name = env::var("RECEIPT_BUCKET")
    .map_err(|_| "RECEIPT_BUCKET environment variable is not set")?;
```

## 공유 상태 사용
<a name="rust-shared-state"></a>

Lambda 함수의 핸들러 코드와 무관한 공유 변수를 선언할 수 있습니다. 이러한 변수는 함수가 이벤트를 수신하기 전에 [초기화 단계](lambda-runtime-environment.md#runtimes-lifecycle-ib)에서 상태 정보를 로드하는 데 도움이 될 수 있습니다. 예를 들어 이 페이지의 코드를 수정하여 Amazon S3 클라이언트를 초기화할 때 공유 상태를 사용하도록 `main` 함수와 핸들러 서명을 업데이트할 수 있습니다.

```
async fn function_handler(client: &Client, event: LambdaEvent<Value>) -> Result<String, Error> {
    ...
    upload_receipt_to_s3(client, &bucket_name, &key, &receipt_content).await?;
    ...
}

...
      
#[tokio::main]
async fn main() -> Result<(), Error> {
    let shared_config = aws_config::from_env().load().await;
    let client = Client::new(&shared_config);
    let shared_client = &client;
    lambda_runtime::run(service_fn(move |event: LambdaEvent<Request>| async move {
        handler(&shared_client, event).await
    }))
    .await
```

## Rust Lambda 함수의 코드 모범 사례
<a name="rust-best-practices"></a>

Lambda 함수를 구축할 때 코딩 모범 사례를 사용하려면 다음 목록의 지침을 준수하세요.
+ **핵심 로직에서 Lambda 핸들러를 분리합니다.** 이를 통해 단위 테스트를 수행할 수 있는 더 많은 함수를 만들 수 있습니다.
+ **종속성의 복잡성을 최소화합니다.** [실행 환경](lambda-runtime-environment.md) 시작 시 빠르게 로드되는 더 단순한 프레임워크가 권장됩니다.
+ **배포 패키지 크기를 런타임 필요에 따라 최소화합니다.** 이렇게 하면 호출 전에 배포 패키지를 다운로드하고 압축을 풀 때 걸리는 시간이 단축됩니다.

**실행 환경 재사용을 활용하여 함수 성능을 향상시킵니다.** 함수 핸들러 외부에서 SDK 클라이언트 및 데이터베이스 연결을 초기화하고 정적 자산을 `/tmp` 디렉토리에 로컬로 캐시합니다. 동일한 함수 인스턴스에서 처리하는 후속 간접 호출은 이러한 리소스를 재사용할 수 있습니다. 이를 통해 함수 실행 시간을 줄여 비용을 절감합니다.

호출에서 발생할 수 있는 데이터 유출을 방지하려면 실행 환경을 사용하여 사용자 데이터, 이벤트 또는 보안과 관련된 기타 정보를 저장하지 마세요. 함수가 핸들러 내부 메모리에 저장할 수 없는 변경 가능한 상태에 의존하는 경우 각 사용자에 대해 별도의 함수 또는 별도의 함수 버전을 생성하는 것이 좋습니다.

**연결 유지 지시문을 사용하여 지속적인 연결을 유지하세요.** Lambda는 시간이 지남에 따라 유휴 연결을 제거합니다. 함수를 호출할 때 유휴 연결을 재사용하려고 하면 연결 오류가 발생합니다. 지속적인 연결을 유지하려면 런타임과 관련된 연결 유지 지시문을 사용하세요. 예를 들어, [Node.js에서 연결 유지를 이용해 연결 재사용](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/node-reusing-connections.html)을 참조하세요.

** [환경 변수](configuration-envvars.md)를 사용하여 함수에 운영 파라미터를 전달합니다.** 예를 들어, Amazon S3 버킷에 기록하는 경우 기록하고 있는 버킷 이름을 하드 코딩하는 대신 환경 변수로 구성합니다.

Lambda 함수에서 함수가 자기 자신을 간접적으로 간접 호출하거나 함수를 다시 간접적으로 간접 호출할 수 있는 프로세스를 시작하는 **재귀적 간접 호출을 사용하지 마세요**. 리커시브 코드를 사용할 경우, 의도하지 않은 함수 호출이 증가하고 비용이 상승할 수 있습니다. 의도치 않게 간접 호출이 대량으로 발생하는 경우 함수의 예약된 동시성을 즉시 `0`으로 설정하여 코드를 업데이트하는 동안 해당 함수에 대한 모든 간접 호출을 제한합니다.

Lambda 함수 코드에는 **문서화되지 않은 비공개 API를 사용하지 마세요.** AWS Lambda 관리형 런타임의 경우, Lambda는 주기적으로 보안 및 기능 업데이트를 Lambda의 내부 API에 적용합니다. 이러한 내부 API 업데이트는 이전 버전과 호환되지 않으므로 함수가 이러한 비공개 API에 종속성을 갖는 경우 호출 실패와 같은 의도하지 않은 결과를 초래할 수 있습니다. 공개적으로 사용 가능한 API의 목록은 [API 레퍼런스](https://docs.aws.amazon.com/lambda/latest/api/welcome.html)를 참조하세요.

**멱등성 코드를 작성합니다.** 함수에 멱등성 코드를 작성하면 중복 이벤트가 동일한 방식으로 처리됩니다. 코드는 이벤트를 올바르게 검증하고 중복 이벤트를 정상적으로 처리해야 합니다. 자세한 내용은 [멱등성 Lambda 함수를 만들려면 어떻게 해야 합니까?](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-function-idempotent/) 단원을 참조하십시오.

# Lambda 컨텍스트 객체를 사용하여 Rust 함수 정보 검색
<a name="rust-context"></a>

Lambda가 함수를 실행하면 [핸들러](rust-handler.md)가 수신하는 LambdaEvent에 컨텍스트 객체가 추가됩니다. 이 객체는 호출, 함수 및 실행 환경에 관한 정보를 속성에 제공합니다.

**컨텍스트 속성**
+  `request_id`: Lambda 서비스에서 생성한 AWS 요청 ID입니다.
+  `deadline`: 현재 호출의 실행 기한(밀리초)입니다.
+  `invoked_function_arn`: 간접 호출 중인 Lambda 함수의 Amazon 리소스 이름(ARN)입니다.
+  `xray_trace_id`: 현재 호출에 대한 AWS X-Ray 기록 ID입니다.
+  `client_content`: AWS 모바일 SDK에서 전송한 클라이언트 컨텍스트 객체입니다. AWS 모바일 SDK를 사용하여 함수를 간접 호출하지 않는 한 이 필드는 비어 있습니다.
+  `identity`: 함수를 간접 호출한 Amazon Cognito ID입니다. Lambda API에 대한 호출 요청이 Amazon Cognito 자격 증명 풀에서 발급한 AWS 자격 증명을 사용하여 이루어지지 않은 경우 이 필드는 비어 있습니다.
+  `env_config`: 로컬 환경 변수의 Lambda 함수 구성입니다. 이 속성에는 함수 이름, 메모리 할당, 버전 및 로그 스트림과 같은 정보가 포함됩니다.

## 간접 호출 컨텍스트 정보 액세스
<a name="rust-context-invoke"></a>

Lambda 함수들은 자신의 환경과 호출 요청에 관한 메타데이터에 액세스할 수 있습니다. 함수 핸들러가 수신하는 `LambaEvent` 객체에는 `context` 메타데이터가 포함됩니다.

```
use lambda_runtime::{service_fn, LambdaEvent, Error};
use serde_json::{json, Value};

async fn handler(event: LambdaEvent<Value>) -> Result<Value, Error> {
    let invoked_function_arn = event.context.invoked_function_arn;
    Ok(json!({ "message": format!("Hello, this is function {invoked_function_arn}!") }))
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    lambda_runtime::run(service_fn(handler)).await
}
```

# Rust로 HTTP 이벤트 처리
<a name="rust-http-events"></a>

Amazon API Gateway APIs, Application Load Balancer 및 [Lambda 함수 URL](urls-configuration.md)에서 Lambda에 HTTP 이벤트를 전송할 수 있습니다. crates.io의 [aws\$1lambda\$1events](https://crates.io/crates/aws_lambda_events) 크레이트를 사용하여 이러한 소스의 이벤트를 처리할 수 있습니다.

**Example - API Gateway 프록시 요청 처리**  
다음 사항에 유의하세요.  
+ `use aws_lambda_events::apigw::{ApiGatewayProxyRequest, ApiGatewayProxyResponse}`: [aws\$1lambda\$1events](https://crates.io/crates/aws-lambda-events) 크레이트에는 많은 Lambda 이벤트가 포함되어 있습니다. 컴파일 시간을 줄이려면 기능 플래그를 사용하여 필요한 이벤트를 활성화하세요. 예시: `aws_lambda_events = { version = "0.8.3", default-features = false, features = ["apigw"] }`.
+ `use http::HeaderMap`: 이 가져오기를 수행하려면 종속 구성 요소에 [http](https://crates.io/crates/http) 크레이트를 추가해야 합니다.

```
use aws_lambda_events::apigw::{ApiGatewayProxyRequest, ApiGatewayProxyResponse};
use http::HeaderMap;
use lambda_runtime::{service_fn, Error, LambdaEvent};

async fn handler(
    _event: LambdaEvent<ApiGatewayProxyRequest>,
) -> Result<ApiGatewayProxyResponse, Error> {
    let mut headers = HeaderMap::new();
    headers.insert("content-type", "text/html".parse().unwrap());
    let resp = ApiGatewayProxyResponse {
        status_code: 200,
        multi_value_headers: headers.clone(),
        is_base64_encoded: false,
        body: Some("Hello AWS Lambda HTTP request".into()),
        headers,
    };
    Ok(resp)
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    lambda_runtime::run(service_fn(handler)).await
}
```

[Lambda용 Rust 런타임 클라이언트](https://github.com/aws/aws-lambda-rust-runtime)는 이벤트를 전송하는 서비스에 관계없이 기본 HTTP 유형으로 작업할 수 있도록 하는 이러한 이벤트 유형에 대한 추상화도 제공합니다. 다음 코드는 이전 예제와 동일하며 Lambda 함수 URL, Application Load Balancer 및 API Gateway와 함께 즉시 작동합니다.

**참고**  
[lambda\$1http](https://crates.io/crates/lambda_http) 크레이트는 아래에 있는 [lambda\$1runtime](https://crates.io/crates/lambda_runtime) 크레이트를 사용합니다. `lambda_runtime`을 별도로 가져올 필요가 없습니다.

**Example - HTTP 요청 처리**  

```
use lambda_http::{service_fn, Error, IntoResponse, Request, RequestExt, Response};

async fn handler(event: Request) -> Result<impl IntoResponse, Error> {
    let resp = Response::builder()
        .status(200)
        .header("content-type", "text/html")
        .body("Hello AWS Lambda HTTP request")
        .map_err(Box::new)?;
    Ok(resp)
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    lambda_http::run(service_fn(handler)).await
}
```

`lambda_http` 사용 방법의 또 다른 예는 AWS Labs GitHub 리포지토리의[http-axum 코드 샘플](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/http-axum/src/main.rs)을 참조하세요.

**Rust용 샘플 HTTP Lambda 이벤트**
+ [Lambda HTTP 이벤트](https://github.com/aws/aws-lambda-rust-runtime/tree/main/examples/http-basic-lambda): HTTP 이벤트를 처리하는 Rust 함수입니다.
+ [CORS 헤더가 포함된 Lambda HTTP 이벤트](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/http-cors): Tower를 사용하여 CORS 헤더를 삽입하는 Rust 함수입니다.
+ [공유 리소스가 포함된 Lambda HTTP 이벤트](https://github.com/aws/aws-lambda-rust-runtime/tree/main/examples/basic-shared-resource): 함수 핸들러가 생성되기 전에 초기화된 공유 리소스를 사용하는 Rust 함수입니다.

# .zip 파일 아카이브를 사용하여 Rust Lambda 함수 배포
<a name="rust-package"></a>

이 페이지에서는 Rust 함수를 컴파일한 다음 [Cargo Lambda](https://www.cargo-lambda.info/guide/what-is-cargo-lambda.html)를 사용하여 컴파일된 바이너리를 AWS Lambda에 배포하는 방법을 설명합니다. 또한 AWS Command Line Interface 및 AWS Serverless Application Model CLI를 사용하여 컴파일된 바이너리를 배포하는 방법도 보여줍니다.

**Topics**
+ [

## 사전 조건
](#rust-package-prerequisites)
+ [

## macOS, Windows 또는 Linux에서 Rust 함수 빌드
](#rust-package-build)
+ [

## Cargo Lambda로 Rust 함수 바이너리 배포
](#rust-deploy-cargo)
+ [

## Cargo Lambda로 Rust 함수 호출
](#rust-invoke-function)

## 사전 조건
<a name="rust-package-prerequisites"></a>
+ [Rust](https://www.rust-lang.org/tools/install)
+ [AWS CLI 버전 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)

## macOS, Windows 또는 Linux에서 Rust 함수 빌드
<a name="rust-package-build"></a>

다음 단계에서는 Rust를 사용하여 첫 번째 Lambda 함수에 대한 프로젝트를 생성하고 Rust Lambda 함수 빌드 및 배포를 간소화하는 Cargo 명령줄 도구의 타사 오픈 소스 확장인 [Cargo Lambda](https://www.cargo-lambda.info/)로 프로젝트를 컴파일하는 방법을 보여줍니다.

1. Cargo 명령줄 도구에 Rust Lambda 함수 빌드 및 배포를 간소화하는 타사 오픈 소스 확장인 [Cargo Lambda](https://www.cargo-lambda.info/guide/what-is-cargo-lambda.html)를 설치합니다.

   ```
   cargo install cargo-lambda
   ```

   다른 옵션은 Cargo Lambda 설명서의 [Installation](https://www.cargo-lambda.info/guide/installation.html)을 참조하세요.

1. 패키지 구조를 생성합니다. 이 명령은 `src/main.rs`에 몇 가지 기본 함수 코드를 생성합니다. 이 코드를 테스트에 사용하거나 사용자 고유의 코드로 바꿀 수 있습니다.

   ```
   cargo lambda new my-function
   ```

1. 패키지의 루트 디렉터리 내에서 [build](https://www.cargo-lambda.info/commands/build.html) 하위 명령을 실행하여 함수의 코드를 컴파일합니다.

   ```
   cargo lambda build --release
   ```

   (선택 사항) Lambda에서 AWS Graviton2를 사용하려면 `--arm64` 플래그를 추가하여 ARM CPU용 코드를 컴파일합니다.

   ```
   cargo lambda build --release --arm64
   ```

1. Rust 함수를 배포하기 전에 머신에서 AWS 자격 증명을 구성합니다.

   ```
   aws configure
   ```

## Cargo Lambda로 Rust 함수 바이너리 배포
<a name="rust-deploy-cargo"></a>

[deploy](https://www.cargo-lambda.info/commands/deploy.html) 하위 명령을 사용하여 컴파일된 바이너리를 Lambda에 배포합니다. 이 명령은 [실행 역할](lambda-intro-execution-role.md)을 생성한 다음 Lambda 함수를 생성합니다. 기존 실행 역할을 지정하려면 [--iam-role 플래그](https://www.cargo-lambda.info/commands/deploy.html#iam-roles)를 사용합니다.

```
cargo lambda deploy my-function
```

### AWS CLI로 Rust 함수 바이너리 배포
<a name="rust-deploy-aws-cli"></a>

AWS CLI로 바이너리를 배포할 수도 있습니다.

1. [build](https://www.cargo-lambda.info/commands/build.html) 하위 명령을 사용하여 .zip 배포 패키지를 빌드합니다.

   ```
   cargo lambda build --release --output-format zip
   ```

1. .zip 패키지를 Lambda에 배포하려면 [create-function](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-function.html) 명령을 실행합니다.
   + `--runtime`에서 `provided.al2023`를 지정합니다. 이는 [OS 전용 런타임](runtimes-provided.md)입니다. OS 전용 런타임은 컴파일된 바이너리와 사용자 지정 런타임을 Lambda에 배포하는 데 사용됩니다.
   + `--role`에서 [실행 역할](lambda-intro-execution-role.md)의 ARN을 지정합니다.

   ```
   aws lambda create-function \
        --function-name my-function \
        --runtime provided.al2023 \
        --role arn:aws:iam::111122223333:role/lambda-role \
        --handler rust.handler \
        --zip-file fileb://target/lambda/my-function/bootstrap.zip
   ```

### AWS SAM CLI로 Rust 함수 바이너리 배포
<a name="rust-deploy-sam-cli"></a>

AWS SAM CLI로 바이너리를 배포할 수도 있습니다.

1. 리소스와 속성 정의를 사용하여 AWS SAM 템플릿을 생성합니다. `Runtime`에서 `provided.al2023`를 지정합니다. 이는 [OS 전용 런타임](runtimes-provided.md)입니다. OS 전용 런타임은 컴파일된 바이너리와 사용자 지정 런타임을 Lambda에 배포하는 데 사용됩니다.

   AWS SAM을 사용한 Lambda 함수 배포에 대한 자세한 내용은 **AWS Serverless Application Model 개발자 안내서의 [AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html)을 참조하세요.  
**Example Rust 바이너리에 대한 SAM 리소스 및 속성 정의**  

   ```
   AWSTemplateFormatVersion: '2010-09-09'
   Transform: AWS::Serverless-2016-10-31
   Description: SAM template for Rust binaries
   Resources:
     RustFunction:
       Type: AWS::Serverless::Function 
       Properties:
         CodeUri: target/lambda/my-function/
         Handler: rust.handler
         Runtime: provided.al2023
   Outputs:
     RustFunction:
       Description: "Lambda Function ARN"
       Value: !GetAtt RustFunction.Arn
   ```

1. [build](https://www.cargo-lambda.info/commands/build.html) 하위 명령을 사용하여 함수를 컴파일합니다.

   ```
   cargo lambda build --release
   ```

1. [sam deploy](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-deploy.html) 명령을 사용하여 함수를 Lambda에 배포합니다.

   ```
   sam deploy --guided
   ```

AWS SAM CLI를 사용하여 Rust 함수를 빌드하는 방법에 대한 자세한 내용은 **AWS Serverless Application Model 개발자 안내서의 [Cargo Lambda로 Rust Lambda 함수 빌드](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/building-rust.html)를 참조하세요.

## Cargo Lambda로 Rust 함수 호출
<a name="rust-invoke-function"></a>

[간접 호출](https://www.cargo-lambda.info/commands/invoke.html) 하위 명령을 사용하여 페이로드로 함수를 테스트합니다.

```
cargo lambda invoke --remote --data-ascii '{"command": "Hello world"}' my-function
```

### AWS CLI로 Rust 함수 호출
<a name="rust-invoke-cli"></a>

AWS CLI를 사용하여 함수를 간접 호출할 수도 있습니다.

```
aws lambda invoke --function-name my-function --cli-binary-format raw-in-base64-out --payload '{"command": "Hello world"}' /tmp/out.txt
```

**cli-binary-format** 옵션은 AWS CLI 버전 2를 사용할 때 필요합니다. 이 설정을 기본 설정으로 지정하려면 `aws configure set cli-binary-format raw-in-base64-out`을(를) 실행하세요. 자세한 내용은 *AWS Command Line Interface 사용 설명서 버전 2*에서 [AWS CLI 지원 글로벌 명령줄 옵션](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)을 참조하세요.

# Rust Lambda 함수를 위한 계층 작업
<a name="rust-layers"></a>

Rust로 작성된 Lambda 함수의 종속성을 관리하는 데는[ 계층](chapter-layers.md)을 사용하지 않는 것이 좋습니다. 이는 Rust의 Lambda 함수가 단일 실행 파일로 컴파일되어 함수를 배포할 때 Lambda에 제공하기 때문입니다. 이 실행 파일에는 컴파일된 함수 코드와 모든 종속성이 포함되어 있습니다. 계층을 사용하면 이 프로세스가 복잡해질 뿐만 아니라 함수가 초기화 단계에서 추가 어셈블리를 메모리에 수동으로 로드해야 하기 때문에 콜드 스타트 시간이 늘어납니다.

Rust 핸들러와 함께 외부 종속성을 사용하려면 배포 패키지에 외부 종속성을 직접 포함하세요. 이렇게 하면 배포 프로세스를 간소화하고 내장된 Rust 컴파일러 최적화를 활용할 수 있습니다. 함수에서 AWS SDK for Rust와 같은 종속 항목을 가져와서 사용하는 방법에 대한 예시는 [Rust에서 Lambda 함수 핸들러 정의](rust-handler.md) 섹션을 참조하세요.

# Rust Lambda 함수 기록 및 모니터링
<a name="rust-logging"></a>

AWS Lambda는 자동으로 Lambda 함수를 모니터링하고 로그를 Amazon CloudWatch로 보냅니다. Lambda 함수는 함수의 각 인스턴스에 대한 CloudWatch Logs 로그 그룹 및 로그 스트림과 함께 제공됩니다. Lambda 런타임 환경은 각 호출에 관한 세부 정보를 로그 스트림에 전송하며, 함수 코드에서 로그 및 그 외 출력을 중계합니다. 자세한 내용은 [CloudWatch Logs로 Lambda 함수 로그 전송](monitoring-cloudwatchlogs.md) 섹션을 참조하세요. 로그 형식 구성에 대한 자세한 내용은 [JSON 및 일반 텍스트 로그 형식 구성](monitoring-cloudwatchlogs-logformat.md) 항목을 참조하세요. 이 페이지에서는 Lambda 함수의 코드에서 로그 출력을 생성하는 방법을 설명합니다.

## 로그를 작성하는 함수 생성
<a name="rust-logging-function"></a>

함수 코드에서 로그를 출력하려면 `println!` 매크로와 같이 `stdout` 또는 `stderr`에 기록하는 모든 로깅 함수를 사용할 수 있습니다. 다음 예제에서는 `println!`을 사용하여 함수 처리기가 시작될 때와 완료되기 전에 메시지를 인쇄합니다.

```
use lambda_runtime::{service_fn, LambdaEvent, Error};
use serde_json::{json, Value};
async fn handler(event: LambdaEvent<Value>) -> Result<Value, Error> {
    println!("Rust function invoked");
    let payload = event.payload;
    let first_name = payload["firstName"].as_str().unwrap_or("world");
    println!("Rust function responds to {}", &first_name);
    Ok(json!({ "message": format!("Hello, {first_name}!") }))
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    lambda_runtime::run(service_fn(handler)).await
}
```

## Tracing 크레이트를 사용한 고급 로깅 구현
<a name="rust-logging-tracing"></a>

[Tracing](https://crates.io/crates/tracing)은 구조화된 이벤트 기반 진단 정보를 수집하기 위해 Rust 프로그램을 계측하기 위한 프레임워크입니다. 이 프레임워크는 구조화된 JSON 로그 메시지 생성과 같은 로깅 출력 수준 및 형식을 사용자 지정하는 유틸리티를 제공합니다. 이 프레임워크를 사용하려면 함수 핸들러를 구현하기 전에 `subscriber`를 초기화해야 합니다. 그런 다음 `debug`, `info`, `error` 등의 추적 매크로를 사용하여 각 시나리오에 대해 원하는 로깅 수준을 지정할 수 있습니다.

**Example - Tracing 크레이트 사용**  
다음 사항에 유의하세요.  
+ `tracing_subscriber::fmt().json()`: 이 옵션을 포함하면 로그 형식이 JSON으로 지정됩니다. 이 옵션을 사용하려면 `tracing-subscriber` 종속 구성 요소에 `json` 기능을 포함해야 합니다(예: `tracing-subscriber = { version = "0.3.11", features = ["json"] }`).
+ `#[tracing::instrument(skip(event), fields(req_id = %event.context.request_id))]`: 이 주석은 핸들러가 간접 호출될 때마다 스팬을 생성합니다. 스팬은 각 로그 라인에 요청 ID를 추가합니다.
+ `{ %first_name }`: 이 구성은 `first_name` 필드를 사용되는 로그 라인에 추가합니다. 이 필드의 값은 같은 이름의 변수에 해당합니다.

```
use lambda_runtime::{service_fn, Error, LambdaEvent};
use serde_json::{json, Value};
#[tracing::instrument(skip(event), fields(req_id = %event.context.request_id))]
async fn handler(event: LambdaEvent<Value>) -> Result<Value, Error> {
    tracing::info!("Rust function invoked");
    let payload = event.payload;
    let first_name = payload["firstName"].as_str().unwrap_or("world");
    tracing::info!({ %first_name }, "Rust function responds to event");
    Ok(json!({ "message": format!("Hello, {first_name}!") }))
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    tracing_subscriber::fmt().json()
        .with_max_level(tracing::Level::INFO)
        // this needs to be set to remove duplicated information in the log.
        .with_current_span(false)
        // this needs to be set to false, otherwise ANSI color codes will
        // show up in a confusing manner in CloudWatch logs.
        .with_ansi(false)
        // disabling time is handy because CloudWatch will add the ingestion time.
        .without_time()
        // remove the name of the function from every log entry
        .with_target(false)
        .init();
    lambda_runtime::run(service_fn(handler)).await
}
```

이 Rust 함수가 간접 호출되면 다음과 유사한 2개의 로그 라인이 인쇄됩니다.

```
{"level":"INFO","fields":{"message":"Rust function invoked"},"spans":[{"req_id":"45daaaa7-1a72-470c-9a62-e79860044bb5","name":"handler"}]}
{"level":"INFO","fields":{"message":"Rust function responds to event","first_name":"David"},"spans":[{"req_id":"45daaaa7-1a72-470c-9a62-e79860044bb5","name":"handler"}]}
```