

# C\$1을 사용하여 Lambda 함수 빌드
<a name="lambda-csharp"></a>

관리형 .NET 8 런타임, 사용자 지정 런타임 또는 컨테이너 이미지를 사용하여 Lambda에서 .NET 애플리케이션을 실행할 수 있습니다. 애플리케이션 코드가 컴파일된 후에는 .zip 파일 또는 컨테이너 이미지로 Lambda에 배포할 수 있습니다. Lambda는 .NET 언어에 대해 다음과 같은 런타임을 제공합니다.


| 이름 | 식별자 | 운영 체제 | 사용 중단 날짜 | 블록 함수 생성 | 블록 함수 업데이트 | 
| --- | --- | --- | --- | --- | --- | 
|  .NET 10  |  `dotnet10`  |  Amazon Linux 2023  |   2028년 11월 14일   |   2028년 12월 14일   |   2029년 1월 15일   | 
|  .NET 9(컨테이너만 해당)  |  `dotnet9`  |  Amazon Linux 2023  |   2026년 11월 10일   |   예약되지 않음   |   예약되지 않음   | 
|  .NET 8  |  `dotnet8`  |  Amazon Linux 2023  |   2026년 11월 10일   |   2026년 12월 10일   |   2027년 1월 11일   | 

## .NET 개발 환경 설정
<a name="csharp-dev-env"></a>

Lambda 함수를 개발하고 빌드하려면 Microsoft Visual Studio, Visual Studio Code 및 JetBrains Rider를 비롯한 일반적으로 사용 가능한 .NET 통합 개발 환경(IDE)을 아무거나 이용하면 됩니다. 개발 환경을 단순화하기 위해.AWS은(는) NET 프로젝트 템플릿 세트와 `Amazon.Lambda.Tools` 명령줄 인터페이스(CLI)를 제공합니다.

다음.NET CLI 명령을 실행하여 이 프로젝트 템플릿과 명령줄 도구를 설치합니다.

### .NET 프로젝트 템플릿 설치
<a name="csharp-dev-env-templates"></a>

이 템플릿 패키지를 설치하려면 다음 명령을 실행합니다.

```
dotnet new install Amazon.Lambda.Templates
```

### CLI 도구 설치 및 업데이트
<a name="csharp-dev-env-cli-tools"></a>

다음 명령을 실행하여 `Amazon.Lambda.Tools` CLI를 설치, 업데이트 및 제거합니다.

명령줄 도구 설치하기:

```
dotnet tool install -g Amazon.Lambda.Tools
```

명령줄 도구 업데이트:

```
dotnet tool update -g Amazon.Lambda.Tools
```

명령줄 도구 제거:

```
dotnet tool uninstall -g Amazon.Lambda.Tools
```

# C\$1에서 Lambda 함수 핸들러 정의
<a name="csharp-handler"></a>

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

이 페이지에서는 프로젝트 설정, 이름 지정 규칙, 모범 사례 등 C\$1에서 Lambda 함수 핸들러를 사용하여 .NET 관리형 런타임으로 작업하는 방법을 설명합니다. 이 페이지에는 주문에 대한 정보를 가져와서 텍스트 파일 영수증을 생성하고 해당 파일을 Amazon Simple Storage Service(S3) 버킷에 넣는 C\$1 Lambda 함수의 예제도 포함되어 있습니다. 함수를 작성한 후 배포하는 방법에 대한 자세한 내용은 [.zip 파일 아카이브를 사용하여 C\$1 Lambda 함수를 빌드 및 배포](csharp-package.md) 또는 [컨테이너 이미지를 사용하여 .NET Lambda 함수 배포](csharp-image.md) 섹션을 참조하세요.

**Topics**
+ [

## C\$1 핸들러 프로젝트 설정
](#csharp-handler-setup)
+ [

## 예제 C\$1 Lambda 함수 코드
](#csharp-example-code)
+ [

## 클래스 라이브러리 핸들러
](#csharp-class-library-handlers)
+ [

## 실행 가능한 어셈블리 핸들러
](#csharp-executable-assembly-handlers)
+ [

## C\$1 함수에 유효한 핸들러 서명
](#csharp-handler-signatures)
+ [

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

## C\$1 Lambda 함수의 직렬화
](#csharp-handler-serializer)
+ [

## 파일 기반 함수
](#csharp-file-based-functions)
+ [

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

## 핸들러에서 SDK for .NET v3 사용
](#csharp-example-sdk-usage)
+ [

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

## 전역 상태 사용
](#csharp-handler-state)
+ [

## Lambda 주석 프레임워크를 사용하여 함수 코드를 간소화합니다
](#csharp-handler-annotations)
+ [

## C\$1 Lambda 함수의 코드 모범 사례
](#csharp-best-practices)

## C\$1 핸들러 프로젝트 설정
<a name="csharp-handler-setup"></a>

C\$1에서 Lambda 함수를 사용할 때는 코드를 작성한 다음 Lambda에 코드를 배포하는 작업이 프로세스에 포함됩니다. .NET에서 Lambda 함수를 배포하기 위한 두 가지 실행 모델, 즉 클래스 라이브러리 접근 방식과 실행 가능한 어셈블리 접근 방식이 있습니다.

클래스 라이브러리 접근 방식에서는 함수 코드를 .NET 어셈블리(`.dll`)로 패키징하고 .NET 관리형 런타임(`dotnet8`)을 사용하여 Lambda에 배포합니다. 핸들러 이름의 경우 Lambda는 `AssemblyName::Namespace.Classname::Methodname` 형식의 문자열을 예상합니다. 함수 초기화 단계에서 함수 클래스가 초기화되고 생성자의 코드가 실행됩니다.

실행 가능한 어셈블리 접근 방식에서는 C\$1 9에 처음 도입된 [최상위 문 기능](https://learn.microsoft.com/en-us/dotnet/csharp/tutorials/top-level-statements)을 사용합니다. 이 접근 방식은 함수에 대한 간접 호출 명령을 수신할 때마다 Lambda가 실행하는 실행 가능한 어셈블리를 생성합니다. 이 접근 방식에서는 .NET 관리형 런타임(`dotnet8`)도 사용합니다. 핸들러 이름에는 실행할 실행 가능한 어셈블리의 이름을 Lambda에 제공합니다.

이 페이지의 기본 예제는 클래스 라이브러리 접근 방식을 보여줍니다. C\$1 Lambda 프로젝트를 다양한 방식으로 초기화할 수 있지만 가장 쉬운 방법은 `Amazon.Lambda.Tools` CLI와 함께 .NET CLI를 사용하는 것입니다. [.NET 개발 환경 설정](lambda-csharp.md#csharp-dev-env)의 단계에 따라 `Amazon.Lambda.Tools` CLI를 설정합니다. 그리고 다음 명령을 사용하여 프로젝트를 초기화합니다.

```
dotnet new lambda.EmptyFunction --name ExampleCS
```

이 명령은 다음과 같은 파일 구조를 생성합니다.

```
/project-root 
    └ src
        └ ExampleCS
            └ Function.cs (contains main handler)
            └ Readme.md
            └ aws-lambda-tools-defaults.json
            └ ExampleCS.csproj          
    └ test
         └ ExampleCS.Tests
            └ FunctionTest.cs (contains main handler)
            └ ExampleCS.Tests.csproj
```

이 파일 구조에서 함수의 기본 핸들러 로직은 `Function.cs` 파일에 있습니다.

## 예제 C\$1 Lambda 함수 코드
<a name="csharp-example-code"></a>

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

**Example `Function.cs` Lambda 함수**  

```
using System;
using System.Text;
using System.Threading.Tasks;
using Amazon.Lambda.Core;
using Amazon.S3;
using Amazon.S3.Model;

// Assembly attribute to enable Lambda function logging
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace ExampleLambda;

public class Order
{
    public string OrderId { get; set; } = string.Empty;
    public double Amount { get; set; }
    public string Item { get; set; } = string.Empty;
}

public class OrderHandler
{
    private static readonly AmazonS3Client s3Client = new();

    public async Task<string> HandleRequest(Order order, ILambdaContext context)
    {
        try
        {
            string? bucketName = Environment.GetEnvironmentVariable("RECEIPT_BUCKET");
            if (string.IsNullOrWhiteSpace(bucketName))
            {
                throw new ArgumentException("RECEIPT_BUCKET environment variable is not set");
            }

            string receiptContent = $"OrderID: {order.OrderId}\nAmount: ${order.Amount:F2}\nItem: {order.Item}";
            string key = $"receipts/{order.OrderId}.txt";

            await UploadReceiptToS3(bucketName, key, receiptContent);

            context.Logger.LogInformation($"Successfully processed order {order.OrderId} and stored receipt in S3 bucket {bucketName}");
            return "Success";
        }
        catch (Exception ex)
        {
            context.Logger.LogError($"Failed to process order: {ex.Message}");
            throw;
        }
    }

    private async Task UploadReceiptToS3(string bucketName, string key, string receiptContent)
    {
        try
        {
            var putRequest = new PutObjectRequest
            {
                BucketName = bucketName,
                Key = key,
                ContentBody = receiptContent,
                ContentType = "text/plain"
            };

            await s3Client.PutObjectAsync(putRequest);
        }
        catch (AmazonS3Exception ex)
        {
            throw new Exception($"Failed to upload receipt to S3: {ex.Message}", ex);
        }
    }
}
```

`Function.cs` 파일은 다음 코드 섹션을 포함하고 있습니다.
+ `using` 문: Lambda 함수에 필요한 C\$1 클래스를 가져오는 데 사용합니다.
+ `[assembly: LambdaSerializer(...)]`: `LambdaSerializer`는 함수에 전달하기 전에 JSON 이벤트 페이로드를 C\$1 객체로 자동 변환하도록 Lambda에 지시하는 어셈블리 속성입니다.
+ `namespace ExampleLambda`: 네임스페이스를 정의합니다. C\$1에서 네임스페이스 이름은 파일 이름과 일치하지 않아도 됩니다.
+ `public class Order {...}`: 예상 입력 이벤트의 셰이프를 정의합니다.
+ `public class OrderHandler {...}`: C\$1 클래스를 정의합니다. 그 안에 기본 핸들러 메서드와 기타 도우미 메서드를 정의합니다.
+ `private static readonly AmazonS3Client s3Client = new();`: 기본 핸들러 메서드 외부에서 기본 자격 증명 공급자 체인으로 Amazon S3 클라이언트를 초기화합니다. 이렇게 하면 [초기화 단계](lambda-runtime-environment.md#runtimes-lifecycle-ib)에서 Lambda가 이 코드를 실행합니다.
+ `public async ... HandleRequest (Order order, ILambdaContext context)`: 기본 애플리케이션 논리를 포함한 **기본 핸들러 메서드**입니다.
+ `private async Task UploadReceiptToS3(...) {}`: 기본 `handleRequest` 핸들러 메서드에서 참조하는 도우미 메서드입니다.

이 함수에는 Amazon S3 SDK 클라이언트가 필요하므로 프로젝트의 종속성에 이를 추가해야 합니다. `src/ExampleCS`로 이동하고 다음 명령을 실행하면 됩니다.

```
dotnet add package AWSSDK.S3
```

### aws-lambda-tools-defaults.json에 메타데이터 정보 추가
<a name="csharp-metadata-example"></a>

기본적으로 생성된 `aws-lambda-tools-defaults.json` 파일에는 함수에 대한 `profile` 또는 `region` 정보가 없습니다. 또한 `function-handler` 문자열을 올바른 값(`ExampleCS::ExampleLambda.OrderHandler::HandleRequest`)으로 업데이트합니다. 수동으로 이 업데이트를 수행하고 필요한 메타데이터를 추가하여 함수에 특정 자격 증명 프로필과 리전을 사용할 수 있습니다. 예를 들어, `aws-lambda-tools-defaults.json` 파일은 다음과 유사해야 합니다.

```
{
  "Information": [
    "This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI.",
    "To learn more about the Lambda commands with the .NET Core CLI execute the following command at the command line in the project root directory.",
    "dotnet lambda help",
    "All the command line options for the Lambda command can be specified in this file."
  ],
  "profile": "default",
  "region": "us-east-1",
  "configuration": "Release",
  "function-architecture": "x86_64",
  "function-runtime": "dotnet8",
  "function-memory-size": 512,
  "function-timeout": 30,
  "function-handler": "ExampleCS::ExampleLambda.OrderHandler::HandleRequest"
}
```

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

## 클래스 라이브러리 핸들러
<a name="csharp-class-library-handlers"></a>

이 페이지의 기본 [예제 코드](#csharp-example-code)는 클래스 라이브러리 핸들러를 보여줍니다. 클래스 라이브러리 핸들러의 구조는 다음과 같습니다.

```
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace NAMESPACE;

...

public class CLASSNAME {
    public async Task<string> METHODNAME (...) {
    ...
    }
}
```

Lambda 함수를 생성할 때는 함수 핸들러에 대한 정보를 [핸들러 필드](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html#lambda-CreateFunction-request-Handler)의 문자열 형태로 Lambda에 제공해야 합니다. 이를 통해 Lambda는 함수가 간접적으로 간접 호출될 때 코드의 어떤 메서드를 실행할지 알 수 있습니다. C\$1에서 클래스 라이브러리 핸들러의 경우 핸들러 문자열의 형식은 `ASSEMBLY::TYPE::METHOD`입니다.
+ `ASSEMBLY`은(는) 애플리케이션에 대한 .NET 어셈블리 파일의 이름입니다. `Amazon.Lambda.Tools` CLI를 사용하여 애플리케이션을 빌드하고 .`.csproj` 파일의 `AssemblyName` 속성을 사용하여 어셈블리 이름을 설정하지 않은 경우 `ASSEMBLY`는 단지`.csproj` 파일의 이름이 됩니다.
+ `TYPE`은 핸들러 유형의 전체 이름(`NAMESPACE.CLASSNAME`)입니다.
+ `METHOD`는 코드의 주요 핸들러 메서드 이름(`METHODNAME`)입니다.

이 페이지의 주요 예제 코드에서 어셈블리 이름이 `ExampleCS`인 경우 전체 핸들러 문자열은 `ExampleCS::ExampleLambda.OrderHandler::HandleRequest`입니다.

## 실행 가능한 어셈블리 핸들러
<a name="csharp-executable-assembly-handlers"></a>

C\$1에서 Lambda 함수를 실행 가능한 어셈블리로 정의할 수도 있습니다. 실행 가능한 어셈블리 핸들러는 컴파일러가 `Main()` 메서드를 생성하고 그 안에 함수 코드를 배치하는 C\$1의 최상위 문 기능을 활용합니다. 실행 가능한 어셈블리를 사용하는 경우 Lambda 런타임을 부트스트랩해야 합니다. 이렇게 하려면 코드에서 `LambdaBootstrapBuilder.Create` 메서드를 사용합니다. 이 메서드의 입력은 기본 핸들러 함수와 사용할 Lambda 직렬 변환기입니다. 다음은 C\$1의 실행 가능한 어셈블리 핸들러의 예입니다.

```
namespace GetProductHandler;

IDatabaseRepository repo = new DatabaseRepository();

await LambdaBootstrapBuilder.Create<APIGatewayProxyRequest>(Handler, new DefaultLambdaJsonSerializer())
    .Build()
    .RunAsync();

async Task<APIGatewayProxyResponse> Handler(APIGatewayProxyRequest apigProxyEvent, ILambdaContext context)
{
    var id = apigProxyEvent.PathParameters["id"];
    var databaseRecord = await this.repo.GetById(id);
    
    return new APIGatewayProxyResponse 
    {
        StatusCode = (int)HttpStatusCode.OK,
        Body = JsonSerializer.Serialize(databaseRecord)
    };
};
```

실행 가능한 어셈블리 핸들러의 [핸들러 필드](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html#lambda-CreateFunction-request-Handler)에서 Lambda에 코드 실행 방법을 알려주는 핸들러 문자열이 어셈블리의 이름입니다. 이 예제에서는 `GetProductHandler`입니다.

## C\$1 함수에 유효한 핸들러 서명
<a name="csharp-handler-signatures"></a>

C\$1에서 유효한 Lambda 핸들러 서명은 0\$12개의 인수를 사용합니다. 일반적으로 핸들러 서명에는 기본 예제와 같이 2개의 인수가 있습니다.

```
public async Task<string> HandleRequest(Order order, ILambdaContext context)
```

2개의 인수를 제공할 때 첫 번째 인수는 이벤트 입력이고 두 번째 인수는 Lambda 컨텍스트 객체여야 합니다. 두 인수 모두 선택 사항입니다. 예를 들어, 다음은 C\$1에서도 유효한 Lambda 핸들러 서명입니다.
+ `public async Task<string> HandleRequest()`
+ `public async Task<string> HandleRequest(Order order)`
+ `public async Task<string> HandleRequest(ILambdaContext context)`

핸들러 서명의 기본 구문 외에도 몇 가지 추가 제한 사항이 있습니다.
+ 핸들러 서명에는 `unsafe` 키워드를 사용할 수 없습니다. 그러나 핸들러 메서드와 해당 종속성 내에서 `unsafe` 컨텍스트를 사용할 수 있습니다. 자세한 내용은 Microsoft 설명서 웹 사이트에서 [unsafe(C\$1 reference)](https://msdn.microsoft.com/en-us/library/chfa2zb8.aspx)를 참조하세요.
+ 핸들러는 `params` 키워드를 사용하거나 `ArgIterator`를 입력 또는 반환 파라미터로 사용할 수 없습니다. 이러한 키워드는 다양한 수의 파라미터를 지원합니다. 핸들러가 수락할 수 있는 인수의 최대 개수는 2개입니다.
+ 핸들러는 일반 메서드가 아닐 수 있습니다. 즉, `<T>`와 같은 일반 유형 파라미터를 사용할 수 없습니다.
+ Lambda는 서명에 `async void`가 있는 async 핸들러를 지원하지 않습니다.

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

C\$1의 Lambda 핸들러에는 엄격한 이름 지정 제한이 없습니다. 그러나 함수를 배포할 때 Lambda에 올바른 핸들러 문자열을 제공해야 합니다. 올바른 핸들러 문자열은 [클래스 라이브러리 핸들러](#csharp-class-library-handlers)를 배포하는지 아니면 [실행 가능한 어셈블리 핸들러](#csharp-executable-assembly-handlers)를 배포하는지에 따라 달라집니다.

핸들러에 어떤 이름이든 사용할 수 있지만 C\$1에서는 함수 이름을 일반적으로 PascalCase로 지정합니다. 또한 파일 이름이 클래스 이름이나 핸들러 이름과 일치할 필요는 없지만 일반적으로 클래스 이름이 `OrderHandler`인 경우 `OrderHandler.cs`와 같은 파일 이름을 사용하는 것이 좋습니다. 예를 들어 이 예제의 파일 이름을 `Function.cs`에서 `OrderHandler.cs`로 수정할 수 있습니다.

## C\$1 Lambda 함수의 직렬화
<a name="csharp-handler-serializer"></a>

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

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

C\$1에서는 클래스에 예상 입력 이벤트의 셰이프를 정의할 수 있습니다. 이 예제에서는 `Order` 클래스를 정의하여 이 입력을 모델링합니다.

```
public class Order
{
    public string OrderId { get; set; } = string.Empty;
    public double Amount { get; set; }
    public string Item { get; set; } = string.Empty;
}
```

Lambda 함수가 `Stream` 객체 이외의 입력 또는 출력 유형을 사용하는 경우, 애플리케이션에 직렬화 라이브러리를 추가해야 합니다. 이를 통해 JSON 입력을 정의한 클래스의 인스턴스로 변환할 수 있습니다. Lambda에서 C\$1 함수를 직렬화하는 방법에는 리플렉션 기반 직렬화와 소스 생성 직렬화 두 가지가 있습니다.

### 리플렉션 기반 직렬화
<a name="csharp-reflection-based-serialization"></a>

AWS는 애플리케이션에 빠르게 추가할 수 있는 사전 구축된 라이브러리를 제공합니다. 이러한 라이브러리는 [리플렉션](https://learn.microsoft.com/en-us/dotnet/csharp/advanced-topics/reflection-and-attributes/)을 사용하여 직렬화를 구현합니다. 다음 패키지 중 하나를 사용하여 리플렉션 기반 직렬화를 구현합니다.
+ `Amazon.Lambda.Serialization.SystemTextJson` - 백엔드에서 이 패키지는 `System.Text.Json`을 사용하여 직렬화 태스크를 수행합니다.
+ `Amazon.Lambda.Serialization.Json` - 백엔드에서 이 패키지는 `Newtonsoft.Json`을 사용하여 직렬화 태스크를 수행합니다.

`ILambdaSerializer` 라이브러리의 일부로 사용할 수 있는 `Amazon.Lambda.Core` 인터페이스를 구현하여 자체 직렬화 라이브러리를 생성할 수도 있습니다. 이 인터페이스는 다음과 같은 두 가지 메서드를 정의합니다.
+ `T Deserialize<T>(Stream requestStream);`

  이 메서드를 구현하여 `Invoke` API에서 Lambda 함수 핸들러로 전달되는 객체로 요청 페이로드를 역직렬화합니다.
+ `T Serialize<T>(T response, Stream responseStream);`

  이 메서드를 구현하여 Lambda 함수 핸들러에서 반환된 결과를 `Invoke` API 작업에서 반환된 응답 페이로드로 직렬화합니다.

이 페이지의 기본 예제에서는 리플렉션 기반 직렬화를 사용합니다. 리플렉션 기반 직렬화는 AWS Lambda에서 즉시 작동하며 추가 설정이 필요 없으므로 단순성 면에서 좋은 선택입니다. 하지만 더 많은 함수 메모리 사용량이 필요합니다. 런타임 리플렉션으로 인해 함수 지연 시간이 늘어날 수도 있습니다.

### 소스 생성 직렬화
<a name="csharp-source-generated-serialization"></a>

소스 생성 직렬화를 사용하면 컴파일 시 직렬화 코드가 생성됩니다. 이를 통해 리플렉션이 필요하지 않으며 함수의 성능을 향상시킬 수 있습니다. 함수에서 소스 생성 직렬화를 사용하려면 다음을 수행해야 합니다.
+ `JsonSerializerContext`에서 상속되는 새 부분 클래스를 생성하면서 직렬화 또는 역직렬화가 필요한 모든 유형에 대한 `JsonSerializable` 속성을 추가합니다.
+ `SourceGeneratorLambdaJsonSerializer<T>`을(를) 사용하여 `LambdaSerializer`을(를) 구성합니다.
+ 새로 생성한 클래스를 사용하도록 애플리케이션 코드의 수동 직렬화 및 역직렬화를 업데이트합니다.

다음 예제에서는 리플렉션 기반 직렬화를 사용하는 이 페이지의 기본 예제를 소스 생성 직렬화를 사용하도록 수정하는 방법을 보여줍니다.

```
using System.Text.Json;
using System.Text.Json.Serialization;

...

public class Order
{
    public string OrderId { get; set; } = string.Empty;
    public double Amount { get; set; }
    public string Item { get; set; } = string.Empty;
}

[JsonSerializable(typeof(Order))]
public partial class OrderJsonContext : JsonSerializerContext {}

public class OrderHandler
{

    ...

    public async Task<string> HandleRequest(string input, ILambdaContext context)
    {
    
    var order = JsonSerializer.Deserialize(input, OrderJsonContext.Default.Order);
    
    ...
    
    }

}
```

소스 생성 직렬화에는 리플렉션 기반 직렬화보다 더 많은 설정이 필요합니다. 그러나 소스 생성 직렬화를 사용하는 함수는 컴파일 시 코드 생성으로 인해 메모리 사용량이 적고 성능이 더 좋은 경향이 있습니다. 함수 [콜드 스타트](lambda-runtime-environment.md#cold-start-latency)를 제거하려면 소스 생성 직렬화로 전환하는 것이 좋습니다.

**참고**  
Lambda를 통해 네이티브 [사전 컴파일(AOT)](dotnet-native-aot.md)을 사용하려면 소스 생성 직렬화를 사용해야 합니다.

## 파일 기반 함수
<a name="csharp-file-based-functions"></a>

.NET 10에 도입된 파일 기반 앱을 사용하면 `.csproj` 파일 또는 디렉터리 구조 없이 단일 `.cs` 파일에서 .NET 애플리케이션을 구축할 수 있습니다. Lambda는 .NET 10부터 파일 기반 함수를 지원합니다. 이러한 함수는 C\$1에서 Lambda 함수를 빌드하는 간소화된 방법을 제공합니다.

C\$1 파일 기반 Lambda 함수 생성을 시작하는 가장 빠른 방법은 `Amazon.Lambda.Templates` 패키지를 사용하는 것입니다. 이 패키지를 설치하려면 다음 명령을 실행합니다.

```
dotnet new install Amazon.Lambda.Templates
```

다음으로 C\$1 파일 기반 Lambda 예제 함수를 생성합니다.

```
dotnet new lambda.FileBased -n MyLambdaFunction
```

파일 기반 함수는 [실행 가능한 어셈블리 핸들러](#csharp-executable-assembly-handlers)를 사용합니다. 그러므로 `Amazon.Lambda.RuntimeSupport` NuGet 패키지를 포함하고 `LambdaBootstrapBuilder.Create` 메서드를 사용하여 이벤트 유형에 대한 .NET 핸들러 함수를 등록하고 .NET Lambda 런타임 클라이언트를 시작해야 합니다.

파일 기반 함수는 .NET 네이티브 AOT를 사용하며, 여기에는 기본적으로 소스 생성 직렬화가 필요합니다. 소스 파일에서 `#:property PublishAot=false`를 지정하여 네이티브 AOT를 비활성화할 수 있습니다. Lambda에서 네이티브 AOT를 사용하는 방법에 대한 자세한 내용은 [네이티브 런타임 형식으로 .NET Lambda 함수 코드 컴파일](dotnet-native-aot.md) 섹션을 참조하세요.

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

Lambda [컨텍스트 객체](csharp-context.md)에는 호출, 함수, 실행 환경에 관한 정보가 포함되어 있습니다. 이 예제에서 컨텍스트 객체는 `Amazon.Lambda.Core.ILambdaContext` 유형이며, 기본 핸들러 함수의 두 번째 인수입니다.

```
public async Task<string> HandleRequest(Order order, ILambdaContext context) {
    ...
}
```

컨텍스트 객체는 선택적 입력입니다. 허용되는 유효한 핸들러 서명에 대한 자세한 내용은 [C\$1 함수에 유효한 핸들러 서명](#csharp-handler-signatures) 섹션을 참조하세요.

컨텍스트 객체는 Amazon CloudWatch에 함수 로그를 생성하는 데 유용합니다. `context.getLogger()` 메서드를 사용하여 로깅을 위한 `LambdaLogger` 객체를 가져올 수 있습니다. 이 예제에서는 어떤 이유로든 처리가 실패할 경우 로거를 사용하여 오류 메시지를 로깅할 수 있습니다.

```
context.Logger.LogError($"Failed to process order: {ex.Message}");
```

로깅 외에도 함수 모니터링에 컨텍스트 객체를 사용할 수 있습니다. 컨텍스트 객체에 대한 자세한 내용은 [Lambda 컨텍스트 객체를 사용하여 C\$1 함수 정보 검색](csharp-context.md) 섹션을 참조하세요.

## 핸들러에서 SDK for .NET v3 사용
<a name="csharp-example-sdk-usage"></a>

종종 Lambda 함수를 사용하여 다른 AWS 리소스와 상호 작용하거나 업데이트하는 경우가 있습니다. 이러한 리소스와 인터페이스로 접속하는 가장 간단한 방법은 SDK for .NET v3를 사용하는 것입니다.

**참고**  
SDK for .NET(v2)은 더 이상 사용되지 않습니다. SDK for .NET v3만 사용하는 것을 권장합니다.

다음 `Amazon.Lambda.Tools` 명령을 사용하여 프로젝트에 SDK 종속성을 추가할 수 있습니다.

```
dotnet add package <package_name>
```

예를 들어 이 페이지의 기본 예제에서는 Amazon S3 API를 사용하여 S3에 영수증을 업로드해야 합니다. 다음 명령을 사용하여 Amazon S3 SDK 클라이언트를 가져올 수 있습니다.

```
dotnet add package AWSSDK.S3
```

이 명령은 프로젝트에 종속성을 추가합니다. 또한 프로젝트의 `.csproj` 파일에 다음과 유사한 줄이 표시되어야 합니다.

```
<PackageReference Include="AWSSDK.S3" Version="3.7.2.18" />
```

그런 다음, C\$1 코드에서 직접 종속성을 가져옵니다.

```
using Amazon.S3;
using Amazon.S3.Model;
```

그런 다음 예제 코드는 다음과 같이 Amazon S3 클라이언트를 초기화합니다([기본 자격 증명 공급자 체인](https://docs.aws.amazon.com/sdkref/latest/guide/standardized-credentials.html) 사용).

```
private static readonly AmazonS3Client s3Client = new();
```

이 예제에서는 함수를 간접적으로 호출할 때마다 초기화할 필요가 없도록 기본 핸들러 함수에서 Amazon S3 클라이언트를 초기화했습니다. SDK 클라이언트를 초기화한 후에는 이를 사용하여 다른 AWS 서비스와 상호 작용할 수 있습니다. 예제 코드는 다음과 같이 Amazon S3 `PutObject` API를 직접적으로 호출합니다.

```
var putRequest = new PutObjectRequest
{
    BucketName = bucketName,
    Key = key,
    ContentBody = receiptContent,
    ContentType = "text/plain"
};

await s3Client.PutObjectAsync(putRequest);
```

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

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

```
string? bucketName = Environment.GetEnvironmentVariable("RECEIPT_BUCKET");
if (string.IsNullOrWhiteSpace(bucketName))
{
    throw new ArgumentException("RECEIPT_BUCKET environment variable is not set");
}
```

## 전역 상태 사용
<a name="csharp-handler-state"></a>

Lambda는 함수를 처음 호출하기 전 [초기화 단계](lambda-runtime-environment.md#runtimes-lifecycle-ib)에서 정적 코드와 클래스 생성자를 실행합니다. 초기화 중에 생성된 리소스는 간접 호출 간의 메모리에 남아 있으므로 함수를 호출할 때마다 메모리를 생성할 필요가 없습니다.

예제 코드에서 S3 클라이언트 초기화 코드는 기본 핸들러 메서드 외부에 있습니다. 런타임은 함수가 첫 번째 이벤트를 처리하기 전에 클라이언트를 초기화하므로 처리 시간이 길어질 수 있습니다. Lambda가 클라이언트를 다시 초기화할 필요가 없으므로 후속 이벤트는 훨씬 더 빠릅니다.

## Lambda 주석 프레임워크를 사용하여 함수 코드를 간소화합니다
<a name="csharp-handler-annotations"></a>

[Lambda 주석](https://www.nuget.org/packages/Amazon.Lambda.Annotations)은 C\$1을 사용하여 Lambda 함수 작성을 간소화하는 .NET 8용 프레임워크입니다. 주석 프레임워크는 [소스 생성기](https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview)를 사용하여 Lambda 프로그래밍 모델에서 단순화된 코드로 변환되는 코드를 생성합니다. 주석 프레임워크를 사용하면 일반 프로그래밍 모델을 사용하여 작성된 Lambda 함수의 코드 대부분을 대체할 수 있습니다. 프레임워크를 사용하여 작성된 코드는 더 간단한 식을 사용하므로 비즈니스 로직에 집중할 수 있습니다. 예제는 nuget 설명서의 [Amazon.Lambda.Annotations](https://www.nuget.org/packages/Amazon.Lambda.Annotations)를 참조하세요.

Lambda 주석을 사용하는 전체 애플리케이션의 예는 `awsdocs/aws-doc-sdk-examples` GitHub 리포지토리의 [PhotoAssetManager](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/dotnetv3/cross-service/PhotoAssetManager) 예제를 참조하세요. `PamApiAnnotations` 디렉터리의 기본 `Function.cs` 파일은 Lambda 주석을 사용합니다. `PamApi` 디렉터리에는 비교를 위해 일반 Lambda 프로그래밍 모델을 사용하여 작성된 동일한 파일이 있습니다.

### Lambda 주석 프레임워크를 사용한 종속성 주입
<a name="csharp-handler-annotations-injection"></a>

또한 Lambda 주석 프레임워크를 사용하면 익숙한 구문을 활용하여 Lambda 함수에 종속성 주입을 추가할 수 있습니다. `Startup.cs` 파일에 `[LambdaStartup]` 속성을 추가하면 Lambda 주석 프레임워크가 컴파일 타임에 필요한 코드를 생성합니다.

```
[LambdaStartup]
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<IDatabaseRepository, DatabaseRepository>();
    }
}
```

Lambda 함수는 생성자 주입을 사용하여 서비스를 주입하거나 `[FromServices]` 속성을 사용하여 개별 메서드에 주입할 수 있습니다.

```
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace GetProductHandler;

public class Function
{
    private readonly IDatabaseRepository _repo;
    
    public Function(IDatabaseRepository repo)
    {
        this._repo = repo;
    }
    
    [LambdaFunction]
    [HttpApi(LambdaHttpMethod.Get, "/product/{id}")]
    public async Task<Product> FunctionHandler([FromServices] IDatabaseRepository repository, string id)
    {
        return await this._repo.GetById(id);
    }
}
```

## C\$1 Lambda 함수의 코드 모범 사례
<a name="csharp-best-practices"></a>

Lambda 함수를 구축할 때 코딩 모범 사례를 사용하려면 다음 목록의 지침을 준수하세요.
+ **핵심 로직에서 Lambda 핸들러를 분리합니다.** 이를 통해 단위 테스트를 수행할 수 있는 더 많은 함수를 만들 수 있습니다.
+ **함수 배포 패키지의 종속성을 제어합니다.** AWS Lambda 실행 환경에는 여러 라이브러리가 포함되어 있습니다. 최신 기능 및 보안 업데이트를 활성화하려면 Lambda가 주기적으로 이러한 라이브러리를 업데이트해야 합니다. 이러한 업데이트는 Lambda 함수의 동작에 사소한 변화를 가져올 수 있습니다. 함수가 사용하는 종속성을 완전히 제어하려면 모든 종속성을 배포 패키지로 패키징하세요.
+ **종속성의 복잡성을 최소화합니다.** [실행 환경](lambda-runtime-environment.md) 시작 시 빠르게 로드되는 더 단순한 프레임워크가 권장됩니다.
+ **배포 패키지 크기를 런타임 필요에 따라 최소화합니다.** 이렇게 하면 호출 전에 배포 패키지를 다운로드하고 압축을 풀 때 걸리는 시간이 단축됩니다. .NET에서 작성된 함수의 경우, 배포 패키지의 일부로 전체 AWS SDK 라이브러리를 업로드하지 마세요. 대신, 필요한 SDK의 구성 요소를 선택하는 모듈을 선택적으로 활용합니다(예: DynamoDB, Amazon S3 SDK 모듈, Lambda 핵심 라이브러리).

**실행 환경 재사용을 활용하여 함수 성능을 향상시킵니다.** 함수 핸들러 외부에서 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/) 단원을 참조하십시오.

# .zip 파일 아카이브를 사용하여 C\$1 Lambda 함수를 빌드 및 배포
<a name="csharp-package"></a>

.NET 배포 패키지(.zip 파일 아카이브)에는 함수의 컴파일된 어셈블리와 해당 어셈블리의 모든 종속 항목이 함께 포함되어 있습니다. 패키지는 `proj.deps.json` 파일도 포함합니다. 이 패키지는 함수의 모든 종속성과 `proj.runtimeconfig.json` 파일을 .NET 런타임으로 전송하며, 해당 파일은 런타임을 구성하는 데 사용됩니다.

개별 Lambda 함수를 배포하려면.`Amazon.Lambda.Tools` NET Lambda 글로벌 CLI를 사용하면 됩니다. `dotnet lambda deploy-function` 명령을 사용하면.zip 배포 패키지가 자동으로 생성되어 Lambda에 배포됩니다. 하지만 AWS Serverless Application Model(AWS SAM) 또는 AWS Cloud Development Kit (AWS CDK)와(과) 같은 프레임워크를 사용하여 .NET 애플리케이션을 AWS에 배포하는 것이 좋습니다.

서버리스 애플리케이션은 일반적으로 특정 비즈니스 작업을 수행하기 위해 함께 작동하는 Lambda 함수와 기타 관리형 AWS 서비스의 조합으로 구성됩니다. AWS SAM과 AWS CDK는 규모에 따라 다른 AWS 서비스와 함께 Lambda 함수를 빌드하고 배포하는 것을 단순화합니다. [AWS SAM 템플릿 사양](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification.html)에서는 서버리스 애플리케이션을 구성하는 Lambda 함수, API, 권한, 구성 및 기타 AWS 리소스를 설명하는 간단하고 깔끔한 구문을 제공합니다. [AWS CDK](https://docs.aws.amazon.com/cdk/v2/guide/home.html)을(를) 사용하여 클라우드 인프라를 코드로 정의하면 .NET과 같은 최신 프로그래밍 언어와 프레임워크를 활용하여 클라우드에서 신뢰할 수 있고, 확장 가능하며, 비용 대비 효율적인 애플리케이션을 빌드하는 데 도움이 됩니다. AWS CDK 및 AWS SAM은(는) 모두 .NET Lambda 글로벌 CLI를 사용하여 함수를 패키징합니다.

[.NET Core CLI를 사용](csharp-package-cli.md#csharp-layers)하면 C\$1의 함수와 함께 [Lambda 계층](chapter-layers.md)을 사용할 수 있지만 이는 권장되지 않습니다. 계층을 사용하는 C\$1의 함수는 [초기화 단계](lambda-runtime-environment.md#runtimes-lifecycle-ib) 중 공유 어셈블리를 메모리에 수동으로 로드하므로 콜드 시작 시간을 늘릴 수 있습니다. 대신 컴파일 시 모든 공유 코드를 포함하여 런타임 시 어셈블리 로드의 성능 영향을 방지합니다.

AWS SAM, AWS CDK 및 .NET Lambda 글로벌 CLI를 사용하여.NET Lambda 함수를 빌드하고 배포하는 지침은 다음 섹션에서 확인할 수 있습니다.

**Topics**
+ [

# .NET Lambda 글로벌 CLI 사용
](csharp-package-cli.md)
+ [

# AWS SAM을 사용하여 C\$1 Lambda 함수 배포
](csharp-package-sam.md)
+ [

# AWS CDK을 사용하여 C\$1 Lambda 함수 배포
](csharp-package-cdk.md)
+ [

# ASP.NET 애플리케이션 배포
](csharp-package-asp.md)

# .NET Lambda 글로벌 CLI 사용
<a name="csharp-package-cli"></a>

.NET CLI와 .NET Lambda 글로벌 도구 확장(`Amazon.Lambda.Tools`)은.NET 기반 Lambda 애플리케이션을 생성하고, 패키징하고, Lambda에 배포하는 크로스 플랫폼 방법을 제공합니다. 이 섹션에서는.NET CLI 및 Amazon Lambda 템플릿을 사용하여 새 Lambda .NET 프로젝트를 생성하고 `Amazon.Lambda.Tools`을(를) 사용하여 패키징하고 배포하는 방법을 알아봅니다

**Topics**
+ [

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

## .NET CLI를 사용하여 .NET 프로젝트 생성
](#csharp-package-cli-create)
+ [

## .NET CLI를 사용하여 .NET 프로젝트 배포하기
](#csharp-package-cli-deploy)
+ [

## .NET CLI와 함께 Lambda 계층 사용
](#csharp-layers)

## 사전 조건
<a name="csharp-package-cli-prerequisites"></a>

**.NET 8 SDK**  
아직 하지 않았다면 [.NET 8](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) SDK 및 런타임을 설치하세요.

**AWS Amazon.Lambda.Templates .NET프로젝트 템플릿**  
Lambda 함수 코드를 생성하려면 [https://www.nuget.org/packages/Amazon.Lambda.Templates](https://www.nuget.org/packages/Amazon.Lambda.Templates) NuGet 패키지를 사용합니다. 이 템플릿 패키지를 설치하려면 다음 명령을 실행합니다.  

```
dotnet new install Amazon.Lambda.Templates
```

**AWS Amazon.Lambda.Tools .NET 글로벌 CLI 도구**  
Lambda 함수를 생성하려면 [https://www.nuget.org/packages/Amazon.Lambda.Tools](https://www.nuget.org/packages/Amazon.Lambda.Tools) [.NET 글로벌 도구 확장](https://aws.amazon.com/blogs/developer/net-core-global-tools-for-aws/)을 사용합니다. Amazon.Lambda.Tools를 설치하려면 다음 명령을 실행합니다.  

```
dotnet tool install -g Amazon.Lambda.Tools
```
Amazon.Lambda.Tools .NET CLI 확장에 대한 자세한 내용은 GitHub에서 [AWS Extensions for .NET CLI](https://github.com/aws/aws-extensions-for-dotnet-cli) 리포지토리를 참조하세요.

## .NET CLI를 사용하여 .NET 프로젝트 생성
<a name="csharp-package-cli-create"></a>

.NET CLI에서는 `dotnet new` 명령을 사용해 한 명령줄에서 .NET 프로젝트를 생성합니다. Lambda는 [https://www.nuget.org/packages/Amazon.Lambda.Templates](https://www.nuget.org/packages/Amazon.Lambda.Templates) NuGet 패키지를 사용하여 추가 템플릿을 제공합니다.

이 패키지를 설치한 후 다음 명령을 실행하여 사용 가능한 템플릿 목록을 확인합니다.

```
dotnet new list
```

템플릿에 대한 세부 정보를 검토하려면 `help` 옵션을 사용하세요. 예를 들어 `lambda.EmptyFunction` 템플릿에 대한 세부 정보를 확인하려면 다음 명령을 실행합니다.

```
dotnet new lambda.EmptyFunction --help
```

.NET Lambda 함수의 기본 템플릿을 생성하려면 `lambda.EmptyFunction` 템플릿을 사용하십시오. 그러면 문자열을 입력으로 받아 `ToUpper` 메서드를 사용하여 대문자로 변환하는 간단한 함수가 생성됩니다. 이 템플릿은 다음 옵션을 지원합니다.
+ `--name` – 함수의 이름입니다.
+ `--region` - 함수를 생성할 AWS 리전입니다.
+ `--profile` – 사용자의 AWS SDK for .NET 자격 증명에 있는 프로필의 이름입니다. .NET의 보안 인증 프로필에 대한 자세한 내용은 .NET 개발자 안내서용 *AWS SDK*에서 [AWS 보안 인증 구성](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/net-dg-config-creds.html)을 참조하십시오.

이 예제에서는 기본 프로필 및 AWS 리전 설정을 사용하여 `myDotnetFunction`(이)라는 빈 함수를 새로 만듭니다.

```
dotnet new lambda.EmptyFunction --name myDotnetFunction
```

이 명령은 프로젝트 디렉터리에 다음 파일 및 디렉터리를 생성합니다.

```
└── myDotnetFunction
    ├── src
    │   └── myDotnetFunction
    │       ├── Function.cs
    │       ├── Readme.md
    │       ├── aws-lambda-tools-defaults.json
    │       └── myDotnetFunction.csproj
    └── test
        └── myDotnetFunction.Tests
            ├── FunctionTest.cs
            └── myDotnetFunction.Tests.csproj
```

`src/myDotnetFunction` 디렉터리 아래에서 다음과 같은 파일들을 검사합니다.
+ **aws-lambda-tools-defaults.json**: Lambda 함수를 배포할 때 이 파일에 명령줄 옵션을 지정합니다. 예:

  ```
    "profile" : "default",
    "region" : "us-east-2",
    "configuration" : "Release",
    "function-architecture": "x86_64",
    "function-runtime":"dotnet8",
    "function-memory-size" : 256,
    "function-timeout" : 30,
    "function-handler" : "myDotnetFunction::myDotnetFunction.Function::FunctionHandler"
  ```
+ **Function.cs**: Lambda 핸들러 함수 코드입니다. 이 코드는 기본 `Amazon.Lambda.Core` 라이브러리와 기본 `LambdaSerializer` 속성을 포함하는 C\$1 템플릿에 속합니다. 직렬화 요구 사항들과 옵션들에 관한 자세한 내용은 [C\$1 Lambda 함수의 직렬화](csharp-handler.md#csharp-handler-serializer) 단원을 참조하세요. 이 단원은 Lambda 함수 코드를 적용하기 위해 편집할 수 있는 하나의 샘플 함수도 포함하고 있습니다.

  ```
  using Amazon.Lambda.Core;
  
  // Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
  [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
  
  namespace myDotnetFunction;
  
  public class Function
  {
  
      /// <summary>
      /// A simple function that takes a string and does a ToUpper
      /// </summary≫
      /// <param name="input"></param>
      /// <param name="context"></param>
      /// <returns></returns>
      public string FunctionHandler(string input, ILambdaContext context)
      {
          return input.ToUpper();
      }
  }
  ```
+ **myDotnetFunction.csproj**: 애플리케이션을 구성하는 파일 및 어셈블리들의 목록을 열거한 [MSBuild](https://msdn.microsoft.com/en-us/library/dd393574.aspx) 파일입니다.

  ```
  <Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
      <TargetFramework>net8.0</TargetFramework>
      <ImplicitUsings>enable</ImplicitUsings>
      <Nullable>enable</Nullable>
      <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
      <AWSProjectType>Lambda</AWSProjectType>
      <!-- This property makes the build directory similar to a publish directory and helps the AWS .NET Lambda Mock Test Tool find project dependencies. -->
      <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
      <!-- Generate ready to run images during publishing to improve cold start time. -->
      <PublishReadyToRun>true</PublishReadyToRun>
    </PropertyGroup>
    <ItemGroup>
      <PackageReference Include="Amazon.Lambda.Core" Version="2.2.0" />
      <PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" Version="2.4.0" />
    </ItemGroup>
  </Project>
  ```
+ **Readme**: 이 파일을 사용하면 Lambda 함수를 문서화할 수 있습니다.

`myfunction/test` 디렉터리 아래에서 다음과 같은 파일들을 검사합니다.
+ **myDotnetFunction.Tests.csproj**: 앞서 언급한 것처럼 이것은 테스트 프로젝트를 구성하는 여러 파일 및 어셈블리를 열거한 [MSBuild](https://msdn.microsoft.com/en-us/library/dd393574.aspx) 파일입니다. 이 파일은 `Amazon.Lambda.Core` 라이브러리도 포함하고 있기 때문에 함수를 테스트하는 데 필요한 Lambda 템플릿을 원활하게 통합할 수 있습니다.

  ```
  <Project Sdk="Microsoft.NET.Sdk">
     ... 
  
      <PackageReference Include="Amazon.Lambda.Core" Version="2.2.0 " />
     ...
  ```
+ **FunctionTest.cs**: `src` 디렉터리에 포함된 것과 똑같은 C\$1 코드 템플릿 파일입니다. Lambda 함수를 프로덕션 환경에 업로드하기 전에 함수의 프로덕션 코드를 미러링하고 테스트할 수 있도록 이 파일을 편집합니다.

  ```
  using Xunit;
  using Amazon.Lambda.Core;
  using Amazon.Lambda.TestUtilities;
  
  using MyFunction;
  
  namespace MyFunction.Tests
  {
      public class FunctionTest
      {
          [Fact]
          public void TestToUpperFunction()
          {
  
              // Invoke the lambda function and confirm the string was upper cased.
              var function = new Function();
              var context = new TestLambdaContext();
              var upperCase = function.FunctionHandler("hello world", context);
  
              Assert.Equal("HELLO WORLD", upperCase);
          }
      }
  }
  ```

## .NET CLI를 사용하여 .NET 프로젝트 배포하기
<a name="csharp-package-cli-deploy"></a>

배포 패키지를 빌드하고 Lambda에 배포하려면 `Amazon.Lambda.Tools` CLI 도구를 사용합니다. 이전 단계에서 생성한 파일로 함수를 배포하려면 먼저 함수의 `.csproj` 파일이 포함된 폴더로 이동하십시오.

```
cd myDotnetFunction/src/myDotnetFunction
```

코드를 Lambda에.zip 배포 패키지로 배포하려면 다음 명령을 실행합니다. 자체 함수 이름을 선택하십시오.

```
dotnet lambda deploy-function myDotnetFunction
```

배포 중에 마법사는 [실행 역할로 Lambda 함수 권한 정의](lambda-intro-execution-role.md)을 선택하라고 요청합니다. 이 예제에서는 `lambda_basic_role`을(를) 선택합니다.

함수를 배포한 후 `dotnet lambda invoke-function` 명령을 사용하여 클라우드에서 테스트할 수 있습니다. `lambda.EmptyFunction` 템플릿에 있는 예제 코드의 경우 `--payload` 옵션을 사용하여 문자열을 전달하여 함수를 테스트할 수 있습니다.

```
dotnet lambda invoke-function myDotnetFunction --payload "Just checking if everything is OK"
```

함수가 성공적으로 배포된 경우 다음과 유사한 출력이 표시될 것입니다.

```
dotnet lambda invoke-function myDotnetFunction --payload "Just checking if everything is OK"
Amazon Lambda Tools for .NET Core applications (5.8.0)
Project Home: https://github.com/aws/aws-extensions-for-dotnet-cli, https://github.com/aws/aws-lambda-dotnet

Payload:
"JUST CHECKING IF EVERYTHING IS OK"

Log Tail:
START RequestId: id Version: $LATEST
END RequestId: id
REPORT RequestId: id  Duration: 0.99 ms       Billed Duration: 1 ms         Memory Size: 256 MB     Max Memory Used: 12 MB
```

## .NET CLI와 함께 Lambda 계층 사용
<a name="csharp-layers"></a>

**참고**  
.NET의 함수와 함께 [계층](chapter-layers.md)을 사용할 수 있지만 이는 권장되지 않습니다. 계층을 사용하는 .NET의 함수는 `Init` 단계 중 공유 어셈블리를 메모리에 수동으로 로드하므로 콜드 시작 시간을 늘릴 수 있습니다. 대신 컴파일 시간에 모든 공유 코드를 포함하여 .NET 컴파일러의 기본 제공 최적화를 활용하세요.

.NET CLI는 계층 게시 및 계층을 사용하는 C\$1 함수 배포에 도움이 되는 명령을 지원합니다. 지정된 Amazon S3 버킷에 계층을 게시하려면 .`.csproj` 파일과 동일한 디렉터리에서 다음 명령을 실행합니다.

```
dotnet lambda publish-layer <layer_name> --layer-type runtime-package-store --s3-bucket <s3_bucket_name>
```

그런 다음 .NET CLI를 사용하여 함수를 배포할 때 다음 명령에서 사용할 계층 ARN을 지정합니다.

```
dotnet lambda deploy-function <function_name> --function-layers arn:aws:lambda:us-east-1:123456789012:layer:layer-name:1
```

Hello World 함수의 전체 예제는 [blank-csharp-with-layer](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/blank-csharp-with-layer) 샘플을 참조하세요.

# AWS SAM을 사용하여 C\$1 Lambda 함수 배포
<a name="csharp-package-sam"></a>

AWS Serverless Application Model(AWS SAM)은 AWS에서 서버리스 애플리케이션을 빌드하고 실행하는 프로세스를 간소화하는 데 도움이 되는 도구 키트입니다. YAML 또는 JSON 템플릿에서 애플리케이션의 리소스를 정의하고 AWS SAM Command Line Interface(AWS SAM CLI)를 사용하여 애플리케이션을 빌드, 패키징 및 배포합니다. AWS SAM 템플릿에서 Lambda 함수를 빌드하면 AWS SAM은(는) 함수 코드와 사용자가 지정하는 종속 항목을 사용하여 .zip 배포 패키지 또는 컨테이너 이미지를 자동으로 생성합니다. AWS SAM은(는) [CloudFormation 스택](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacks.html)을 사용하여 함수를 배포합니다. AWS SAM을 사용하여 Lambda 함수를 빌드하고 배포하는 방법에 대해 자세히 알아보려면 **AWS Serverless Application Model 개발자 안내서의 [Getting started with AWS SAM](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started.html)을 참조하세요.

다음 단계에서 AWS SAM을(를) 사용하여 샘플 .NET Hello World 애플리케이션을 다운로드, 빌드 및 배포하는 방법을 보여줍니다. 이 샘플 애플리케이션은 Lambda 함수와 Amazon API Gateway 엔드포인트를 사용하여 기본 API 백엔드를 구현합니다. API Gateway 엔드포인트에 HTTP GET 요청을 보내면 API Gateway가 Lambda 함수를 간접 호출합니다. 함수는 요청을 처리하는 Lambda 함수 인스턴스의 IP 주소와 함께 “hello world” 메시지를 반환합니다.

AWS SAM을(를) 사용하여 애플리케이션을 빌드하고 배포하면 AWS SAM CLI는 백그라운드에서 `dotnet lambda package` 명령을 사용하여 개별 Lambda 함수 코드 번들을 패키징합니다.

## 사전 조건
<a name="csharp-package-sam-prerequisites"></a>

**.NET 8 SDK**  
[.NET 8](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) SDK 및 런타임을 설치합니다.

**AWS SAM CLI 버전 1.39 이상**  
AWS SAM CLI의 최신 버전을 설치하는 방법에 대해 알아보려면 [AWS SAM CLI 설치](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html)를 확인하십시오.

## 샘플 AWS SAM 애플리케이션 배포
<a name="csharp-package-sam-deploy"></a>

1. 다음 명령을 활용하는 Hello world .NET 템플릿을 사용하여 애플리케이션을 초기화합니다.

   ```
   sam init --app-template hello-world --name sam-app \
   --package-type Zip --runtime dotnet8
   ```

   이 명령은 프로젝트 디렉터리에 다음 파일 및 디렉터리를 생성합니다.

   ```
   └── sam-app
       ├── README.md
       ├── events
       │   └── event.json
       ├── omnisharp.json
       ├── samconfig.toml
       ├── src
       │   └── HelloWorld
       │       ├── Function.cs
       │       ├── HelloWorld.csproj
       │       └── aws-lambda-tools-defaults.json
       ├── template.yaml
       └── test
           └── HelloWorld.Test
               ├── FunctionTest.cs
               └── HelloWorld.Tests.csproj
   ```

1. `template.yaml file`이(가) 포함된 디렉토리로 이동합니다. 이 파일은 Lambda 함수 및 API Gateway API를 포함하여 애플리케이션의 AWS 리소스를 정의하는 템플릿입니다.

   ```
   cd sam-app
   ```

1. 애플리케이션의 소스를 빌드하려면 다음 명령을 실행합니다.

   ```
   sam build
   ```

1. AWS에 애플리케이션을 배포하려면 다음 명령을 실행합니다.

   ```
   sam deploy --guided
   ```

   이 명령은 다음과 같은 일련의 프롬프트와 함께 애플리케이션을 패키징하고 배포합니다. 기본 옵션을 그대로 사용하려면 입력 키를 누릅니다.
**참고**  
**HelloWorldFunction에 권한 부여가 정의되어 있지 않을 수도 있습니다. 괜찮습니까?**에 대해 `y`을(를) 입력합니다.
   + **스택 이름**: CloudFormation에 배포할 스택의 이름입니다. 이 이름은 AWS 계정 및 AWS 리전에 고유한 것이어야 합니다.
   + **AWS 리전**: 앱을 배포하려는 AWS 리전입니다.
   + **배포 전 변경 사항 확인**: AWS SAM이(가) 애플리케이션 변경 사항을 배포하기 전에 변경 세트를 수동으로 검토하려면 예를 선택합니다. 아니요를 선택하면 AWS SAM CLI가 애플리케이션 변경 사항을 자동으로 배포합니다.
   + **SAM CLI IAM 역할 생성 허용**: 이 예제의 Hello world 템플릿을 비롯한 많은 AWS SAM 템플릿은 AWS Identity and Access Management (IAM) 역할을 생성하여 Lambda 함수를 다른 AWS 서비스에 액세스할 수 있는 권한을 부여합니다. IAM 역할을 생성하거나 수정하는 CloudFormation 스택을 배포할 권한을 제공하려면 예를 선택합니다.
   + **롤백 비활성화**: 기본적으로 AWS SAM이(가) 스택을 생성하거나 배포하는 동안 오류가 발생하면 스택을 이전 버전으로 롤백합니다. 이 기본값을 허용하려면 아니요를 선택합니다.
   + **HelloWorldFunction에 권한 부여가 정의되어 있지 않을 수 있습니다. 괜찮습니까**: `y`을(를) 입력합니다.
   + **samconfig.toml에 인수 저장**: 구성 선택 사항을 저장하려면 예를 선택합니다. 앞으로는 파라미터 `sam deploy` 없이 다시 실행하여 변경 내용을 애플리케이션에 배포할 수 있습니다.

1. 애플리케이션 배포가 완료되면 CLI는 Hello World Lambda 함수의 Amazon 리소스 이름(ARN)과 이 함수에 대해 생성된 IAM 역할을 반환합니다. 또한 API Gateway API의 엔드포인트가 표시됩니다. 애플리케이션을 테스트하려면 브라우저에서 엔드포인트를 엽니다. 다음과 유사한 응답이 나타납니다.

   ```
   {"message":"hello world","location":"34.244.135.203"}
   ```

1. 다음 명령을 실행하여 리소스를 삭제합니다. 참고로 생성한 API 엔드포인트는 인터넷을 통해 액세스할 수 있는 퍼블릭 엔드포인트입니다. 테스트 후에는 이 엔드포인트를 삭제하는 것이 좋습니다.

   ```
   sam delete
   ```

## 다음 단계
<a name="csharp-package-sam-next"></a>

.NET을 사용하여 Lambda 함수를 빌드하고 배포하기 위해 AWS SAM을(를) 사용하는 방법에 대해 자세히 알아보려면 다음 리소스를 참조하십시오.
+ [https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html)가이드
+ AWS Lambda 및 [SAM CLI를 사용하여 서버리스 .NET 애플리케이션 빌드하기](https://aws.amazon.com/blogs/dotnet/building-serverless-net-applications-with-aws-lambda-and-the-sam-cli/)

# AWS CDK을 사용하여 C\$1 Lambda 함수 배포
<a name="csharp-package-cdk"></a>

AWS Cloud Development Kit (AWS CDK)은(는) .NET과 같은 최신 프로그래밍 언어 및 프레임워크를 사용하여 클라우드 인프라를 코드로 정의하는 오픈 소스 소프트웨어 개발 프레임워크입니다. AWS CDK프로젝트를 실행하여 CloudFormation 템플릿을 생성한 다음 이를 사용하여 코드를 배포합니다.

AWS CDK을(를) 사용하여 예제 Hello world .NET 애플리케이션을 빌드하고 배포하려면 다음 섹션의 지침을 따르십시오. 샘플 애플리케이션은 API Gateway 엔드포인트와 Lambda 함수로 구성된 기본 API 백엔드를 구현합니다. 엔드포인트에 HTTP GET 요청을 보내면 API Gateway는 Lambda 함수를 간접 호출합니다. 함수는 요청을 처리하는 Lambda 인스턴스의 IP 주소와 함께 Hello world 메시지를 반환합니다.

## 사전 조건
<a name="csharp-package-cdk-prereqs"></a>

**.NET 8 SDK**  
[.NET 8](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) SDK 및 런타임을 설치합니다.

**AWS CDK 버전 2**  
AWS CDK의 최신 버전을 설치하는 방법을 알아보려면 *AWS Cloud Development Kit (AWS CDK) v2 개발자 안내서*의 [AWS CDK(으)로 시작하기](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html)를 확인하십시오.

## 샘플 AWS CDK 애플리케이션 배포
<a name="csharp-package-cdk-deploy"></a>

1. 샘플 애플리케이션을 위한 프로젝트 디렉터리를 생성하고 탐색합니다.

   ```
   mkdir hello-world
   cd hello-world
   ```

1. 다음 명령을 실행하여 새 AWS CDK 애플리케이션을 초기화합니다.

   ```
   cdk init app --language csharp
   ```

   이 명령은 프로젝트 디렉터리에 다음과 같은 파일 및 디렉터리를 생성합니다

   ```
   ├── README.md
   ├── cdk.json
   └── src
       ├── HelloWorld
       │   ├── GlobalSuppressions.cs
       │   ├── HelloWorld.csproj
       │   ├── HelloWorldStack.cs
       │   └── Program.cs
       └── HelloWorld.sln
   ```

1. `src` 디렉터리를 열고 .NET CLI를 사용하여 새 Lambda 함수를 생성합니다. AWS CDK을(를) 사용하여 배포할 함수입니다. 이 예제에서는 `lambda.EmptyFunction` 템플릿을 사용하여 `HelloWorldLambda`(이)라는 Hello world 함수를 생성합니다.

   ```
   cd src
   dotnet new lambda.EmptyFunction -n HelloWorldLambda
   ```

   이 단계 후에 프로젝트 디렉터리 내부의 디렉터리 구조는 다음과 같아야 합니다.

   ```
   ├── README.md
   ├── cdk.json
   └── src
       ├── HelloWorld
       │   ├── GlobalSuppressions.cs
       │   ├── HelloWorld.csproj
       │   ├── HelloWorldStack.cs
       │   └── Program.cs
       ├── HelloWorld.sln
       └── HelloWorldLambda
           ├── src
           │   └── HelloWorldLambda
           │       ├── Function.cs
           │       ├── HelloWorldLambda.csproj
           │       ├── Readme.md
           │       └── aws-lambda-tools-defaults.json
           └── test
               └── HelloWorldLambda.Tests
                   ├── FunctionTest.cs
                   └── HelloWorldLambda.Tests.csproj
   ```

1. `src/HelloWorld` 디렉터리에서 `HelloWorldStack.cs` 파일을 엽니다. 파일의 내용을 다음 코드로 바꿉니다.

   ```
   using Amazon.CDK;
   using Amazon.CDK.AWS.Lambda;
   using Amazon.CDK.AWS.Logs;
   using Constructs;
   
   namespace CdkTest
   {
       public class HelloWorldStack : Stack
       {
           internal HelloWorldStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
           {
               var buildOption = new BundlingOptions()
               {
                   Image = Runtime.DOTNET_8.BundlingImage,
                   User = "root",
                   OutputType = BundlingOutput.ARCHIVED,
                   Command = new string[]{
               "/bin/sh",
                   "-c",
                   " dotnet tool install -g Amazon.Lambda.Tools"+
                   " && dotnet build"+
                   " && dotnet lambda package --output-package /asset-output/function.zip"
                   }
               };
   
                var helloWorldLambdaFunction = new Function(this, "HelloWorldFunction", new FunctionProps
               {
                   Runtime = Runtime.DOTNET_8,
                   MemorySize = 1024,
                   LogRetention = RetentionDays.ONE_DAY,
                   Handler = "HelloWorldLambda::HelloWorldLambda.Function::FunctionHandler",
                   Code = Code.FromAsset("./src/HelloWorldLambda/src/HelloWorldLambda", new Amazon.CDK.AWS.S3.Assets.AssetOptions
                   {
                       Bundling = buildOption
                   }),
               });
           }
       }
   }
   ```

   Lambda 함수 자체의 정의뿐만 아니라 애플리케이션 코드를 컴파일하고 번들링하는 코드입니다. `BundlingOptions` 객체를 사용하면 zip 파일의 콘텐츠를 생성하는 데 사용되는 명령 집합과 함께 zip 파일을 생성할 수 있습니다. 이 경우 `dotnet lambda package` 명령은 zip 파일을 컴파일하고 생성하는 데 사용됩니다.

1. 애플리케이션을 배포하려면 다음 명령을 입력합니다.

   ```
   cdk deploy
   ```

1. .NET Lambda CLI를 사용하여 배포된 Lambda 함수를 간접 호출하십시오.

   ```
   dotnet lambda invoke-function HelloWorldFunction -p "hello world"
   ```

1. 테스트를 마친 후 생성한 리소스를 보관하고 싶지 않다면 삭제해도 됩니다. 다음 명령을 실행하여 리소스를 삭제합니다.

   ```
   cdk destroy
   ```

## 다음 단계
<a name="csharp-package-cdk-next"></a>

.NET을 사용하여 Lambda 함수를 빌드하고 배포하기 위해 AWS CDK을(를) 사용하는 방법에 대해 자세히 알아보려면 다음 리소스를 참조하십시오.
+ [C\$1에서 AWS CDK 작업](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-csharp.html)
+ [AWS CDK를 사용하여.NET C\$1 Lambda 함수를 빌드, 패키징 및 게시합니다](https://aws.amazon.com/blogs/modernizing-with-aws/build-package-publish-dotnet-csharp-lambda-functions-aws-cdk/)

# ASP.NET 애플리케이션 배포
<a name="csharp-package-asp"></a>

이벤트 기반 함수를 호스팅할 뿐만 아니라 Lambda와 함께.NET을 사용하여 가벼운 ASP.NET 애플리케이션을 호스팅할 수도 있습니다. `Amazon.Lambda.AspNetCoreServer` NuGet 패키지를 사용하여 ASP.NET 애플리케이션을 빌드하고 배포할 수 있습니다. 이 섹션에서는.NET Lambda CLI 도구를 사용하여 Lambda에 ASP.NET 웹 API를 배포하는 방법을 알아봅니다.

**Topics**
+ [

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

## Lambda에 ASP.NET 웹 API 배포하기
](#csharp-package-asp-deploy-api)
+ [

## Lambda에 ASP.NET 최소 API 배포하기
](#csharp-package-asp-deploy-minimal)

## 사전 조건
<a name="csharp-package-asp-prerequisites"></a>

**.NET 8 SDK**  
[.NET 8](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) SDK 및 ASP.NET Core 런타임을 설치합니다.

**Amazon.Lambda.Tools**  
Lambda 함수를 생성하려면 [https://www.nuget.org/packages/Amazon.Lambda.Tools](https://www.nuget.org/packages/Amazon.Lambda.Tools) [.NET 글로벌 도구 확장](https://aws.amazon.com/blogs/developer/net-core-global-tools-for-aws/)을 사용합니다. Amazon.Lambda.Tools를 설치하려면 다음 명령을 실행합니다.  

```
dotnet tool install -g Amazon.Lambda.Tools
```
Amazon.Lambda.Tools .NET CLI 확장에 대한 자세한 내용은 GitHub에서 [AWS Extensions for .NET CLI](https://github.com/aws/aws-extensions-for-dotnet-cli) 리포지토리를 참조하세요.

**Amazon.Lambda.Templates**  
Lambda 함수 코드를 생성하려면 [https://www.nuget.org/packages/Amazon.Lambda.Templates](https://www.nuget.org/packages/Amazon.Lambda.Templates) NuGet 패키지를 사용합니다. 이 템플릿 패키지를 설치하려면 다음 명령을 실행합니다.  

```
dotnet new --install Amazon.Lambda.Templates
```

## Lambda에 ASP.NET 웹 API 배포하기
<a name="csharp-package-asp-deploy-api"></a>

ASP.NET을 사용하여 웹 API를 배포하기 위해.NET Lambda 템플릿을 사용하여 새 웹 API 프로젝트를 생성할 수 있습니다. 다음 명령을 사용하여 새 ASP.NET 웹 API 프로젝트를 초기화합니다. 예제 명령에서는 프로젝트 `AspNetOnLambda`의 이름을 지정합니다.

```
dotnet new serverless.AspNetCoreWebAPI -n AspNetOnLambda
```

이 명령은 프로젝트 디렉터리에 다음 파일 및 디렉터리를 생성합니다.

```
.
└── AspNetOnLambda
    ├── src
    │   └── AspNetOnLambda
    │       ├── AspNetOnLambda.csproj
    │       ├── Controllers
    │       │   └── ValuesController.cs
    │       ├── LambdaEntryPoint.cs
    │       ├── LocalEntryPoint.cs
    │       ├── Readme.md
    │       ├── Startup.cs
    │       ├── appsettings.Development.json
    │       ├── appsettings.json
    │       ├── aws-lambda-tools-defaults.json
    │       └── serverless.template
    └── test
        └── AspNetOnLambda.Tests
            ├── AspNetOnLambda.Tests.csproj
            ├── SampleRequests
            │   └── ValuesController-Get.json
            ├── ValuesControllerTests.cs
            └── appsettings.json
```

Lambda가 함수를 간접 호출할 때 사용하는 진입점 `LambdaEntryPoint.cs` 파일입니다. .NET Lambda 템플릿으로 생성된 파일에는 다음 코드가 포함되어 있습니다.

```
namespace AspNetOnLambda;

public class LambdaEntryPoint : Amazon.Lambda.AspNetCoreServer.APIGatewayProxyFunction
{
    protected override void Init(IWebHostBuilder builder)
    {
        builder
            .UseStartup≪Startup≫();
    }

    protected override void Init(IHostBuilder builder)
    {
    }
}
```

Lambda에서 사용하는 진입점은 `Amazon.Lambda.AspNetCoreServer` 패키지의 세 가지 기본 클래스 중 하나를 상속해야 합니다. 이 세 가지 기본 클래스는 다음과 같습니다.
+ `APIGatewayProxyFunction`
+ `APIGatewayHttpApiV2ProxyFunction`
+ `ApplicationLoadBalancerFunction`

제공된.NET Lambda 템플릿을 사용하여 `LambdaEntryPoint.cs` 파일을 생성할 때 사용되는 기본 클래스는 `APIGatewayProxyFunction`입니다. 함수에서 사용하는 기본 클래스는 Lambda 함수 앞에 있는 API 계층에 따라 달라집니다.

세 기본 클래스 각각에는 `FunctionHandlerAsync`(이)라는 퍼블릭 메서드가 포함되어 있습니다. 이 메서드의 이름은 Lambda가 함수를 간접 호출하는 데 사용하는 [핸들러 문자열](csharp-handler.md#csharp-class-library-handlers)에 속합니다. 이 `FunctionHandlerAsync` 메서드는 인바운드 이벤트 페이로드를 올바른 ASP.NET 형식으로 변환하고 ASP.NET 응답을 Lambda 응답 페이로드로 다시 변환합니다. 표시된 예제 `AspNetOnLambda` 프로젝트의 경우 핸들러 문자열은 다음과 같습니다.

```
AspNetOnLambda::AspNetOnLambda.LambdaEntryPoint::FunctionHandlerAsync
```

Lambda에 API를 배포하려면 다음 명령을 실행하여 소스 코드 파일이 포함된 디렉토리로 이동하고 CloudFormation을(를) 사용하여 함수를 배포하십시오.

```
cd AspNetOnLambda/src/AspNetOnLambda
dotnet lambda deploy-serverless
```

**작은 정보**  
`dotnet lambda deploy-serverless` 명령을 사용하여 API를 배포하는 경우 CloudFormation에서는 배포 중에 지정한 스택 이름을 기반으로 Lambda 함수에 이름을 지정합니다. Lambda 함수에 사용자 지정 이름을 지정하려면 `serverless.template` 파일을 편집하여 `AWS::Serverless::Function` 리소스에 `FunctionName` 속성을 추가하십시오. 자세한 내용은 *CloudFormation 사용 설명서*에서 [이름 유형](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html)을 참조하세요.

## Lambda에 ASP.NET 최소 API 배포하기
<a name="csharp-package-asp-deploy-minimal"></a>

Lambda에 ASP.NET 최소 API를 배포하려면.NET Lambda 템플릿을 사용하여 새로운 최소 API 프로젝트를 생성하시면 됩니다. 다음 명령을 사용하여 새 최소 API 프로젝트를 초기화합니다. 이 예제에서는 프로젝트 `MinimalApiOnLambda`의 이름을 지정합니다.

```
dotnet new serverless.AspNetCoreMinimalAPI -n MinimalApiOnLambda
```

이 명령은 프로젝트 디렉터리에서 다음 파일 및 디렉터리를 생성합니다.

```
└── MinimalApiOnLambda
    └── src
        └── MinimalApiOnLambda
            ├── Controllers
            │   └── CalculatorController.cs
            ├── MinimalApiOnLambda.csproj
            ├── Program.cs
            ├── Readme.md
            ├── appsettings.Development.json
            ├── appsettings.json
            ├── aws-lambda-tools-defaults.json
            └── serverless.template
```

`Program.cs` 파일에는 다음 코드가 포함되어 있습니다.

```
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();

// Add AWS Lambda support. When application is run in Lambda Kestrel is swapped out as the web server with Amazon.Lambda.AspNetCoreServer. This
// package will act as the webserver translating request and responses between the Lambda event source and ASP.NET Core.
builder.Services.AddAWSLambdaHosting(LambdaEventSource.RestApi);

var app = builder.Build();


app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.MapGet("/", () => "Welcome to running ASP.NET Core Minimal API on AWS Lambda");

app.Run();
```

Lambda에서 실행하도록 최소 API를 구성하려면 Lambda와 ASP.NET Core 간의 요청 및 응답이 제대로 변환되도록 이 코드를 편집해야 할 수 있습니다. 기본적으로 함수는 REST API 이벤트 소스에 맞게 구성됩니다. HTTP API 또는 Application Load Balancer의 경우 다음 옵션 중 하나를 사용하여 `(LambdaEventSource.RestApi)`을(를) 대체합니다.
+ `(LambdaEventSource.HttpAPi)`
+ `(LambdaEventSource.ApplicationLoadBalancer)`

Lambda에 최소 API를 배포하려면 다음 명령을 실행하여 소스 코드 파일이 포함된 디렉토리로 이동하고 CloudFormation을(를) 사용하여 함수를 배포하십시오.

```
cd MinimalApiOnLambda/src/MinimalApiOnLambda
dotnet lambda deploy-serverless
```

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

.NET로 작성된 Lambda 함수의 종속성을 관리하는 데는 [계층](chapter-layers.md)을 사용하지 않는 것이 좋습니다. .NET이 컴파일된 언어이고 함수가 [Init](lambda-runtime-environment.md#runtimes-lifecycle-ib) 단계에서 수동으로 공유 어셈블리를 메모리로 로드해야 하기 때문입니다. 따라서 콜드 시간 시간이 늘어날 수 있습니다. 계층을 사용하면 배포 프로세스가 복잡해질 뿐만 아니라 기본 제공 컴파일러 최적화를 활용할 수 없습니다.

.NET 핸들러와 함께 외부 종속성을 사용하려면 컴파일 시기에 배포 패키지에 외부 종속성을 직접 포함하세요. 이렇게 하면 배포 프로세스를 간소화하고 내장된 .NET 컴파일러 최적화를 활용할 수 있습니다. 함수에서 NuGet 패키지와 같은 종속 항목을 가져와서 사용하는 방법에 대한 예제는 섹션을 참조하세요.

# 컨테이너 이미지를 사용하여 .NET Lambda 함수 배포
<a name="csharp-image"></a>

.NET Lambda 함수의 컨테이너 이미지를 빌드하는 세 가지 방법이 있습니다.
+ [.NET용 AWS 기본 이미지 사용](#csharp-image-instructions)

  [AWS 기본 이미지](images-create.md#runtimes-images-lp)에는 언어 런타임, Lambda와 함수 코드 간의 상호 작용을 관리하는 런타임 인터페이스 클라이언트 및 로컬 테스트를 위한 런타임 인터페이스 에뮬레이터가 미리 로드되어 있습니다.
+ [AWS OS 전용 기본 이미지 사용](images-create.md#runtimes-images-provided)

  [AWS OS 전용 기본 이미지](https://gallery.ecr.aws/lambda/provided)는 Amazon Linux 배포판 및 [런타임 인터페이스 에뮬레이터](https://github.com/aws/aws-lambda-runtime-interface-emulator/)를 포함합니다. 이러한 이미지는 일반적으로 [Go](go-image.md#go-image-provided) 및 [Rust](lambda-rust.md)와 같은 컴파일된 언어의 컨테이너 이미지와 Lambda가 기본 이미지를 제공하지 않는 언어 또는 언어 버전(예: Node.js 19)의 컨테이너 이미지를 생성하는 데 사용됩니다. OS 전용 기본 이미지를 사용하여 [사용자 지정 런타임](runtimes-custom.md)을 구현할 수도 있습니다. 이미지가 Lambda와 호환되도록 하려면 [.NET용 런타임 인터페이스 클라이언트](#csharp-image-clients)를 이미지에 포함해야 합니다.
+ [비AWS 기본 이미지 사용](#csharp-image-clients)

  Alpine Linux, Debian 등의 다른 컨테이너 레지스트리의 대체 기본 이미지를 사용할 수 있습니다. 조직에서 생성한 사용자 지정 이미지를 사용할 수도 있습니다. 이미지가 Lambda와 호환되도록 하려면 [.NET용 런타임 인터페이스 클라이언트](#csharp-image-clients)를 이미지에 포함해야 합니다.

**작은 정보**  
Lambda 컨테이너 함수가 활성 상태가 되는 데 걸리는 시간을 줄이려면 Docker 설명서의 [다단계 빌드 사용](https://docs.docker.com/build/building/multi-stage/)을 참조하세요. 효율적인 컨테이너 이미지를 빌드하려면 [Dockerfile 작성 모범 사례](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/)를 따르세요.

이 페이지에서는 Lambda용 컨테이너 이미지를 빌드, 테스트 및 배포하는 방법을 설명합니다.

**Topics**
+ [

## .NET용 AWS 기본 이미지
](#csharp-image-base)
+ [

## .NET용 AWS 기본 이미지 사용
](#csharp-image-instructions)
+ [

## 런타임 인터페이스 클라이언트에서 대체 기본 이미지 사용
](#csharp-image-clients)

## .NET용 AWS 기본 이미지
<a name="csharp-image-base"></a>

AWS는 .NET에 대한 다음과 같은 기본 이미지를 제공합니다.


| 태그 | 런타임 | 운영 체제 | Dockerfile | 사용 중단 | 
| --- | --- | --- | --- | --- | 
| 10 | .NET 10 | Amazon Linux 2023 | [GitHub의 .NET 10용 Dockerfile](https://github.com/aws/aws-lambda-base-images/blob/dotnet10/Dockerfile.dotnet10) |   2028년 11월 14일   | 
| 9 | .NET 9 | Amazon Linux 2023 | [GitHub의 .NET 9용 Dockerfile](https://github.com/aws/aws-lambda-base-images/blob/dotnet9/Dockerfile.dotnet9) |   2026년 11월 10일   | 
| 8 | .NET 8 | Amazon Linux 2023 | [GitHub의 .NET 8용 Dockerfile](https://github.com/aws/aws-lambda-base-images/blob/dotnet8/Dockerfile.dotnet8) |   2026년 11월 10일   | 

Amazon ECR 리포지토리: [gallery.ecr.aws/lambda/dotnet](https://gallery.ecr.aws/lambda/dotnet)

## .NET용 AWS 기본 이미지 사용
<a name="csharp-image-instructions"></a>

### 사전 조건
<a name="dotnet-csharp-image-prerequisites"></a>

이 섹션의 단계를 완료하려면 다음이 필요합니다.
+ [.NET SDK](https://dotnet.microsoft.com/download) - 다음 단계에서는 .NET 8 기본 이미지를 사용합니다. .NET 버전이 Dockerfile에 지정한 [기본 이미지](https://gallery.ecr.aws/lambda/dotnet)의 버전과 일치하는지 확인하세요.
+ [Docker](https://docs.docker.com/get-docker)(최소 버전 25.0.0)
+ Docker [buildx 플러그인](https://github.com/docker/buildx/blob/master/README.md)

### 기본 이미지를 사용하여 이미지 생성 및 배포
<a name="dotnet-image-create"></a>

다음 단계에서는 [Amazon.Lambda.Templates](https://github.com/aws/aws-lambda-dotnet#dotnet-cli-templates)와 [Amazon.Lambda.Tools](https://github.com/aws/aws-extensions-for-dotnet-cli#aws-lambda-amazonlambdatools)를 사용하여 .NET 프로젝트를 생성합니다. 그런 다음 도커 이미지를 빌드하고 Amazon ECR에 업로드하고 Lambda 함수에 배포합니다.

1. [Amazon.Lambda.Templates](https://github.com/aws/aws-lambda-dotnet#dotnet-cli-templates) NuGet 패키지를 설치합니다.

   ```
   dotnet new install Amazon.Lambda.Templates
   ```

1. `lambda.image.EmptyFunction` 템플릿을 사용하여.NET 프로젝트를 생성합니다.

   ```
   dotnet new lambda.image.EmptyFunction --name MyFunction --region us-east-1
   ```

   프로젝트 파일은 `MyFunction/src/MyFunction` 디렉터리에 저장됩니다.
   + **aws-lambda-tools-defaults.json**: Lambda 함수 배포를 위한 명령줄 옵션을 지정합니다.
   + **Function.cs**: Lambda 핸들러 함수 코드입니다. 기본 `Amazon.Lambda.Core` 라이브러리와 기본 `LambdaSerializer` 속성을 포함하는 C\$1 템플릿입니다. 직렬화 요구 사항들과 옵션에 대한 자세한 내용은 [C\$1 Lambda 함수의 직렬화](csharp-handler.md#csharp-handler-serializer) 섹션을 참조하세요. 제공된 코드를 테스트에 사용하거나 사용자 고유의 코드로 바꿀 수 있습니다.
   + **MyFunction.csproj**: 애플리케이션을 구성하는 파일과 어셈블리가 나열된 .NET [프로젝트 파일](https://learn.microsoft.com/en-us/dotnet/core/project-sdk/overview#project-files)입니다.
   + **Dockerfile**: 제공된 Dockerfile을 테스트에 사용하거나 사용자 고유의 Dockerfile로 바꿀 수 있습니다. 사용자 고유의 Dockerfile을 사용하는 경우 다음 사항을 확인하세요.
     + `FROM` 속성을 [기본 이미지의 URI](https://gallery.ecr.aws/lambda/dotnet)로 설정합니다. `MyFunction.csproj` 파일의 기본 이미지와 `TargetFramework`는 모두 동일한 .NET 버전을 사용해야 합니다. 예를 들어 .NET 9을 사용하려면 다음을 수행하세요.
       + Dockerfile: `FROM public.ecr.aws/lambda/dotnet:9`
       + MyFunction.csproj: `<TargetFramework>net9.0</TargetFramework>`
     + `CMD` 인수를 Lambda 함수 핸들러로 설정합니다. `aws-lambda-tools-defaults.json`의 `image-command`와 일치해야 합니다.

1. Amazon.Lambda.Tools [.NET 글로벌 도구](https://aws.amazon.com/blogs/developer/net-core-global-tools-for-aws/)를 설치합니다.

   ```
   dotnet tool install -g Amazon.Lambda.Tools
   ```

   Amazon.Lambda.Tools가 이미 설치되어 있는 경우 최신 버전이 설치되어 있는지 확인합니다.

   ```
   dotnet tool update -g Amazon.Lambda.Tools
   ```

1. 아직 이동하지 않은 경우 디렉터리를 `MyFunction/src/MyFunction`으로 변경합니다.

   ```
   cd src/MyFunction
   ```

1. Amazon.Lambda.Tools를 사용하여 도커 이미지를 빌드하고 새 Amazon ECR 리포지토리로 푸시하고 Lambda 함수를 배포합니다.

   `--function-role`로 함수에 대한 [실행 역할](lambda-intro-execution-role.md)의 Amazon 리소스 이름(ARN)이 아닌 역할 이름을 지정합니다. 예를 들어 `lambda-role`입니다.

   ```
   dotnet lambda deploy-function MyFunction --function-role lambda-role
   ```

   Amazon.Lambda.Tools .NET 글로벌에 대한 자세한 내용은 GitHub의 [AWS .NET CLI용 확장](https://github.com/aws/aws-extensions-for-dotnet-cli) 리포지토리를 참조하세요.

1. 함수를 간접 호출합니다.

   ```
   dotnet lambda invoke-function MyFunction --payload "Testing the function"
   ```

   모든 것이 성공하면 다음과 유사한 응답이 표시됩니다.

   ```
   Payload:
   {"Lower":"testing the function","Upper":"TESTING THE FUNCTION"}
   
   Log Tail:
   INIT_REPORT Init Duration: 9999.81 ms   Phase: init     Status: timeout
   START RequestId: 12378346-f302-419b-b1f2-deaa1e8423ed Version: $LATEST
   END RequestId: 12378346-f302-419b-b1f2-deaa1e8423ed
   REPORT RequestId: 12378346-f302-419b-b1f2-deaa1e8423ed  Duration: 3173.06 ms    Billed Duration: 3174 ms        Memory Size: 512 MB     Max Memory Used: 24 MB
   ```

1. Lambda 함수를 삭제합니다.

   ```
   dotnet lambda delete-function MyFunction
   ```

## 런타임 인터페이스 클라이언트에서 대체 기본 이미지 사용
<a name="csharp-image-clients"></a>

[OS 전용 기본 이미지](images-create.md#runtimes-images-provided)나 대체 기본 이미지를 사용하는 경우 이미지에 런타임 인터페이스 클라이언트를 포함해야 합니다. 런타임 인터페이스 클라이언트는 Lambda와 함수 코드 간의 상호 작용을 관리하는 [런타임 API](runtimes-api.md)을 확장합니다.

다음 예제에서는 비 AWS 기본 이미지를 사용하여.NET용 컨테이너 이미지를 빌드하는 방법과 .NET용 Lambda 런타임 인터페이스 클라이언트인 [Amazon.Lambda.RuntimeSupport 패키지](https://github.com/aws/aws-lambda-dotnet/blob/master/Libraries/src/Amazon.Lambda.RuntimeSupport/README.md#using-amazonlambdaruntimesupport-as-a-class-library)를 추가하는 방법을 보여줍니다. 예제 Dockerfile에서는 Microsoft .NET 8 기본 이미지를 사용합니다.

### 사전 조건
<a name="dotnet-csharp-alt-prerequisites"></a>

이 섹션의 단계를 완료하려면 다음이 필요합니다.
+ [.NET SDK](https://dotnet.microsoft.com/download) - 다음 단계에서는 .NET 9 기본 이미지를 사용합니다. .NET 버전이 Dockerfile에 지정한 기본 이미지의 버전과 일치하는지 확인하세요.
+ [Docker](https://docs.docker.com/get-docker)(최소 버전 25.0.0)
+ Docker [buildx 플러그인](https://github.com/docker/buildx/blob/master/README.md)

### 대체 기본 이미지를 사용하여 이미지 생성 및 배포
<a name="dotnet-alt-create"></a>

1. [Amazon.Lambda.Templates](https://github.com/aws/aws-lambda-dotnet#dotnet-cli-templates) NuGet 패키지를 설치합니다.

   ```
   dotnet new install Amazon.Lambda.Templates
   ```

1. `lambda.CustomRuntimeFunction` 템플릿을 사용하여.NET 프로젝트를 생성합니다. 이 템플릿에는 [Amazon.Lambda.RuntimeSupport](https://github.com/aws/aws-lambda-dotnet/blob/master/Libraries/src/Amazon.Lambda.RuntimeSupport/README.md#using-amazonlambdaruntimesupport-as-a-class-library) 패키지가 포함되어 있습니다.

   ```
   dotnet new lambda.CustomRuntimeFunction --name MyFunction --region us-east-1
   ```

1. `MyFunction/src/MyFunction` 디렉터리로 이동합니다. 여기에 프로젝트 파일이 저장됩니다. 다음 파일을 검사합니다.
   + **aws-lambda-tools-defaults.json** – Lambda 함수를 배포할 때 이 파일에 명령줄 옵션을 지정합니다.
   + **Function.cs** - 이 코드에는 `Amazon.Lambda.RuntimeSupport` 라이브러리를 부트스트랩으로 초기화하는 `Main` 메서드가 있는 클래스가 포함되어 있습니다. `Main` 메서드는 함수 프로세스의 진입점입니다. `Main` 메서드는 부트스트랩이 작업할 수 있는 래퍼로 함수 처리기를 래핑합니다. 자세한 내용은 GitHub 리포지토리의 [Using Amazon.Lambda.RuntimeSupport as a class library](https://github.com/aws/aws-lambda-dotnet/blob/master/Libraries/src/Amazon.Lambda.RuntimeSupport/README.md#using-amazonlambdaruntimesupport-as-a-class-library)를 참조하세요.
   + **MyFunction.csproj** - 애플리케이션을 구성하는 파일과 어셈블리가 나열된 .NET [프로젝트 파일](https://learn.microsoft.com/en-us/dotnet/core/project-sdk/overview#project-files)입니다.
   + **Readme.md** - 이 파일에는 샘플 Lambda 함수에 대한 자세한 정보가 들어 있습니다.

1. `aws-lambda-tools-defaults.json` 파일을 열고 다음 줄을 추가합니다.

   ```
     "package-type": "image",
     "docker-host-build-output-dir": "./bin/Release/lambda-publish"
   ```
   + **package-type**: 배포 패키지를 컨테이너 이미지로 정의합니다.
   + **docker-host-build-output-dir**: 빌드 프로세스의 출력 디렉터리를 설정합니다.  
**Example aws-lambda-tools-defaults.json**  

   ```
   {
     "Information": [
       "This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI.",
       "To learn more about the Lambda commands with the .NET Core CLI execute the following command at the command line in the project root directory.",
       "dotnet lambda help",
       "All the command line options for the Lambda command can be specified in this file."
     ],
     "profile": "",
     "region": "us-east-1",
     "configuration": "Release",
     "function-runtime": "provided.al2023",
     "function-memory-size": 256,
     "function-timeout": 30,
     "function-handler": "bootstrap",
     "msbuild-parameters": "--self-contained true",
     "package-type": "image",
     "docker-host-build-output-dir": "./bin/Release/lambda-publish"
   }
   ```

1. `MyFunction/src/MyFunction` 디렉터리에 Dockerfile을 생성합니다. 다음 예제 Dockerfile은 [AWS 기본 이미지](#csharp-image-base) 대신 Microsoft .NET 기본 이미지를 사용합니다.
   + `FROM` 속성을 기본 이미지 식별자로 설정합니다. `MyFunction.csproj` 파일의 기본 이미지와 `TargetFramework`는 모두 동일한 .NET 버전을 사용해야 합니다.
   + `COPY` 명령을 사용하여 함수를 `/var/task` 디렉터리에 복사합니다.
   + Docker 컨테이너가 시작될 때 실행할 모듈로 `ENTRYPOINT`를 설정합니다. 이 경우 모듈은 `Amazon.Lambda.RuntimeSupport` 라이브러리를 초기화하는 부트스트랩입니다.

   참고로 Dockerfile 예제에는 [USER 지침](https://docs.docker.com/reference/dockerfile/#user)이 포함되어 있지 않습니다. Lambda에 컨테이너 이미지를 배포할 때 Lambda는 권한이 최소 권한인 기본 Linux 사용자를 자동으로 정의합니다. 이는 `USER` 지침이 제공되지 않을 때 `root` 사용자에게 기본 설정이 적용되는 표준 Docker 동작과는 다릅니다.  
**Example Dockerfile**  

   ```
   # You can also pull these images from DockerHub amazon/aws-lambda-dotnet:8
   FROM mcr.microsoft.com/dotnet/runtime:9.0
   
   # Set the image's internal work directory
   WORKDIR /var/task
     
   # Copy function code to Lambda-defined environment variable
   COPY "bin/Release/net9.0/linux-x64"  .
     
   # Set the entrypoint to the bootstrap
   ENTRYPOINT ["/usr/bin/dotnet", "exec", "/var/task/bootstrap.dll"]
   ```

1. Amazon.Lambda.Tools [.NET 글로벌 도구 확장](https://aws.amazon.com/blogs/developer/net-core-global-tools-for-aws/)을 설치합니다.

   ```
   dotnet tool install -g Amazon.Lambda.Tools
   ```

   Amazon.Lambda.Tools가 이미 설치되어 있는 경우 최신 버전이 설치되어 있는지 확인합니다.

   ```
   dotnet tool update -g Amazon.Lambda.Tools
   ```

1. Amazon.Lambda.Tools를 사용하여 도커 이미지를 빌드하고 새 Amazon ECR 리포지토리로 푸시하고 Lambda 함수를 배포합니다.

   `--function-role`로 함수에 대한 [실행 역할](lambda-intro-execution-role.md)의 Amazon 리소스 이름(ARN)이 아닌 역할 이름을 지정합니다. 예를 들어 `lambda-role`입니다.

   ```
   dotnet lambda deploy-function MyFunction --function-role lambda-role
   ```

   Amazon.Lambda.Tools .NET CLI 확장에 대한 자세한 내용은 GitHub의 [AWS Extensions for .NET CLI](https://github.com/aws/aws-extensions-for-dotnet-cli) 리포지토리를 참조하세요.

1. 함수를 간접 호출합니다.

   ```
   dotnet lambda invoke-function MyFunction --payload "Testing the function"
   ```

   모든 것이 성공하면 다음을 볼 수 있습니다.

   ```
   Payload:
   "TESTING THE FUNCTION"
   
   Log Tail:
   START RequestId: id Version: $LATEST
   END RequestId: id
   REPORT RequestId: id  Duration: 0.99 ms       Billed Duration: 1 ms         Memory Size: 256 MB     Max Memory Used: 12 MB
   ```

1. Lambda 함수를 삭제합니다.

   ```
   dotnet lambda delete-function MyFunction
   ```

# 네이티브 런타임 형식으로 .NET Lambda 함수 코드 컴파일
<a name="dotnet-native-aot"></a>

.NET 8은 네이티브 사전(AOT) 컴파일을 지원합니다. 네이티브 AOT를 사용하면 Lambda 함수 코드를 네이티브 런타임 형식으로 컴파일할 수 있으므로 런타임에 .NET 코드를 컴파일할 필요가 없습니다. 네이티브 AOT 컴파일은 .NET에서 작성하는 Lambda 함수의 콜드 스타트 시간을 줄일 수 있습니다. 자세한 내용은 AWS Compute Blog의 [Introducing the .NET 8 runtime for AWS Lambda](https://aws.amazon.com/blogs/compute/introducing-the-net-8-runtime-for-aws-lambda/)를 참조하세요.

**Topics**
+ [

## Lambda 런타임
](#dotnet-native-aot-runtime)
+ [

## 사전 조건
](#dotnet-native-aot-prerequisites)
+ [

## 시작하기
](#dotnet-native-aot-getting-started)
+ [

## 직렬화
](#dotnet-native-aot-serialization)
+ [

## 트리밍
](#dotnet-native-aot-trimming)
+ [

## 문제 해결
](#dotnet-native-aot-troubleshooting)

## Lambda 런타임
<a name="dotnet-native-aot-runtime"></a>

네이티브 AOT 컴파일을 사용하여 Lambda 함수 빌드를 배포하려면 관리형 .NET 8 Lambda 런타임을 사용합니다. 이 런타임은 x86\$164 및 arm64 아키텍처의 사용을 모두 지원합니다.

AOT를 사용하지 않고 .NET Lambda 함수를 배포할 경우 애플리케이션이 먼저 중간 언어(IL) 코드로 컴파일됩니다. 런타임의 Just-in-Time(JIT) 컴파일러는 Lambda 런타임에 IL 코드를 가져와 필요에 따라 기계 코드로 컴파일합니다. 네이티브 AOT로 미리 컴파일된 Lambda 함수를 사용하면 함수를 배포할 때 코드를 머신 코드로 컴파일하므로 실행 전에 코드를 컴파일하기 위해 Lambda 런타임의 .NET 런타임이나 SDK에 의존하지 않습니다.

AOT의 한 가지 제한 사항은 .NET 8 런타임이 사용하는 것과 동일한 Amazon Linux 2023(AL2023) 운영 체제가 있는 환경에서 애플리케이션 코드를 컴파일해야 한다는 것입니다. .NET Lambda CLI는 AL2023 이미지를 사용하여 Docker 컨테이너에서 애플리케이션을 컴파일하는 기능을 제공합니다.

크로스 아키텍처 호환성과 관련된 잠재적인 문제를 방지하려면 함수에 대해 구성한 것과 동일한 프로세서 아키텍처를 사용하는 환경에서 코드를 컴파일하는 것이 좋습니다. 크로스 아키텍처 컴파일의 제한 사항에 대해 자세히 알아보려면 Microsoft .NET 설명서의 [교차 컴파일](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/cross-compile)을 참조하세요.

## 사전 조건
<a name="dotnet-native-aot-prerequisites"></a>

**Docker**  
네이티브 AOT를 사용하려면 .NET 8 런타임과 동일한 AL2023 운영 체제가 있는 환경에서 함수 코드를 컴파일해야 합니다. 다음 섹션의 .NET CLI 명령은 도커를 사용하여 AL2023 환경에서 Lambda 함수를 개발하고 빌드합니다.

**.NET 8 SDK**  
네이티브 AOT 컴파일은 .NET 8의 기능입니다. 빌드 머신에 런타임뿐만 아니라 [.NET 8 SDK](https://dotnet.microsoft.com/en-us/download/dotnet/8.0)도 설치해야 합니다.

**Amazon.Lambda.Tools**  
Lambda 함수를 생성하려면 [https://www.nuget.org/packages/Amazon.Lambda.Tools](https://www.nuget.org/packages/Amazon.Lambda.Tools) [.NET 글로벌 도구 확장](https://aws.amazon.com/blogs/developer/net-core-global-tools-for-aws/)을 사용합니다. Amazon.Lambda.Tools를 설치하려면 다음 명령을 실행합니다.  

```
dotnet tool install -g Amazon.Lambda.Tools
```
Amazon.Lambda.Tools .NET CLI 확장에 대한 자세한 내용은 GitHub에서 [AWS Extensions for .NET CLI](https://github.com/aws/aws-extensions-for-dotnet-cli) 리포지토리를 참조하세요.

**Amazon.Lambda.Templates**  
Lambda 함수 코드를 생성하려면 [https://www.nuget.org/packages/Amazon.Lambda.Templates](https://www.nuget.org/packages/Amazon.Lambda.Templates) NuGet 패키지를 사용합니다. 이 템플릿 패키지를 설치하려면 다음 명령을 실행합니다.  

```
dotnet new install Amazon.Lambda.Templates
```

## 시작하기
<a name="dotnet-native-aot-getting-started"></a>

.NET 글로벌 CLI와 AWS Serverless Application Model(AWS SAM) 모두 네이티브 AOT를 사용하여 애플리케이션을 빌드하기 위한 시작 템플릿을 제공합니다. 첫 번째 네이티브 AOT Lambda 함수를 빌드하려면 다음 지침의 단계를 수행하십시오.

**네이티브 AOT 컴파일된 Lambda 함수를 초기화하고 배포하기**

1. 네이티브 AOT 템플릿을 사용하여 새 프로젝트를 초기화한 다음 생성된 `.cs` 및 `.csproj` 파일이 포함된 디렉토리로 이동합니다. 이 예제에서는 함수 `NativeAotSample`의 이름을 지정합니다.

   ```
   dotnet new lambda.NativeAOT -n NativeAotSample
   cd ./NativeAotSample/src/NativeAotSample
   ```

   네이티브 AOT 템플릿으로 생성한 `Function.cs` 파일에는 다음 함수 코드가 포함되어 있습니다.

   ```
   using Amazon.Lambda.Core;
   using Amazon.Lambda.RuntimeSupport;
   using Amazon.Lambda.Serialization.SystemTextJson;
   using System.Text.Json.Serialization;
   
   namespace NativeAotSample;
   
   public class Function
   {
       /// <summary>
       /// The main entry point for the Lambda function. The main function is called once during the Lambda init phase. It
       /// initializes the .NET Lambda runtime client passing in the function handler to invoke for each Lambda event and
       /// the JSON serializer to use for converting Lambda JSON format to the .NET types.
       /// </summary>
       private static async Task Main()
       {
           Func<string, ILambdaContext, string> handler = FunctionHandler;
           await LambdaBootstrapBuilder.Create(handler, new SourceGeneratorLambdaJsonSerializer<LambdaFunctionJsonSerializerContext>())
               .Build()
               .RunAsync();
       }
   
       /// <summary>
       /// A simple function that takes a string and does a ToUpper.
       ///
       /// To use this handler to respond to an AWS event, reference the appropriate package from
       /// https://github.com/aws/aws-lambda-dotnet#events
       /// and change the string input parameter to the desired event type. When the event type
       /// is changed, the handler type registered in the main method needs to be updated and the LambdaFunctionJsonSerializerContext
       /// defined below will need the JsonSerializable updated. If the return type and event type are different then the
       /// LambdaFunctionJsonSerializerContext must have two JsonSerializable attributes, one for each type.
       ///
       // When using Native AOT extra testing with the deployed Lambda functions is required to ensure
       // the libraries used in the Lambda function work correctly with Native AOT. If a runtime
       // error occurs about missing types or methods the most likely solution will be to remove references to trim-unsafe
       // code or configure trimming options. This sample defaults to partial TrimMode because currently the AWS
       // SDK for .NET does not support trimming. This will result in a larger executable size, and still does not
       // guarantee runtime trimming errors won't be hit.
       /// </summary>
       /// <param name="input"></param>
       /// <param name="context"></param>
       /// <returns></returns>
       public static string FunctionHandler(string input, ILambdaContext context)
       {
           return input.ToUpper();
       }
   }
   
   /// <summary>
   /// This class is used to register the input event and return type for the FunctionHandler method with the System.Text.Json source generator.
   /// There must be a JsonSerializable attribute for each type used as the input and return type or a runtime error will occur
   /// from the JSON serializer unable to find the serialization information for unknown types.
   /// </summary>
   [JsonSerializable(typeof(string))]
   public partial class LambdaFunctionJsonSerializerContext : JsonSerializerContext
   {
       // By using this partial class derived from JsonSerializerContext, we can generate reflection free JSON Serializer code at compile time
       // which can deserialize our class and properties. However, we must attribute this class to tell it what types to generate serialization code for.
       // See https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-source-generation
   ```

   네이티브 AOT는 애플리케이션을 단일 네이티브 바이너리로 컴파일합니다. 해당 바이너리의 엔트리포인트는 `static Main` 메서드입니다. `static Main` 내에서 Lambda 런타임이 부트스트랩되고 `FunctionHandler` 메서드가 설정됩니다. 런타임 부트스트랩의 일부로 소스 생성 시리얼라이저는 `new SourceGeneratorLambdaJsonSerializer<LambdaFunctionJsonSerializerContext>()`을(를) 사용하여 구성됩니다

1. Lambda에 애플리케이션을 배포하려면 도커가 로컬 환경에서 실행되고 있는지 확인하고 다음 명령을 실행하십시오.

   ```
   dotnet lambda deploy-function
   ```

   .NET 글로벌 CLI는 백그라운드에서 AL2023 도커 이미지를 다운로드하고 실행 중인 컨테이너 내에서 애플리케이션 코드를 컴파일합니다. 컴파일된 바이너리는 Lambda에 배포되기 전에 로컬 파일 시스템으로 다시 출력됩니다.

1. 다음 명령을 실행하여 함수를 테스트하십시오. `<FUNCTION_NAME>`을(를) 배포 마법사에서 함수에 선택한 이름으로 바꾸십시오.

   ```
   dotnet lambda invoke-function <FUNCTION_NAME> --payload "hello world"
   ```

   CLI의 응답에는 콜드 시작(초기화 기간)에 대한 성과 세부 정보와 함수 간접 호출의 총 실행 시간이 포함됩니다.

1. 이전 단계에 따라 생성한 AWS 리소스를 삭제하려면 다음 명령을 실행하십시오. `<FUNCTION_NAME>`을(를) 배포 마법사에서 함수에 선택한 이름으로 바꾸십시오. 더 이상 사용하지 않는 AWS 리소스를 삭제하면 AWS 계정에 불필요한 요금이 청구되는 것을 방지할 수 있습니다.

   ```
   dotnet lambda delete-function <FUNCTION_NAME>
   ```

## 직렬화
<a name="dotnet-native-aot-serialization"></a>

[네이티브 AOT를 사용하여 Lambda에 함수를 배포하려면 함수 코드가 소스 생성 직렬화](https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/source-generation-modes?pivots=dotnet-8-0)를 사용해야 합니다. 소스 생성기는 런타임 리플렉션을 사용하여 직렬화를 위해 객체 속성에 액세스하는 데 필요한 메타데이터를 수집하는 대신 애플리케이션을 빌드할 때 컴파일되는 C\$1 소스 파일을 생성합니다. 소스 생성 시리얼라이저를 올바르게 구성하려면 함수에서 사용하는 입력 및 출력 객체와 사용자 지정 유형을 포함해야 합니다. 예를 들어 API Gateway REST API에서 이벤트를 수신하고 사용자 지정 `Product` 유형을 반환하는 Lambda 함수에는 다음과 같이 정의된 시리얼라이저가 포함됩니다.

```
[JsonSerializable(typeof(APIGatewayProxyRequest))]
[JsonSerializable(typeof(APIGatewayProxyResponse))]
[JsonSerializable(typeof(Product))]
public partial class CustomSerializer : JsonSerializerContext
{
}
```

## 트리밍
<a name="dotnet-native-aot-trimming"></a>

네이티브 AOT는 컴파일 과정에서 애플리케이션 코드를 트리밍하여 바이너리가 최대한 작아지도록 합니다. .NET 8 for Lambda는 이전 버전의 .NET에 비해 향상된 트리밍 지원을 제공합니다. [Lambda 런타임 라이브러리](https://github.com/aws/aws-lambda-dotnet/pull/1596), [AWS .NET SDK](https://github.com/aws/aws-sdk-net/pulls?q=is%3Apr+trimming), [.NET Lambda Annotations](https://github.com/aws/aws-lambda-dotnet/pull/1610) 및 .NET 8 자체에 대한 지원이 추가되었습니다.

이러한 개선 사항을 통해 빌드 시간 트리밍 경고를 제거할 수 있지만 .NET이 트림으로부터 완전히 안전하다고 할 수는 없습니다. 즉, 함수가 사용되는 라이브러리의 일부는 일부 컴파일 단계에서 제거될 수도 있습니다. 다음 예제와 같이 `TrimmerRootAssemblies`를 `.csproj` 파일의 일부로 정의하여 이를 관리할 수 있습니다.

```
<ItemGroup>
    <TrimmerRootAssembly Include="AWSSDK.Core" />
    <TrimmerRootAssembly Include="AWSXRayRecorder.Core" />
    <TrimmerRootAssembly Include="AWSXRayRecorder.Handlers.AwsSdk" />
    <TrimmerRootAssembly Include="Amazon.Lambda.APIGatewayEvents" />
    <TrimmerRootAssembly Include="bootstrap" />
    <TrimmerRootAssembly Include="Shared" />
</ItemGroup>
```

트리밍 경고를 받은 경우 `TrimmerRootAssembly`에 경고를 생성하는 클래스를 추가해도 문제가 해결되지 않을 수 있습니다. 트리밍 경고는 클래스가 런타임까지 확인할 수 없는 다른 클래스에 액세스하려고 함을 나타냅니다. 런타임 오류를 방지하려면 `TrimmerRootAssembly`에 이 두 번째 클래스를 추가합니다.

트리밍 경고 관리에 대해 자세히 알아보려면 Microsoft .NET 설명서의 [트리밍 경고 소개](https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/fixing-warnings)를 참조하세요.

## 문제 해결
<a name="dotnet-native-aot-troubleshooting"></a>

**오류: OS 간 네이티브 컴파일은 지원되지 않습니다.**  
Amazon.Lambda.Tools .NET Core 글로벌 도구 버전이 오래되었습니다. 최신 버전으로 업데이트한 후 다시 시도하세요.

**도커: 이 플랫폼에서는 이미지 운영 체제 ‘linux’를 사용할 수 없습니다.**  
시스템의 도커는 Windows 컨테이너를 사용하도록 구성되어 있습니다. 네이티브 AOT 빌드 환경을 실행하려면 Linux 컨테이너로 전환하세요.

일반적인 오류에 대한 자세한 내용은 GitHub에서 [AWS NativeAOT for .NET](https://github.com/awslabs/dotnet-nativeaot-labs#common-errors) 리포지토리를 참조하세요.

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

Lambda는 함수를 실행할 때 컨텍스트 객체를 [핸들러](csharp-handler.md)에 전달합니다. 이 객체는 호출, 함수 및 실행 환경에 관한 정보를 속성에 제공합니다.

**컨텍스트 속성**
+ `FunctionName` – Lambda 함수의 이름입니다.
+ `FunctionVersion` – 함수의 [버전](configuration-versions.md)입니다.
+ `InvokedFunctionArn` – 함수를 간접 호출할 때 사용하는 Amazon 리소스 이름(ARN)입니다. 간접 호출자가 버전 번호 또는 별칭을 지정했는지 여부를 나타냅니다.
+ `MemoryLimitInMB` – 함수에 할당된 메모리의 양입니다.
+ `AwsRequestId` – 호출 요청의 식별자입니다.
+ `LogGroupName` – 함수에 대한 로그 그룹입니다.
+ `LogStreamName` – 함수 인스턴스에 대한 로그 스트림입니다.
+ `RemainingTime` (`TimeSpan`) – 실행 시간이 초과되기 전에 남은 시간(밀리초)입니다.
+ `Identity` – (모바일 앱) 요청을 승인한 Amazon Cognito 자격 증명에 대한 정보입니다.
+ `ClientContext` – (모바일 앱) 클라이언트 애플리케이션이 Lambda에게 제공한 클라이언트 컨텍스트입니다.
+ `Logger` 함수에 대한 [로거 객체](csharp-logging.md)입니다.

`ILambdaContext` 객체의 정보를 사용하여 모니터링 목적으로 함수의 간접 호출에 대한 정보를 출력할 수 있습니다. 다음 코드는 구조화된 로깅 프레임워크에 컨텍스트 정보를 추가하는 방법의 예입니다. 이 예제에서는 함수가 `AwsRequestId`을(를) 로그 출력에 추가합니다. 또한 함수는 Lambda 함수 제한 시간에 도달하려는 경우 `RemainingTime` 속성을 사용하여 진행 중인 작업도 취소합니다.

```
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace GetProductHandler;

public class Function
{
    private readonly IDatabaseRepository _repo;
    
    public Function()
    {
        this._repo = new DatabaseRepository();
    }
    
    public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest request, ILambdaContext context)
    {
        Logger.AppendKey("AwsRequestId", context.AwsRequestId);
        
        var id = request.PathParameters["id"];

        using var cts = new CancellationTokenSource();
        
        try
        {
            cts.CancelAfter(context.RemainingTime.Add(TimeSpan.FromSeconds(-1)));
            
            var databaseRecord = await this._repo.GetById(id, cts.Token);
            
            return new APIGatewayProxyResponse 
            {
                StatusCode = (int)HttpStatusCode.OK,
                Body = JsonSerializer.Serialize(databaseRecord)
            };
        }
        catch (Exception ex)
        {
            return new APIGatewayProxyResponse 
            {
                StatusCode = (int)HttpStatusCode.InternalServerError,
                Body = JsonSerializer.Serialize(new { error = ex.Message })
            };
        }
        finally
        {
            cts.Cancel();
        }
    }
}
```

# C\$1 Lambda 함수 로그 및 모니터링
<a name="csharp-logging"></a>

AWS Lambda는 자동으로 Lambda 함수를 모니터링하고 로그 항목을 Amazon CloudWatch로 보냅니다. Lambda 함수는 함수의 각 인스턴스에 대한 CloudWatch Logs 로그 그룹 및 로그 스트림과 함께 제공됩니다. Lambda 런타임 환경은 각 간접 호출에 대한 세부 정보와 함수 코드의 기타 출력을 로그 스트림으로 전송합니다. CloudWatch Logs에 대한 자세한 내용은 [CloudWatch Logs로 Lambda 함수 로그 전송](monitoring-cloudwatchlogs.md) 섹션을 참조하세요.

**Topics**
+ [

## 로그를 반환하는 함수 생성
](#csharp-logging-output)
+ [

## .NET에서 Lambda 고급 로깅 제어 사용
](#csharp-logging-advanced)
+ [

## 추가 로깅 도구 및 라이브러리
](#csharp-tools-libraries)
+ [

## 구조화된 로깅에 Powertools forAWS Lambda(.NET) 및 AWS SAM 사용
](#dotnet-logging-sam)
+ [

## Lambda 콘솔에서 로그 보기
](#csharp-logging-console)
+ [

## CloudWatch 콘솔에서 로그 보기
](#csharp-logging-cwconsole)
+ [

## AWS Command Line Interface(AWS CLI)(을)를 사용하여 로그 보기
](#csharp-logging-cli)
+ [

## 로그 삭제
](#csharp-logging-delete)

## 로그를 반환하는 함수 생성
<a name="csharp-logging-output"></a>

함수 코드의 로그를 출력하려면 컨텍스트 객체에서 [ILambdaLogger](https://github.com/aws/aws-lambda-dotnet/blob/master/Libraries/src/Amazon.Lambda.Core/ILambdaLogger.cs)를 사용하거나 [콘솔 클래스](https://docs.microsoft.com/en-us/dotnet/api/system.console)에서 메서드를 사용하거나 `stdout` 또는 `stderr`에 쓰는 로깅 라이브러리를 사용합니다.

.NET 런타임은 각 호출에 대해 `START`, `END` 및 `REPORT` 줄을 로깅합니다. 보고서 행은 다음과 같은 세부 정보를 제공합니다.

**REPORT 행 데이터 필드**
+ **RequestId** – 호출의 고유한 요청 ID입니다.
+ **지속시간** – 함수의 핸들러 메서드가 이벤트를 처리하는 데 걸린 시간입니다.
+ **청구 기간** – 호출에 대해 청구된 시간입니다.
+ **메모리 크기** - 함수에 할당된 메모리 양입니다.
+ **사용된 최대 메모리** – 함수에서 사용한 메모리 양입니다. 간접 호출이 실행 환경을 공유하는 경우 Lambda는 모든 간접 호출에서 사용된 최대 메모리를 보고합니다. 이 동작으로 인해 보고된 값이 예상보다 높을 수 있습니다.
+ **초기화 기간** – 제공된 첫 번째 요청의 경우 런타임이 핸들러 메서드 외부에서 함수를 로드하고 코드를 실행하는 데 걸린 시간입니다.
+ **XRAY TraceId** – 추적된 요청의 경우 [AWS X-Ray 추적 ID](services-xray.md)입니다.
+ **SegmentId** - 추적된 요청의 경우 X-Ray 세그먼트 ID입니다.
+ **샘플링 완료(Sampled)** – 추적된 요청의 경우 샘플링 결과입니다.

## .NET에서 Lambda 고급 로깅 제어 사용
<a name="csharp-logging-advanced"></a>

함수의 로그를 캡처, 처리 및 사용하는 방법을 더 잘 제어할 수 있도록 지원되는 .NET 런타임에 대한 다음의 로깅 옵션을 구성할 수 있습니다.
+ **로그 형식** - 함수 로그의 경우 일반 텍스트와 구조화된 JSON 형식 중에서 선택
+ **로그 수준** - JSON 형식의 로그의 경우, Lambda가 CloudWatch로 전송하는 로그의 세부 수준(ERROR, DEBUG 또는 INFO 등)을 선택
+ **로그 그룹** - 함수가 로그를 보내는 CloudWatch 로그 그룹을 선택

이러한 로깅 옵션에 대한 자세한 내용과 이를 사용하도록 함수를 구성하는 방법에 대한 지침은 [Lambda 함수에 대한 고급 로깅 제어 구성](monitoring-logs.md#monitoring-cloudwatchlogs-advanced)을 참조하세요.

.NET Lambda 함수에서 로그 형식 및 로그 수준 옵션을 사용하려면 다음 섹션의 지침을 참조하세요.

### .NET에서 구조화된 JSON 로그 형식 사용
<a name="csharp-logging-advanced-JSON"></a>

함수의 로그 형식으로 JSON을 선택하면 Lambda는 [ILambdaLogger](https://github.com/aws/aws-lambda-dotnet/blob/master/Libraries/src/Amazon.Lambda.Core/ILambdaLogger.cs)를 사용하여 로그 출력을 구조화된 JSON으로 전송합니다. 각 JSON 로그 객체에는 다음 키가 있는 다섯 개의 키 값 페어가 포함되어 있습니다.
+ `"timestamp"` - 로그 메시지가 생성된 시간
+ `"level"` - 메시지에 할당된 로그 수준
+ `"requestId"` - 함수 간접 호출의 고유한 요청 ID
+ `"traceId"` - `_X_AMZN_TRACE_ID` 환경 변수
+ `"message"` - 로그 메시지의 내용

`ILambdaLogger` 인스턴스는 예를 들어 예외를 로깅할 때 키 값 페어를 추가할 수 있습니다. [고객이 제공하는 로그 파라미터](#csharp-logging-advanced-JSON-user-supplied) 섹션에서 설명한 대로 자체 추가 파라미터를 제공할 수도 있습니다.

**참고**  
코드가 이미 다른 로깅 라이브러리를 사용하여 JSON 형식의 로그를 생성하는 경우 함수의 로그 형식이 일반 텍스트로 설정되었는지 확인합니다. 로그 형식을 JSON으로 설정하면 로그 출력이 이중으로 인코딩됩니다.

다음 로깅 명령 예제에서는 `INFO` 수준의 로그 메시지를 작성하는 방법을 보여줍니다.

**Example .NET 로깅 코드**  

```
context.Logger.LogInformation("Fetching cart from database");
```

다음 예제와 같이 로그 수준을 인수로 사용하는 일반 로그 메서드를 사용할 수도 있습니다.

```
context.Logger.Log(LogLevel.Information, "Fetching cart from database");
```

이 코드 예제의 로그 출력은 다음과 같이 CloudWatch Logs에서 캡처됩니다.

**Example JSON 로그 레코드**  

```
{
    "timestamp": "2025-09-07T01:30:06.977Z",
    "level": "Information",
    "requestId": "8f711428-7e55-46f9-ae88-2a65d4f85fc5",
    "traceId": "1-6408af34-50f56f5b5677a7d763973804",
    "message": "Fetching cart from database"
}
```

**참고**  
JSON이 아닌 일반 텍스트를 사용하도록 함수의 로그 형식을 구성하는 경우 메시지에 캡처된 로그 수준은 4자리 레이블을 사용하는 Microsoft 규칙을 따릅니다. 예를 들어 `Debug`의 로그 수준은 메시지에서 `dbug`로 표시됩니다.  
JSON 형식의 로그를 사용하도록 함수를 구성하는 경우 로그에 캡처된 로그 수준은 JSON 로그 레코드 예제에 표시된 대로 전체 레이블을 사용합니다.

로그 출력에 수준을 할당하지 않으면 Lambda는 자동으로 수준 INFO를 할당합니다.

#### JSON에서 예외 로깅
<a name="csharp-logging-advanced-JSON-exceptions"></a>

`ILambdaLogger`를 통해 구조화된 JSON 로깅을 사용하는 경우 다음 예제와 같이 코드에서 예외를 로깅할 수 있습니다.

**Example 예외 로깅 사용**  

```
try
{
    connection.ExecuteQuery(query);
}
catch(Exception e)
{
    context.Logger.LogWarning(e, "Error executing query");
}
```

이 코드에서 생성된 로그 형식 출력은 다음 예제 JSON에 나와 있습니다. JSON의 `message` 속성은 `LogWarning` 직접 호출에서 제공된 메시지 인수를 사용하여 채워지는 반면, `errorMessage` 속성은 예외 자체의 `Message` 속성에서 가져옵니다.

**Example JSON 로그 레코드**  

```
{
    "timestamp": "2025-09-07T01:30:06.977Z",
    "level": "Warning",
    "requestId": "8f711428-7e55-46f9-ae88-2a65d4f85fc5",
    "traceId": "1-6408af34-50f56f5b5677a7d763973804",
    "message": "Error executing query",
    "errorType": "System.Data.SqlClient.SqlException",
    "errorMessage": "Connection closed",
    "stackTrace": ["<call exception.StackTrace>"]
}
```

함수의 로깅 형식이 JSON으로 설정된 경우 Lambda는 코드에서 발견되지 않은 예외가 발생할 때 JSON 형식의 로그 메시지도 출력합니다. 다음 코드 스니펫 및 로그 메시지 예제에서는 발견되지 않은 예외가 로깅되는 방법을 보여줍니다.

**Example 예외 코드**  

```
throw new ApplicationException("Invalid data");
```

**Example JSON 로그 레코드**  

```
{
    "timestamp": "2025-09-07T01:30:06.977Z",
    "level": "Error",
    "requestId": "8f711428-7e55-46f9-ae88-2a65d4f85fc5",
    "traceId": "1-6408af34-50f56f5b5677a7d763973804",
    "message": "Invalid data",
    "errorType": "System.ApplicationException",
    "errorMessage": "Invalid data",
    "stackTrace": ["<call exception.StackTrace>"]
}
```

#### 고객이 제공하는 로그 파라미터
<a name="csharp-logging-advanced-JSON-user-supplied"></a>

JSON 형식의 로그 메시지를 사용하면 추가 로그 파라미터를 제공하고 이를 `message` 로그에 포함할 수 있습니다. 다음 코드 스니펫 예제에서는 `retryAttempt` 및 `uri` 레이블이 지정된 두 개의 사용자 제공 파라미터를 추가하는 명령을 보여줍니다. 예제에서 이러한 파라미터의 값은 로깅 명령으로 전달된 `retryAttempt` 및 `uriDestination` 인수에서 가져옵니다.

**Example 추가 파라미터를 사용하는 JSON 로깅 명령**  

```
context.Logger.LogInformation("Starting retry {retryAttempt} to make GET request to {uri}", retryAttempt, uriDestination);
```

이 명령에서 생성된 로그 메시지 출력은 다음 예제 JSON에 나와 있습니다.

**Example JSON 로그 레코드**  

```
{
    "timestamp": "2025-09-07T01:30:06.977Z",
    "level": "Information",
    "requestId": "8f711428-7e55-46f9-ae88-2a65d4f85fc5",
    "traceId": "1-6408af34-50f56f5b5677a7d763973804",
    "message": "Starting retry 1 to make GET request to http://example.com/",
    "retryAttempt": 1,
    "uri": "http://example.com/"
}
```

**작은 정보**  
추가 파라미터를 지정할 때 이름 대신 위치 속성을 사용할 수도 있습니다. 예를 들어 이전 예제의 로깅 명령을 다음과 같이 쓸 수도 있습니다.  

```
context.Logger.LogInformation("Starting retry {0} to make GET request to {1}", retryAttempt, uriDestination);
```

추가 로깅 파라미터를 제공하면 Lambda는 이를 JSON 로그 레코드에서 최상위 속성으로 캡처합니다. 이 접근 방식은 별도의 하위 객체에서 추가 파라미터를 캡처하는 `Serilog`와 같은 일부 널리 사용되는 .NET 로깅 라이브러리와 다릅니다.

추가 파라미터에 대해 제공하는 인수가 복잡한 객체인 경우 기본적으로 Lambda는 `ToString()` 메서드를 사용하여 값을 제공합니다. 인수에 JSON 직렬화를 적용해야 함을 나타내려면 다음 코드 스니펫에 표시된 대로 `@` 접두사를 사용합니다. 이 예제에서 `User`는 `FirstName` 및 `LastName` 속성을 포함하는 객체입니다.

**Example JSON 직렬화가 적용된 객체를 포함하는 JSON 로깅 명령**  

```
context.Logger.LogInformation("User {@user} logged in", User);
```

이 명령에서 생성된 로그 메시지 출력은 다음 예제 JSON에 나와 있습니다.

**Example JSON 로그 레코드**  

```
{
    "timestamp": "2025-09-07T01:30:06.977Z",
    "level": "Information",
    "requestId": "8f711428-7e55-46f9-ae88-2a65d4f85fc5",
    "traceId": "1-6408af34-50f56f5b5677a7d763973804",
    "message": "User {@user} logged in",
    "user": 
    {
        "FirstName": "John",
        "LastName": "Doe"
    }
}
```

추가 파라미터에 대한 인수가 배열이거나 `IList` 또는 `IDictionary`를 구현하는 경우 Lambda는 다음 JSON 로그 레코드 예제와 같이 인수를 JSON 로그 메시지에 배열로 추가합니다. 이 예제에서 `{users}`는 이전 예제와 동일한 형식의 `User` 속성 인스턴스를 포함하는 `IList` 인수를 가져옵니다. Lambda는 이 `IList`를 배열로 변환하며, 이때 각 값은 `ToString` 메서드를 사용하여 생성됩니다.

**Example `IList` 인수를 포함하는 JSON 로그 레코드**  

```
{
    "timestamp": "2025-09-07T01:30:06.977Z",
    "level": "Information",
    "requestId": "8f711428-7e55-46f9-ae88-2a65d4f85fc5",
    "traceId": "1-6408af34-50f56f5b5677a7d763973804",
    "message": "{users} have joined the group",
    "users": 
    [
        "Rosalez, Alejandro",
        "Stiles, John"       
    ] 
}
```

로깅 명령에서 `@` 접두사를 사용하여 목록에 JSON 직렬화를 적용할 수도 있습니다. 다음 JSON 로그 레코드 예제에서는 `users` 속성에 JSON 직렬화가 적용되었습니다.

**Example JSON 직렬화가 적용된된 `IList` 인수를 포함하는 JSON 로그 레코드**  

```
{
    "timestamp": "2025-09-07T01:30:06.977Z",
    "level": "Information",
    "requestId": "8f711428-7e55-46f9-ae88-2a65d4f85fc5",
    "traceId": "1-6408af34-50f56f5b5677a7d763973804",
    "message": "{@users} have joined the group",
    "users": 
    [
        {
            "FirstName": "Alejandro",
            "LastName": "Rosalez"
        },
        {
            "FirstName": "John",
            "LastName": "Stiles"
        }        
    ] 
}
```

### .NET에서 로그 수준 필터링 사용
<a name="csharp-logging-advanced-levels"></a>

로그 수준 필터링을 구성하면 특정 상세 수준 이하의 로그만 CloudWatch Logs로 전송하도록 선택할 수 있습니다. 함수의 로그 수준 필터링을 구성하는 방법을 알아보려면 [로그 수준 필터링](monitoring-cloudwatchlogs-log-level.md)을 참조하세요.

AWS Lambda에서 로그 메시지를 로그 수준별로 필터링하려면 JSON 형식의 로그를 사용하거나 .NET `Console` 메서드를 사용하여 로그 메시지를 출력할 수 있습니다. JSON 형식의 로그를 생성하려면 [함수의 로그 유형을 JSON으로 구성](monitoring-cloudwatchlogs-logformat.md#monitoring-cloudwatchlogs-set-format)하고 `ILambdaLogger` 인스턴스를 사용합니다.

JSON 형식의 로그를 사용하여 Lambda는 [.NET에서 구조화된 JSON 로그 형식 사용](#csharp-logging-advanced-JSON)에서 설명하는 JSON 객체의 'level' 키 값 페어를 사용하여 로그 출력을 필터링합니다.

.NET `Console` 메서드를 사용하여 CloudWatch Logs에 메시지를 쓰는 경우 Lambda는 다음과 같이 메시지에 로그 수준을 적용합니다.
+ **Console.WriteLine 메서드** - Lambda에서 `INFO`의 로그 수준을 적용함
+ **Console.Error 메서드** - Lambda에서 `ERROR`의 로그 수준을 적용함

로그 수준 필터링을 사용하도록 함수를 구성하는 경우 Lambda가 CloudWatch 로그로 전송하기를 원하는 로그 수준을 다음 옵션 중에서 선택해야 합니다. .NET `ILambdaLogger`에서 사용하는 표준 Microsoft 수준에 대한 Lambda에서 사용하는 로그 수준의 매핑을 기록합니다.


| Lambda 로그 수준 | 동등한 Microsoft 수준 | 표준 사용량 | 
| --- | --- | --- | 
| TRACE(최대 세부 정보) | 추적 | 코드 실행 경로를 추적하는 데 사용되는 가장 세밀한 정보 | 
| DEBUG | 디버그 | 시스템 디버깅에 대한 세부 정보 | 
| INFO | 정보 | 함수의 정상 작동을 기록하는 메시지 | 
| WARN | 경고 | 해결되지 않을 경우 예상치 못한 동작으로 이어질 수 있는 잠재적 오류에 대한 메시지 | 
| 오류 | 오류 | 코드가 예상대로 작동하지 못하게 하는 문제에 대한 메시지 | 
| FATAL(최소 세부 정보) | 심각 | 응용 프로그램 작동을 중지시키는 심각한 오류에 대한 메시지 | 

Lambda는 선택한 상세 수준 이하의 로그만 Cloudwatch로 전송합니다. 예를 들어 로그 수준을 WARN으로 구성하면 Lambda는 WARN, ERROR 및 FATAL에 해당하는 로그를 전송합니다.

## 추가 로깅 도구 및 라이브러리
<a name="csharp-tools-libraries"></a>

[Powertools for AWS Lambda(.NET)](https://docs.aws.amazon.com/powertools/dotnet/)는 서버리스 모범 사례를 구현하고 개발자 속도를 높이기 위한 개발자 도구 키트입니다. [Logging 유틸리티](https://docs.aws.amazon.com/powertools/dotnet/core/logging/)는 JSON으로 구조화된 출력과 함께 모든 함수의 함수 컨텍스트에 대한 추가 정보를 포함하는 Lambda 최적화 로거를 제공합니다. 이 유틸리티를 사용하여 다음을 수행합니다.
+ Lambda 컨텍스트, 콜드 스타트 및 구조 로깅 출력에서 JSON으로 주요 필드 캡처
+ 지시 시 Lambda 호출 이벤트 로깅(기본적으로 비활성화됨)
+ 로그 샘플링을 통해 호출 비율에 대해서만 모든 로그 인쇄(기본적으로 비활성화됨)
+ 언제든지 구조화된 로그에 추가 키 추가
+ 사용자 지정 로그 포맷터(Bring Your Own Formatter)를 사용하여 조직의 로깅 RFC와 호환되는 구조로 로그 출력

## 구조화된 로깅에 Powertools forAWS Lambda(.NET) 및 AWS SAM 사용
<a name="dotnet-logging-sam"></a>

다음 단계를 따라 AWS SAM을 사용하는 통합 [Powertools for AWS Lambda(.NET)](https://docs.powertools.aws.dev/lambda-dotnet) 모듈을 사용하여 샘플 Hello World C\$1 애플리케이션을 다운로드, 빌드 및 배포합니다. 이 애플리케이션은 기본 API 백엔드를 구현하고 Powertools를 사용하여 로그, 지표 및 추적을 내보냅니다. 이 구성에는 Amazon API Gateway 엔드포인트와 Lambda 함수가 포함됩니다. API Gateway 엔드포인트로 GET 요청을 전송하면 Lambda 함수가 간접 호출되고 Embedded Metric Format을 사용하여 로그 및 지표를 CloudWatch로 전송하고 기록을 AWS X-Ray로 전송합니다. 이 함수는 `hello world` 메시지를 반환합니다.

**사전 조건**

이 섹션의 단계를 완료하려면 다음이 필요합니다.
+ .NET 8
+ [AWS CLI 버전 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ [AWS SAM CLI 버전 1.75 이상](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html). 이전 버전의 AWS SAM CLI가 있는 경우 [AWS SAM CLI 업그레이드](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/manage-sam-cli-versions.html#manage-sam-cli-versions-upgrade)를 참조하세요.

**샘플 AWS SAM 애플리케이션 배포**

1. Hello World TypeScript 템플릿을 사용하여 애플리케이션을 초기화합니다.

   ```
   sam init --app-template hello-world-powertools-dotnet --name sam-app --package-type Zip --runtime dotnet6 --no-tracing
   ```

1. 앱을 빌드합니다.

   ```
   cd sam-app && sam build
   ```

1. 앱을 배포합니다.

   ```
   sam deploy --guided
   ```

1. 화면에 표시되는 프롬프트를 따릅니다. 대화형 환경에서 제공되는 기본 옵션을 수락하려면 `Enter`을 누릅니다.
**참고**  
**HelloWorldFunction에 권한 부여가 정의되어 있지 않을 수 있습니다. 괜찮습니다?**에 대해 `y`를 입력합니다.

1. 배포된 애플리케이션의 URL을 가져옵니다.

   ```
   aws cloudformation describe-stacks --stack-name sam-app --query 'Stacks[0].Outputs[?OutputKey==`HelloWorldApi`].OutputValue' --output text
   ```

1. API 엔드포인트 간접 호출:

   ```
   curl -X GET <URL_FROM_PREVIOUS_STEP>
   ```

   성공하면 다음과 같은 결과가 응답됩니다.

   ```
   {"message":"hello world"}
   ```

1. 함수에 대한 로그를 가져오려면 [sam logs](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-logs.html)를 실행합니다. 자세한 내용은 *AWS Serverless Application Model 개발자 안내서*에서 [로그 관련 작업](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-logging.html)을 참조하세요.

   ```
   sam logs --stack-name sam-app
   ```

   출력은 다음과 같습니다.

   ```
   2025/02/20/[$LATEST]4eaf8445ba7a4a93b999cb17fbfbecd8 2025-09-20T14:15:27.988000 INIT_START Runtime Version: dotnet:6.v13        Runtime Version ARN: arn:aws:lambda:ap-southeast-2::runtime:699f346a05dae24c58c45790bc4089f252bf17dae3997e79b17d939a288aa1ec
   2025/02/20/[$LATEST]4eaf8445ba7a4a93b999cb17fbfbecd8 2025-09-20T14:15:28.229000 START RequestId: bed25b38-d012-42e7-ba28-f272535fb80e Version: $LATEST
   2025/02/20/[$LATEST]4eaf8445ba7a4a93b999cb17fbfbecd8 2025-09-20T14:15:29.259000 2025-09-20T14:15:29.201Z        bed25b38-d012-42e7-ba28-f272535fb80e    info   {"_aws":{"Timestamp":1676902528962,"CloudWatchMetrics":[{"Namespace":"sam-app-logging","Metrics":[{"Name":"ColdStart","Unit":"Count"}],"Dimensions":[["FunctionName"],["Service"]]}]},"FunctionName":"sam-app-HelloWorldFunction-haKIoVeose2p","Service":"PowertoolsHelloWorld","ColdStart":1}
   2025/02/20/[$LATEST]4eaf8445ba7a4a93b999cb17fbfbecd8 2025-09-20T14:15:30.479000 2025-09-20T14:15:30.479Z        bed25b38-d012-42e7-ba28-f272535fb80e    info   {"ColdStart":true,"XrayTraceId":"1-63f3807f-5dbcb9910c96f50742707542","CorrelationId":"d3d4de7f-4ccc-411a-a549-4d67b2fdc015","FunctionName":"sam-app-HelloWorldFunction-haKIoVeose2p","FunctionVersion":"$LATEST","FunctionMemorySize":256,"FunctionArn":"arn:aws:lambda:ap-southeast-2:123456789012:function:sam-app-HelloWorldFunction-haKIoVeose2p","FunctionRequestId":"bed25b38-d012-42e7-ba28-f272535fb80e","Timestamp":"2025-09-20T14:15:30.4602970Z","Level":"Information","Service":"PowertoolsHelloWorld","Name":"AWS.Lambda.Powertools.Logging.Logger","Message":"Hello world API - HTTP 200"}
   2025/02/20/[$LATEST]4eaf8445ba7a4a93b999cb17fbfbecd8 2025-09-20T14:15:30.599000 2025-09-20T14:15:30.599Z        bed25b38-d012-42e7-ba28-f272535fb80e    info   {"_aws":{"Timestamp":1676902528922,"CloudWatchMetrics":[{"Namespace":"sam-app-logging","Metrics":[{"Name":"ApiRequestCount","Unit":"Count"}],"Dimensions":[["Service"]]}]},"Service":"PowertoolsHelloWorld","ApiRequestCount":1}
   2025/02/20/[$LATEST]4eaf8445ba7a4a93b999cb17fbfbecd8 2025-09-20T14:15:30.680000 END RequestId: bed25b38-d012-42e7-ba28-f272535fb80e
   2025/02/20/[$LATEST]4eaf8445ba7a4a93b999cb17fbfbecd8 2025-09-20T14:15:30.680000 REPORT RequestId: bed25b38-d012-42e7-ba28-f272535fb80e  Duration: 2450.99 ms   Billed Duration: 2692 ms Memory Size: 256 MB     Max Memory Used: 74 MB  Init Duration: 240.05 ms
   XRAY TraceId: 1-63f3807f-5dbcb9910c96f50742707542       SegmentId: 16b362cd5f52cba0
   ```

1. 이는 인터넷을 통해 액세스할 수 있는 퍼블릭 API 엔드포인트입니다. 테스트 후에는 엔드포인트를 삭제하는 것이 좋습니다.

   ```
   sam delete
   ```

### 로그 보존 관리
<a name="csharp-log-retention"></a>

함수를 삭제해도 로그 그룹이 자동으로 삭제되지 않습니다. 로그를 무기한 저장하지 않으려면 로그 그룹을 삭제하거나 경과 후 CloudWatch가 로그를 자동으로 삭제하는 보존 기간을 구성하세요. 로그 보존을 설정하려면 AWS SAM 템플릿에 다음을 추가합니다.

```
Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      # Omitting other properties

  LogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub "/aws/lambda/${HelloWorldFunction}"
      RetentionInDays: 7
```

## Lambda 콘솔에서 로그 보기
<a name="csharp-logging-console"></a>

Lambda 함수를 간접 호출한 후 Lambda 콘솔을 사용하여 로그 출력을 볼 수 있습니다.

포함된 **코드** 편집기에서 코드를 테스트할 수 있는 경우 **실행 결과**에서 로그를 찾을 수 있습니다. 콘솔 테스트 기능을 사용하여 함수를 간접적으로 간접 호출하면 **세부 정보** 섹션에서 **로그 출력**을 찾을 수 있습니다.

## CloudWatch 콘솔에서 로그 보기
<a name="csharp-logging-cwconsole"></a>

Amazon CloudWatch 콘솔을 사용하여 모든 Lambda 함수 호출에 대한 로그를 볼 수 있습니다.

**CloudWatch 콘솔에서 로그를 보려면**

1. CloudWatch 콘솔에서 [로그 그룹 페이지](https://console.aws.amazon.com/cloudwatch/home?#logs:)를 엽니다.

1. 함수(**/aws/lambda/*your-function-name***)에 대한 로그 그룹을 선택합니다.

1. 로그 스트림을 선택합니다.

각 로그 스트림은 [함수의 인스턴스](lambda-runtime-environment.md)에 해당합니다. 로그 스트림은 Lambda 함수를 업데이트할 때, 그리고 동시 호출을 처리하기 위해 추가 인스턴스가 생성될 때 나타납니다. 특정 호출에 대한 로그를 찾으려면 AWS X-Ray로 함수를 계측하는 것이 좋습니다. X-Ray는 요청 및 로그 스트림에 대한 세부 정보를 기록합니다.

## AWS Command Line Interface(AWS CLI)(을)를 사용하여 로그 보기
<a name="csharp-logging-cli"></a>

AWS CLI은(는) 명령줄 셸의 명령을 사용하여 AWS 서비스와 상호 작용할 수 있는 오픈 소스 도구입니다. 이 섹션의 단계를 완료하려면 [AWS CLI 버전 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)가 필요합니다.

[AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html)를 사용하면 `--log-type` 명령 옵션을 통해 호출에 대한 로그를 검색할 수 있습니다. 호출에서 base64로 인코딩된 로그를 최대 4KB까지 포함하는 `LogResult` 필드가 응답에 포함됩니다.

**Example 로그 ID 검색**  
다음 예제에서는 `LogResult`이라는 함수의 `my-function` 필드에서 *로그 ID*를 검색하는 방법을 보여줍니다.  

```
aws lambda invoke --function-name my-function out --log-type Tail
```
다음 결과가 표시됩니다:  

```
{
    "StatusCode": 200,
    "LogResult": "U1RBUlQgUmVxdWVzdElkOiA4N2QwNDRiOC1mMTU0LTExZTgtOGNkYS0yOTc0YzVlNGZiMjEgVmVyc2lvb...",
    "ExecutedVersion": "$LATEST"
}
```

**Example decode the logs**  
동일한 명령 프롬프트에서 `base64` 유틸리티를 사용하여 로그를 디코딩합니다. 다음 예제에서는 `my-function`에 대한 base64로 인코딩된 로그를 검색하는 방법을 보여줍니다.  

```
aws lambda invoke --function-name my-function out --log-type Tail \
--query 'LogResult' --output text --cli-binary-format raw-in-base64-out | base64 --decode
```
**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)을 참조하세요.  
다음 결과가 표시됩니다.  

```
START RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8 Version: $LATEST
"AWS_SESSION_TOKEN": "AgoJb3JpZ2luX2VjELj...", "_X_AMZN_TRACE_ID": "Root=1-5d02e5ca-f5792818b6fe8368e5b51d50;Parent=191db58857df8395;Sampled=0"",ask/lib:/opt/lib",
END RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8
REPORT RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8  Duration: 79.67 ms      Billed Duration: 80 ms         Memory Size: 128 MB     Max Memory Used: 73 MB
```
`base64` 유틸리티는 Linux, macOS 및 [Ubuntu on Windows](https://docs.microsoft.com/en-us/windows/wsl/install-win10)에서 사용할 수 있습니다. macOS 사용자는 `base64 -D`를 사용해야 할 수도 있습니다.

**Example get-logs.sh 스크립트**  
동일한 명령 프롬프트에서 다음 스크립트를 사용하여 마지막 5개 로그 이벤트를 다운로드합니다. 이 스크립트는 `sed`를 사용하여 출력 파일에서 따옴표를 제거하고, 로그를 사용할 수 있는 시간을 허용하기 위해 15초 동안 대기합니다. 출력에는 Lambda의 응답과 `get-log-events` 명령의 출력이 포함됩니다.  
다음 코드 샘플의 내용을 복사하고 Lambda 프로젝트 디렉터리에 `get-logs.sh`로 저장합니다.  
**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)을 참조하세요.  

```
#!/bin/bash
aws lambda invoke --function-name my-function --cli-binary-format raw-in-base64-out --payload '{"key": "value"}' out
sed -i'' -e 's/"//g' out
sleep 15
aws logs get-log-events --log-group-name /aws/lambda/my-function --log-stream-name stream1 --limit 5
```

**Example macOS 및 Linux(전용)**  
동일한 명령 프롬프트에서 macOS 및 Linux 사용자는 스크립트가 실행 가능한지 확인하기 위해 다음 명령을 실행해야 할 수 있습니다.  

```
chmod -R 755 get-logs.sh
```

**Example 마지막 5개 로그 이벤트 검색**  
동일한 명령 프롬프트에서 다음 스크립트를 실행하여 마지막 5개 로그 이벤트를 가져옵니다.  

```
./get-logs.sh
```
다음 결과가 표시됩니다:  

```
{
    "StatusCode": 200,
    "ExecutedVersion": "$LATEST"
}
{
    "events": [
        {
            "timestamp": 1559763003171,
            "message": "START RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf Version: $LATEST\n",
            "ingestionTime": 1559763003309
        },
        {
            "timestamp": 1559763003173,
            "message": "2019-06-05T19:30:03.173Z\t4ce9340a-b765-490f-ad8a-02ab3415e2bf\tINFO\tENVIRONMENT VARIABLES\r{\r  \"AWS_LAMBDA_FUNCTION_VERSION\": \"$LATEST\",\r ...",
            "ingestionTime": 1559763018353
        },
        {
            "timestamp": 1559763003173,
            "message": "2019-06-05T19:30:03.173Z\t4ce9340a-b765-490f-ad8a-02ab3415e2bf\tINFO\tEVENT\r{\r  \"key\": \"value\"\r}\n",
            "ingestionTime": 1559763018353
        },
        {
            "timestamp": 1559763003218,
            "message": "END RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf\n",
            "ingestionTime": 1559763018353
        },
        {
            "timestamp": 1559763003218,
            "message": "REPORT RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf\tDuration: 26.73 ms\tBilled Duration: 27 ms \tMemory Size: 128 MB\tMax Memory Used: 75 MB\t\n",
            "ingestionTime": 1559763018353
        }
    ],
    "nextForwardToken": "f/34783877304859518393868359594929986069206639495374241795",
    "nextBackwardToken": "b/34783877303811383369537420289090800615709599058929582080"
}
```

## 로그 삭제
<a name="csharp-logging-delete"></a>

함수를 삭제해도 로그 그룹이 자동으로 삭제되지 않습니다. 로그를 무기한 저장하지 않으려면 로그 그룹을 삭제하거나 로그가 자동으로 삭제되는 [보존 기간을 구성](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/Working-with-log-groups-and-streams.html#SettingLogRetention)하세요.

# AWS Lambda에서 C\$1 코드 계측
<a name="csharp-tracing"></a>

Lambda는 AWS X-Ray와 통합되어 Lambda 애플리케이션을 추적, 디버깅 및 최적화할 수 있습니다. Lambda 함수와 기타 AWS 서비스를 포함할 수 있는 애플리케이션의 리소스를 탐색할 때 X-Ray를 사용하여 요청을 추적할 수 있습니다.

추적 데이터를 X-Ray로 전송하려면 다음 세 SDK 라이브러리 중 하나를 사용할 수 있습니다.
+ [AWS Distro for OpenTelemetry(ADOT)](https://aws.amazon.com/otel) - 안전하게 프로덕션 준비가 된 AWS에서 지원하는 OpenTelemetry(OTEL) SDK의 배포입니다.
+ [AWS X-Ray SDK for .NET](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-dotnet.html) — 추적 데이터를 생성하고 X-Ray에 전송하는 SDK입니다.
+ [Powertools for AWS Lambda(.NET)](https://docs.aws.amazon.com/powertools/dotnet/) – 서버리스 모범 사례를 구현하고 개발자 속도를 높이기 위한 개발자 도구 키트입니다.

각 SDK는 텔레메트리 데이터를 X-Ray 서비스로 전송하는 방법을 제공합니다. X-Ray를 사용하여 애플리케이션의 성능 지표를 확인하고, 필터링하고, 인사이트를 얻어 문제와 최적화 기회를 식별할 수 있습니다.

**중요**  
X-Ray와 Powertools for AWS Lambda SDK는 AWS에서 제공하는 긴밀하게 통합된 계측 솔루션의 일부입니다. ADOT Lambda Layer는 일반적으로 더 많은 데이터를 수집하는 추적 계측기에 대한 전체 업계 표준의 일부이지만 모든 사용 사례에 적합하지는 않을 수 있습니다. 어떤 솔루션을 사용하든 X-Ray에서 엔드 투 엔드 추적 기능을 구현할 수 있습니다. 둘 중 하나를 선택하는 방법에 대해 자세히 알아보려면 [AWS Distro for Open Telemetry와 X-Ray SDK 중에서 선택하기](https://docs.aws.amazon.com/xray/latest/devguide/xray-instrumenting-your-app.html#xray-instrumenting-choosing)를 참조하세요.

**Topics**
+ [

## 추적에 Powertools for AWS Lambda(.NET) 및 AWS SAM 사용
](#dotnet-tracing-sam)
+ [

## X-Ray SDK를 사용하여 .NET 함수 계측
](#dotnet-xray-sdk)
+ [

## Lambda 콘솔을 사용하여 추적 활성화
](#dotnet-tracing-console)
+ [

## Lambda API를 사용하여 추적 활성화
](#dotnet-tracing-api)
+ [

## CloudFormation을 사용하여 추적 활성화
](#dotnet-tracing-cloudformation)
+ [

## X-Ray 추적 해석
](#dotnet-tracing-interpretation)

## 추적에 Powertools for AWS Lambda(.NET) 및 AWS SAM 사용
<a name="dotnet-tracing-sam"></a>

다음 단계를 따라 AWS SAM을 사용하는 통합 [Powertools for AWS Lambda(.NET)](https://docs.powertools.aws.dev/lambda-dotnet) 모듈을 사용하여 샘플 Hello World C\$1 애플리케이션을 다운로드, 빌드 및 배포합니다. 이 애플리케이션은 기본 API 백엔드를 구현하고 Powertools를 사용하여 로그, 지표 및 추적을 내보냅니다. 이 구성에는 Amazon API Gateway 엔드포인트와 Lambda 함수가 포함됩니다. API Gateway 엔드포인트로 GET 요청을 전송하면 Lambda 함수가 간접 호출되고 Embedded Metric Format을 사용하여 로그 및 지표를 CloudWatch로 전송하고 기록을 AWS X-Ray로 전송합니다. 함수가 hello world 메시지를 반환합니다.

**사전 조건**

이 섹션의 단계를 완료하려면 다음이 필요합니다.
+ .NET 8
+ [AWS CLI 버전 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ [AWS SAM CLI 버전 1.75 이상](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html). 이전 버전의 AWS SAM CLI가 있는 경우 [AWS SAM CLI 업그레이드](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/manage-sam-cli-versions.html#manage-sam-cli-versions-upgrade)를 참조하세요.

**샘플 AWS SAM 애플리케이션 배포**

1. Hello World TypeScript 템플릿을 사용하여 애플리케이션을 초기화합니다.

   ```
   sam init --app-template hello-world-powertools-dotnet --name sam-app --package-type Zip --runtime dotnet6 --no-tracing
   ```

1. 앱을 빌드합니다.

   ```
   cd sam-app && sam build
   ```

1. 앱을 배포합니다.

   ```
   sam deploy --guided
   ```

1. 화면에 표시되는 프롬프트를 따릅니다. 대화형 환경에서 제공되는 기본 옵션을 수락하려면 `Enter`을 누릅니다.
**참고**  
**HelloWorldFunction에 권한 부여가 정의되어 있지 않을 수 있습니다. 괜찮습니다?**에 대해 `y`를 입력합니다.

1. 배포된 애플리케이션의 URL을 가져옵니다.

   ```
   aws cloudformation describe-stacks --stack-name sam-app --query 'Stacks[0].Outputs[?OutputKey==`HelloWorldApi`].OutputValue' --output text
   ```

1. API 엔드포인트 간접 호출:

   ```
   curl <URL_FROM_PREVIOUS_STEP>
   ```

   성공하면 다음과 같은 결과가 응답됩니다.

   ```
   {"message":"hello world"}
   ```

1. 함수에 대한 트레이스를 가져오려면 [sam traces](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-traces.html)를 실행합니다.

   ```
   sam traces
   ```

   추적 출력은 다음과 같습니다.

   ```
   New XRay Service Graph
     Start time: 2023-02-20 23:05:16+08:00
     End time: 2023-02-20 23:05:16+08:00
     Reference Id: 0 - AWS::Lambda - sam-app-HelloWorldFunction-pNjujb7mEoew - Edges: [1]
      Summary_statistics:
        - total requests: 1
        - ok count(2XX): 1
        - error count(4XX): 0
        - fault count(5XX): 0
        - total response time: 2.814
     Reference Id: 1 - AWS::Lambda::Function - sam-app-HelloWorldFunction-pNjujb7mEoew - Edges: []
      Summary_statistics:
        - total requests: 1
        - ok count(2XX): 1
        - error count(4XX): 0
        - fault count(5XX): 0
        - total response time: 2.429
     Reference Id: 2 - (Root) AWS::ApiGateway::Stage - sam-app/Prod - Edges: [0]
      Summary_statistics:
        - total requests: 1
        - ok count(2XX): 1
        - error count(4XX): 0
        - fault count(5XX): 0
        - total response time: 2.839
     Reference Id: 3 - client - sam-app/Prod - Edges: [2]
      Summary_statistics:
        - total requests: 0
        - ok count(2XX): 0
        - error count(4XX): 0
        - fault count(5XX): 0
        - total response time: 0
   
   XRay Event [revision 3] at (2023-02-20T23:05:16.521000) with id (1-63f38c2c-270200bf1d292a442c8e8a00) and duration (2.877s)
    - 2.839s - sam-app/Prod [HTTP: 200]
      - 2.836s - Lambda [HTTP: 200]
    - 2.814s - sam-app-HelloWorldFunction-pNjujb7mEoew [HTTP: 200]
    - 2.429s - sam-app-HelloWorldFunction-pNjujb7mEoew
      - 0.230s - Initialization
      - 2.389s - Invocation
        - 0.600s - ## FunctionHandler
          - 0.517s - Get Calling IP
      - 0.039s - Overhead
   ```

1. 이는 인터넷을 통해 액세스할 수 있는 퍼블릭 API 엔드포인트입니다. 테스트 후에는 엔드포인트를 삭제하는 것이 좋습니다.

   ```
   sam delete
   ```

X-Ray는 애플리케이션에 대한 모든 요청을 추적하지 않습니다. X-Ray는 모든 요청의 대표 샘플을 여전히 제공하면서 추적이 효율적으로 수행되도록 샘플링 알고리즘을 적용합니다. 샘플링 요율은 초당 요청이 1개이며 추가 요청의 5퍼센트입니다. 함수에 대해 X-Ray 샘플링 요율을 구성할 수 없습니다.

## X-Ray SDK를 사용하여 .NET 함수 계측
<a name="dotnet-xray-sdk"></a>

함수 코드를 계측하여 메타데이터를 기록하고 다운스트림 호출을 추적할 수 있습니다. 함수가 다른 리소스 및 서비스에 대해 수행하는 호출과 관련된 세부 정보를 기록하려면 AWS X-Ray SDK for .NET을(를) 사용합니다. SDK를 가져오려면 프로젝트 파일에 `AWSXRayRecorder` 패키지를 추가합니다.

```
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
    <AWSProjectType>Lambda</AWSProjectType>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Amazon.Lambda.Core" Version="2.1.0" />
    <PackageReference Include="Amazon.Lambda.SQSEvents" Version="2.1.0" />
    <PackageReference Include="Amazon.Lambda.Serialization.Json" Version="2.1.0" />
    <PackageReference Include="AWSSDK.Core" Version="3.7.103.24" />
    <PackageReference Include="AWSSDK.Lambda" Version="3.7.104.3" />
    <PackageReference Include="AWSXRayRecorder.Core" Version="2.13.0" />
    <PackageReference Include="AWSXRayRecorder.Handlers.AwsSdk" Version="2.11.0" />
  </ItemGroup>
</Project>
```

AWS SDK, 엔터티 프레임워크 및 HTTP 요청에 대한 자동 계측을 제공하는 다양한 Nuget 패키지가 있습니다. *전체 구성 옵션 세트를 확인하려면 AWS X-Ray 개발자 안내서*의 [.NET용 AWS X-Ray SDK](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-dotnet.html)를 참조하십시오.

원하는 Nuget 패키지를 추가한 후 자동 계측을 구성하십시오. 함수의 핸들러 함수 외부에서 이 구성을 수행하는 것이 좋습니다. 실행 환경 재사용을 활용하여 함수 성능을 향상시킬 수 있습니다. 다음 코드 예제에서는 함수 생성자에서 `RegisterXRayForAllServices` 메서드를 호출하여 모든 AWS SDK 호출에 대한 계측을 추가합니다.

```
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace GetProductHandler;

public class Function
{
    private readonly IDatabaseRepository _repo;
    
    public Function()
    {
        // Add auto instrumentation for all AWS SDK calls
        // It is important to call this method before initializing any SDK clients
        AWSSDKHandler.RegisterXRayForAllServices();
        this._repo = new DatabaseRepository();
    }
    
    public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest request)
    {
        var id = request.PathParameters["id"];
        
        var databaseRecord = await this._repo.GetById(id);
        
        return new APIGatewayProxyResponse 
        {
            StatusCode = (int)HttpStatusCode.OK,
            Body = JsonSerializer.Serialize(databaseRecord)
        };
    }
}
```

## Lambda 콘솔을 사용하여 추적 활성화
<a name="dotnet-tracing-console"></a>

콘솔을 사용하여 Lambda 함수에 대한 활성 추적을 전환하려면 다음 단계를 따르십시오.

**활성 추적 켜기**

1. Lambda 콘솔의 [함수 페이지](https://console.aws.amazon.com/lambda/home#/functions)를 엽니다.

1. 함수를 선택합니다.

1. **구성(Configuration)**을 선택한 다음 **모니터링 및 운영 도구(Monitoring and operations tools)**를 선택합니다.

1. **추가 모니터링 도구**에서 **편집**을 선택합니다.

1. **CloudWatch 애플리케이션 신호 및 AWS X-Ray**에서 **Lambda 서비스 트레이스**에 대해 **활성화**를 선택합니다.

1. **저장**을 선택합니다.

## Lambda API를 사용하여 추적 활성화
<a name="dotnet-tracing-api"></a>

AWS CLI 또는 AWS SDK를 사용하여 Lambda 함수에 대한 추적을 구성하고 다음 API 작업을 사용합니다.
+ [UpdateFunctionConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionConfiguration.html)
+ [GetFunctionConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_GetFunctionConfiguration.html)
+ [CreateFunction](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html)

다음 예제 AWS CLI 명령은 **my-function**이라는 함수에 대한 활성 추적을 사용 설정합니다.

```
aws lambda update-function-configuration --function-name my-function \
--tracing-config Mode=Active
```

추적 모드는 함수 버전을 게시할 때 버전별 구성의 일부입니다. 게시된 버전에 대한 추적 모드는 변경할 수 없습니다.

## CloudFormation을 사용하여 추적 활성화
<a name="dotnet-tracing-cloudformation"></a>

CloudFormation 템플릿에서 `AWS::Lambda::Function` 리소스에 대한 추적을 활성화하려면 `TracingConfig` 속성을 사용합니다.

**Example [function-inline.yml](https://github.com/awsdocs/aws-lambda-developer-guide/blob/master/templates/function-inline.yml) – 추적 구성**  

```
Resources:
  function:
    Type: [AWS::Lambda::Function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html)
    Properties:
      TracingConfig:
        Mode: Active
      ...
```

AWS Serverless Application Model(AWS SAM) `AWS::Serverless::Function` 리소스의 경우 `Tracing` 속성을 사용합니다.

**Example [template.yml](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/blank-nodejs/template.yml) – 추적 구성**  

```
Resources:
  function:
    Type: [AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html)
    Properties:
      Tracing: Active
      ...
```

## X-Ray 추적 해석
<a name="dotnet-tracing-interpretation"></a>

함수에 추적 데이터를 X-Ray로 업로드할 권한이 있어야 합니다. Lambda 콘솔에서 추적을 활성화하면 Lambda가 필요한 권한을 함수의 [실행 역할](lambda-intro-execution-role.md)에 추가합니다. 그렇지 않으면 실행 역할에 [AWSXRayDaemonWriteAccess](https://console.aws.amazon.com/iam/home#/policies/arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess) 정책을 추가합니다.

활성 추적을 구성하면 애플리케이션을 통해 특정 요청을 관찰할 수 있습니다. [ X-Ray 서비스 그래프](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html#xray-concepts-servicegraph)는 애플리케이션 및 모든 구성 요소에 대한 정보를 보여줍니다. 다음 예제에서는 2개의 함수가 있는 애플리케이션을 보여줍니다. 기본 함수는 이벤트를 처리하고 때로는 오류를 반환합니다. 맨 위의 두 번째 함수는 첫 번째의 로그 그룹에 나타나는 오류를 처리하고 AWS SDK를 사용하여 X-Ray, Amazon Simple Storage Service(Amazon S3), Amazon CloudWatch Logs를 호출합니다.

![\[\]](http://docs.aws.amazon.com/ko_kr/lambda/latest/dg/images/sample-errorprocessor-servicemap.png)


X-Ray는 애플리케이션에 대한 모든 요청을 추적하지 않습니다. X-Ray는 모든 요청의 대표 샘플을 여전히 제공하면서 추적이 효율적으로 수행되도록 샘플링 알고리즘을 적용합니다. 샘플링 요율은 초당 요청이 1개이며 추가 요청의 5퍼센트입니다. 함수에 대해 X-Ray 샘플링 요율을 구성할 수 없습니다.

X-Ray에서 *추적*은 하나 이상의 *서비스*에서 처리되는 요청에 대한 정보를 기록합니다. Lambda는 각 추적에 대해 2개의 세그먼트를 기록하고, 이에 따라 서비스 그래프에 2개의 노드가 생성됩니다. 다음 이미지에서는 이 두 노드를 강조 표시합니다.

![\[\]](http://docs.aws.amazon.com/ko_kr/lambda/latest/dg/images/xray-servicemap-function.png)


왼쪽의 첫 번째 노드는 호출 요청을 수신하는 Lambda 서비스를 나타냅니다. 두 번째 노드는 특정 Lambda 함수를 나타냅니다. 다음 예에서는 이러한 2개의 세그먼트가 있는 추적을 보여줍니다. 둘 다 이름이 **my-function** 이지만 하나는 오리진이 `AWS::Lambda`이고 다른 하나는 오리진이 `AWS::Lambda::Function`입니다. `AWS::Lambda` 세그먼트에 오류가 표시되면 Lambda 서비스에 문제가 있는 것입니다. `AWS::Lambda::Function` 세그먼트에 오류가 표시되면 함수에 문제가 있는 것입니다.

![\[\]](http://docs.aws.amazon.com/ko_kr/lambda/latest/dg/images/V2_sandbox_images/my-function-2-v1.png)


이 예제에서는 3개의 하위 세그먼트를 표시하도록 `AWS::Lambda::Function` 세그먼트를 확장합니다.

**참고**  
AWS는 현재 Lambda 서비스에 대한 변경 사항을 구현하고 있습니다. 이러한 변경으로 인해, AWS 계정의 여러 Lambda 함수에서 내보내는 시스템 로그 메시지와 추적 세그먼트의 구조와 내용 간에 약간의 차이가 있을 수 있습니다.  
여기에 표시된 예제 트레이스는 이전 스타일의 함수 세그먼트를 보여줍니다. 이전 스타일 세그먼트와 새로운 스타일 세그먼트의 차이점은 다음 단락들에 설명되어 있습니다.  
이러한 변경 사항은 앞으로 몇 주 동안 구현되며, 중국 및 GovCloud 리전을 제외한 모든 AWS 리전의 모든 기능은 새로운 형식의 로그 메시지 및 추적 세그먼트를 사용하도록 전환됩니다.

이전 스타일의 함수 세그먼트에는 다음과 같은 하위 세그먼트가 포함됩니다.
+ **초기화** – 함수를 로드하고 [초기화 코드](foundation-progmodel.md)를 실행하는 데 소요된 시간을 나타냅니다. 이 하위 세그먼트는 함수의 각 인스턴스에서 처리하는 첫 번째 이벤트에 대해서만 표시됩니다.
+ **호출**— 핸들러 코드를 실행하는 데 소요된 시간을 나타냅니다.
+ **오버헤드** – Lambda 런타임이 다음 이벤트를 처리하기 위해 준비하는 데 소비하는 시간을 나타냅니다.

새로운 스타일의 함수 세그먼트에는 `Invocation` 하위 세그먼트가 포함되지 않습니다. 대신, 고객 하위 세그먼트는 함수 세그먼트에 직접 연결됩니다. 이전 스타일과 새로운 스타일의 함수 세그먼트의 구조에 대한 자세한 내용은 [X-Ray 추적 이해](services-xray.md#services-xray-traces)를 참조하세요.

HTTP 클라이언트를 계측하고, SQL 쿼리를 기록하고, 주석 및 메타데이터가 있는 사용자 지정 하위 세그먼트를 생성할 수도 있습니다. 자세한 내용은 *AWS X-Ray 개발자 안내서*의 [AWS X-Ray SDK for .NET](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-dotnet.html)를 참조하십시오.

**가격 책정**  
X-Ray 추적을 AWS 프리 티어의 일부로서 특정 한도까지 매월 무료로 사용할 수 있습니다. 해당 한도를 초과하면 추적 저장 및 검색에 대한 X-Ray 요금이 부과됩니다. 자세한 내용은 [AWS X-Ray 요금](https://aws.amazon.com/xray/pricing/)을 참조하십시오.

# C\$1의 AWS Lambda 함수 테스트
<a name="dotnet-csharp-testing"></a>

**참고**  
서버리스 솔루션 테스트를 위한 기술 및 모범 사례에 대한 전체 소개는 [함수 테스트](testing-guide.md) 장을 참조하세요.

 서버리스 함수 테스트는 기존 테스트 유형과 기법을 사용하지만, 서버리스 애플리케이션을 전체적으로 테스트하는 것도 고려해야 합니다. 클라우드 기반 테스트는 함수와 서버리스 애플리케이션 모두의 품질을 **가장 정확하게** 측정합니다.

 서버리스 애플리케이션 아키텍처에는 API 호출을 통해 중요한 애플리케이션 기능을 제공하는 관리형 서비스가 포함됩니다. 따라서 개발 주기에는 함수와 서비스가 상호 작용할 때 기능을 확인하는 자동화된 테스트가 포함되어야 합니다.

 클라우드 기반 테스트를 생성하지 않으면 로컬 환경과 배포된 환경 간의 차이로 인해 문제가 발생할 수 있습니다. 지속적 통합 프로세스는 QA, 스테이징 또는 프로덕션과 같은 다음 배포 환경으로 코드를 승격하기 전에 클라우드에서 프로비저닝되는 리소스 제품군을 대상으로 테스트를 실행해야 합니다.

 이 짧은 안내서를 계속 읽고 서버리스 애플리케이션의 테스트 전략에 대해 알아보거나 [Serverless Test Samples 리포지토리](https://github.com/aws-samples/serverless-test-samples)를 방문하여 선택한 언어 및 런타임과 관련된 실제 예제를 자세히 살펴보세요.

 ![\[illustration showing the relationship between types of tests\]](http://docs.aws.amazon.com/ko_kr/lambda/latest/dg/images/test-type-illustration2.png) 

 서버리스 테스트의 경우에도 *단위*, *통합* 및 *엔드 투 엔드* 테스트를 작성합니다.
+ **단위 테스트** - 격리된 코드 블록에 대해 실행되는 테스트입니다. 예를 들어, 특정 항목과 대상에 대한 배송료를 계산하는 비즈니스 로직을 확인합니다.
+ **통합 테스트** - 일반적으로 클라우드 환경에서 상호 작용하는 둘 이상의 구성 요소 또는 서비스를 포함하는 테스트입니다. 예를 들어, 함수가 대기열에서 이벤트를 처리하는지 확인합니다.
+ **엔드 투 엔드 테스트** - 전체 애플리케이션의 동작을 확인하는 테스트입니다. 예를 들어, 인프라가 올바르게 설정되어 있고 고객의 주문 기록을 위해 예상대로 서비스 간에 이벤트가 흐르는지 확인합니다.

## 서버리스 애플리케이션 테스트
<a name="dotnet-csharp-testing-techniques-for-serverless-applications"></a>

 일반적으로 다양한 접근 방식을 사용하여 클라우드에서 테스트, 모의 객체로 테스트, 에뮬레이터로 테스트 등의 서버리스 애플리케이션 코드 테스트를 수행합니다.

### 클라우드에서 테스트
<a name="dotnet-csharp-testing-in-the-cloud"></a>

 클라우드에서 테스트는 단위 테스트, 통합 테스트, 엔드 투 엔드 테스트 등의 모든 테스트 단계에서 중요합니다. 클라우드에 배포되고 클라우드 기반 서비스와 상호 작용하는 코드에 대해 테스트를 실행합니다. 이 접근 방식은 코드 품질을 **가장 정확하게** 측정합니다.

 클라우드에서 Lambda 함수를 디버깅하는 편리한 방법은 테스트 이벤트와 콘솔을 이용하는 것입니다. *테스트 이벤트*는 함수에 대한 JSON 입력입니다. 함수에 입력이 필요하지 않은 경우 이벤트는 빈 JSON 문서(`({})`)가 될 수 있습니다. 콘솔은 다양한 서비스 통합을 위한 샘플 이벤트를 제공합니다. 콘솔에서 이벤트를 생성한 후 팀과 공유하여 테스트를 더 쉽고 일관성 있게 만들 수 있습니다.

**참고**  
[콘솔에서 함수를 테스트](testing-functions.md)하는 것이 빠르게 시작할 수 있는 방법이지만 테스트 주기를 자동화하면 애플리케이션 품질과 개발 속도가 보장됩니다.

### 테스트 도구
<a name="dotnet-csharp-testing-tools"></a>

개발 주기를 가속화하기 위해 함수를 테스트할 때 사용할 수 있는 다양한 도구와 기법이 있습니다. 예를 들어, [AWS SAM 가속화](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/using-sam-cli-sync.html)와 [AWS CDK 감시 모드](https://docs.aws.amazon.com/cdk/v2/guide/cli.html#cli-deploy-watch) 모두 클라우드 환경을 업데이트하는 데 필요한 시간을 줄입니다.

Lambda 함수 코드를 정의하는 방법에 따라 단위 테스트를 간단하게 추가할 수 있습니다. Lambda는 클래스를 초기화하기 위해 파라미터가 없는 퍼블릭 생성자가 필요합니다. 두 번째 내부 생성자를 도입하면 애플리케이션이 사용하는 종속성을 제어할 수 있습니다.

```
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace GetProductHandler;

public class Function
{
    private readonly IDatabaseRepository _repo;
    
    public Function(): this(null)
    {
    }
    
    internal Function(IDatabaseRepository repo)
    {
        this._repo = repo ?? new DatabaseRepository();
    }
    
    public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest request)
    {
        var id = request.PathParameters["id"];
        
        var databaseRecord = await this._repo.GetById(id);
        
        return new APIGatewayProxyResponse 
        {
            StatusCode = (int)HttpStatusCode.OK,
            Body = JsonSerializer.Serialize(databaseRecord)
        };
    }
}
```

이 함수에 대한 테스트를 작성하려면 `Function` 클래스의 새 인스턴스를 초기화하고 `IDatabaseRepository`의 모의 구현을 전달하면 됩니다. 아래 예제에서는 `XUnit`, `Moq`, 및 `FluentAssertions`을(를) 사용하여 `FunctionHandler`이(가) 200 상태 코드를 반환하는지 확인하는 간단한 테스트를 작성합니다.

```
using Xunit;
using Moq;
using FluentAssertions;

public class FunctionTests
{
    [Fact]
    public async Task TestLambdaHandler_WhenInputIsValid_ShouldReturn200StatusCode()
    {
        // Arrange
        var mockDatabaseRepository = new Mock<IDatabaseRepository>();
        
        var functionUnderTest = new Function(mockDatabaseRepository.Object);
        
        // Act
        var response = await functionUnderTest.FunctionHandler(new APIGatewayProxyRequest());
        
        // Assert
        response.StatusCode.Should().Be(200);
    }
}
```

비동기 테스트의 예를 비롯한 자세한 예제는 GitHub의 [.NET 테스트 샘플 리포지토리](https://github.com/aws-samples/serverless-test-samples/tree/main/dotnet-test-samples)를 참조하십시오.