

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

Node.js 런타임을 사용하여 AWS Lambda에서 TypeScript 코드를 실행할 수 있습니다. Node.js 는 기본적으로 TypeScript 코드를 실행하지 않으므로 먼저 TypeScript 코드를 JavaScript로 트랜스파일해야 합니다. 그런 다음 JavaScript 파일을 사용하여 함수 코드를 Lambda에 배포합니다. 코드는 사용자가 관리하는 AWS Identity and Access Management(IAM) 역할의 자격 증명을 사용하여 JavaScript용 AWS SDK가 포함된 환경에서 실행됩니다. Node.js 런타임에 포함된 SDK 버전에 대해 자세히 알아보려면 [런타임에 포함된 SDK 버전](lambda-nodejs.md#nodejs-sdk-included) 섹션을 참조하세요.

Lambda는 다음과 같은 Node.js 런타임을 지원합니다.


| 이름 | 식별자 | 운영 체제 | 사용 중단 날짜 | 블록 함수 생성 | 블록 함수 업데이트 | 
| --- | --- | --- | --- | --- | --- | 
|  Node.js 24  |  `nodejs24.x`  |  Amazon Linux 2023  |   2028년 4월 30일   |   2028년 6월 1일   |   2028년 7월 1일   | 
|  Node.js 22  |  `nodejs22.x`  |  Amazon Linux 2023  |   2027년 4월 30일   |   2027년 6월 1일   |   2027년 7월 1일   | 
|  Node.js 20  |  `nodejs20.x`  |  Amazon Linux 2023  |   2026년 4월 30일   |   2026년 8월 31일   |   2026년 9월 30일   | 

**Topics**
+ [TypeScript 개발 환경 설정](#typescript-dev)
+ [Lambda에 대한 유형 정의](#typescript-type-definitions)
+ [TypeScript에서 Lambda 함수 핸들러 정의](typescript-handler.md)
+ [.zip 파일 아카이브를 사용하여 Lambda에 트랜스파일된 TypeScript 코드 배포](typescript-package.md)
+ [컨테이너 이미지를 사용하여 Lambda에 트랜스파일된 TypeScript 코드 배포](typescript-image.md)
+ [Lambda 컨텍스트 객체를 사용하여 TypeScript 함수 정보 검색](typescript-context.md)
+ [TypeScript Lambda 함수 로깅 및 모니터링](typescript-logging.md)
+ [AWS Lambda에서 TypeScript 코드 추적](typescript-tracing.md)

## TypeScript 개발 환경 설정
<a name="typescript-dev"></a>

로컬 통합 개발 환경(IDE) 또는 텍스트 편집기를 사용하여 TypeScript 함수 코드를 작성합니다. Lambda 콘솔에서는 TypeScript 코드를 생성할 수 없습니다.

[esbuild](https://esbuild.github.io/) 또는 Microsoft의 TypeScript 컴파일러(`tsc`)를 사용하여 TypeScript 코드를 JavaScript로 트랜스파일할 수 있습니다. [AWS Serverless Application Model(AWS SAM)](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started.html)와 [AWS Cloud Development Kit (AWS CDK)](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html) 모두 esbuild를 사용합니다.

esbuild를 사용할 경우 다음을 고려하세요.
+ [TypeScript 경고](https://esbuild.github.io/content-types/#typescript-caveats)에는 여러 종류가 있습니다.
+ 사용하려는 Node.js 런타임과 일치하도록 TypeScript 변환 설정을 구성해야 합니다. 자세한 내용은 esbuild 설명서의 [Target(대상)](https://esbuild.github.io/api/#target)을 참조하세요. Lambda에서 지원하는 특정 Node.js 버전을 타겟팅하는 방법을 보여주는 **tsconfig.json** 파일의 예는 [TypeScript GitHub 저장소](https://github.com/tsconfig/bases/blob/main/bases/node14.json)를 참조하세요.
+ esbuild는 유형 검사를 수행하지 않습니다. 유형을 확인하려면 `tsc` 컴파일러를 사용합니다. 다음 예에 표시된 대로 `tsc -noEmit`을 실행하거나 **tsconfig.json** 파일에 `"noEmit"` 파라미터를 추가합니다. 이렇게 하면 `tsc`를 구성하여 JavaScript 파일을 방출하지 않습니다. 유형을 확인한 후 esbuild를 사용하여 TypeScript 파일을 JavaScript로 변환합니다.

**Example tsconfig.json**  

```
 {
  "compilerOptions": {
    "target": "es2020",
    "strict": true,
    "preserveConstEnums": true,
    "noEmit": true,
    "sourceMap": false,
    "module":"commonjs",
    "moduleResolution":"node",
    "esModuleInterop": true, 
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true, 
    "isolatedModules": true, 
  },
  "exclude": ["node_modules", "**/*.test.ts"]
}
```

## Lambda에 대한 유형 정의
<a name="typescript-type-definitions"></a>

[@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) 패키지는 Lambda 함수에 대한 유형 정의를 제공합니다. 함수가 다음 중 하나를 사용하는 경우 이 패키지를 설치합니다.
+ 다음과 같은 일반적인 AWS 이벤트 소스:
  + `APIGatewayProxyEvent`: [Amazon API Gateway 프록시 통합](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html)용 
  + `SNSEvent`: [Amazon Simple Notification Service 알림](with-sns.md)용
  + `SQSEvent`: [Amazon Simple Queue Service 메시지](with-sqs.md)용
  + `S3Event`: [S3 트리거 이벤트](with-s3.md)용
  + `DynamoDBStreamEvent`: [Amazon DynamoDB Streams](with-ddb.md)용
+ Lambda [컨텍스트](typescript-context.md) 객체
+ [콜백](typescript-handler.md#typescript-handler-callback) 핸들러 패턴

함수에 Lambda 유형 정의를 추가하려면 `@types/aws-lambda`를 개발 종속성으로 설치합니다.

```
npm install -D @types/aws-lambda
```

그런 다음 `aws-lambda`에서 유형을 가져옵니다.

```
import { Context, S3Event, APIGatewayProxyEvent } from 'aws-lambda';

export const handler = async (event: S3Event, context: Context) => {
    // Function code
};
```

`import ... from 'aws-lambda'` 문은 유형 정의를 가져옵니다. 관련 없는 타사 도구인 `aws-lambda` npm 패키지는 가져오지 않습니다. 자세한 내용은 DefinitelyTyped GitHub 리포지토리의 [aws-lambda](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/aws-lambda)를 참조하세요.

**참고**  
자체 사용자 지정 유형 정의를 사용할 때는 [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda)가 필요 없습니다. 이벤트 객체에 대한 자체 유형을 정의하는 함수 예제는 [예제 TypeScript Lambda 함수 코드](typescript-handler.md#typescript-example-code) 섹션을 참조하세요.

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

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

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

**Topics**
+ [TypeScript 프로젝트 설정](#typescript-handler-setup)
+ [예제 TypeScript Lambda 함수 코드](#typescript-example-code)
+ [CommonJS 및 ES 모듈](#typescript-commonjs-es-modules)
+ [Node.js 초기화](#typescript-initialization)
+ [핸들러 이름 지정 규칙](#typescript-handler-naming)
+ [입력 이벤트 객체 정의 및 액세스](#typescript-example-input)
+ [TypeScript 함수에 유효한 핸들러 패턴](#typescript-handler-signatures)
+ [핸들러에서 SDK for JavaScript v3 사용](#typescript-example-sdk-usage)
+ [환경 변수에 액세스](#typescript-example-envvars)
+ [전역 상태 사용](#typescript-handler-state)
+ [TypeScript Lambda 함수의 코드 모범 사례](#typescript-best-practices)

## TypeScript 프로젝트 설정
<a name="typescript-handler-setup"></a>

로컬 통합 개발 환경(IDE) 또는 텍스트 편집기를 사용하여 TypeScript 함수 코드를 작성합니다. Lambda 콘솔에서는 TypeScript 코드를 생성할 수 없습니다.

TypeScript Lambda 프로젝트를 초기화하는 방법에는 여러 가지가 있습니다. 예를 들어 `npm`을 사용하여 프로젝트를 생성하거나, [AWS SAM 애플리케이션](typescript-package.md#aws-sam-ts)을 생성하거나, [AWS CDK 애플리케이션](typescript-package.md#aws-cdk-ts)을 생성할 수 있습니다. `npm`을 사용하여 프로젝트를 생성하려면 다음을 수행하세요.

```
npm init
```

함수 코드는 `.ts` 파일에 저장되며, 빌드 시 JavaScript 파일로 트랜스파일됩니다. [esbuild](https://esbuild.github.io/) 또는 Microsoft의 TypeScript 컴파일러(`tsc`)를 사용하여 TypeScript 코드를 JavaScript로 트랜스파일할 수 있습니다. esbuild를 사용하려면 개발 종속성으로 추가합니다.

```
npm install -D esbuild
```

일반적인 TypeScript Lambda 함수 프로젝트는 다음과 같은 일반적인 구조를 따릅니다.

```
/project-root
  ├── index.ts - Contains main handler
  ├── dist/ - Contains compiled JavaScript
  ├── package.json - Project metadata and dependencies
  ├── package-lock.json - Dependency lock file
  ├── tsconfig.json - TypeScript configuration
  └── node_modules/ - Installed dependencies
```

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

다음 예제 Lambda 함수 코드는 주문에 대한 정보를 입력으로 가져와서 텍스트 파일 영수증을 생성하고 해당 파일을 Amazon S3 버킷에 넣습니다. 이 예제에서는 사용자 지정 이벤트 유형(`OrderEvent`)을 정의합니다. AWS 이벤트 소스에 대한 유형 정의를 가져오는 방법을 알아보려면 [Lambda에 대한 유형 정의](lambda-typescript.md#typescript-type-definitions)를 참조하세요.

**참고**  
이 예제에서는 ES 모듈 핸들러를 사용합니다. Lambda는 ES 모듈과 CommonJS 핸들러 모두 지원합니다. 자세한 내용은 [CommonJS 및 ES 모듈](nodejs-handler.md#nodejs-commonjs-es-modules) 섹션을 참조하세요.

**Example index.ts Lambda 함수**  

```
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';

// Initialize the S3 client outside the handler for reuse
const s3Client = new S3Client();

// Define the shape of the input event
type OrderEvent = {
    order_id: string;
    amount: number;
    item: string;
}

/**
 * Lambda handler for processing orders and storing receipts in S3.
 */
export const handler = async (event: OrderEvent): Promise<string> => {
    try {
        // Access environment variables
        const bucketName = process.env.RECEIPT_BUCKET;
        if (!bucketName) {
            throw new Error('RECEIPT_BUCKET environment variable is not set');
        }

        // Create the receipt content and key destination
        const receiptContent = `OrderID: ${event.order_id}\nAmount: $${event.amount.toFixed(2)}\nItem: ${event.item}`;
        const key = `receipts/${event.order_id}.txt`;

        // Upload the receipt to S3
        await uploadReceiptToS3(bucketName, key, receiptContent);

        console.log(`Successfully processed order ${event.order_id} and stored receipt in S3 bucket ${bucketName}`);
        return 'Success';
    } catch (error) {
        console.error(`Failed to process order: ${error instanceof Error ? error.message : 'Unknown error'}`);
        throw error;
    }
};

/**
 * Helper function to upload receipt to S3
 */
async function uploadReceiptToS3(bucketName: string, key: string, receiptContent: string): Promise<void> {
    try {
        const command = new PutObjectCommand({
            Bucket: bucketName,
            Key: key,
            Body: receiptContent
        });

        await s3Client.send(command);
    } catch (error) {
        throw new Error(`Failed to upload receipt to S3: ${error instanceof Error ? error.message : 'Unknown error'}`);
    }
}
```

`index.ts` 파일은 다음 코드 섹션을 포함하고 있습니다.
+ `import` 블록: 이 블록을 사용하여 [AWS SDK 클라이언트](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/the-request-object.html) 등 Lambda 함수에 필요한 라이브러리를 포함할 수 있습니다.
+ `const s3Client` 선언: 핸들러 함수 외부에서 [Amazon S3 클라이언트](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/)를 초기화합니다. 그러면 [초기화 단계](lambda-runtime-environment.md#runtimes-lifecycle-ib)에서 Lambda가 이 코드를 실행하고 클라이언트는 [여러 간접 호출에서 재사용](lambda-runtime-environment.md#execution-environment-reuse)할 수 있도록 보존됩니다.
+ `type OrderEvent`: 예상 입력 이벤트의 구조를 정의합니다.
+ `export const handler`: Lambda가 간접적으로 호출하는 주요 핸들러 함수입니다. 함수를 배포할 때 [Handler](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html#lambda-CreateFunction-request-Handler) 속성에 `index.handler`를 지정합니다. `Handler` 속성 값은 파일 이름과 내보낸 핸들러 메서드의 이름이며, 점으로 구분됩니다.
+ `uploadReceiptToS3` 함수: 기본 핸들러 함수에서 참조하는 도우미 함수입니다.

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

## CommonJS 및 ES 모듈
<a name="typescript-commonjs-es-modules"></a>

Node.js는 CommonJS와 ECMAScript 모듈(ES 모듈)이라는 2가지 모듈 시스템을 지원합니다. Lambda에서는 [실행 환경 초기화](#typescript-initialization) 도중 비동기식 태스크를 완료할 수 있는 최상위 레벨 대기를 지원하므로 ES 모듈 사용이 권장됩니다.

Node.js는 파일 확장자가 `.cjs`인 파일을 CommonJS 모듈로 취급하는 반면 `.mjs` 확장자는 ES 모듈을 나타냅니다. 기본적으로 Node.js는 파일 확장자가 `.js`인 파일을 CommonJS 모듈로 취급합니다. 함수의 `package.json` 파일에서 `type`을 `module`로 지정하여 `.js` 파일을 ES 모듈로 처리하도록 Node.js를 구성할 수 있습니다. `NODE_OPTIONS` 환경 변수에 `—experimental-detect-module` 플래그를 추가하여 `.js` 파일을 CommonJS 또는 ES 모듈로 처리해야 하는지 여부를 자동으로 감지하도록 Node.js를 Lambda에서 구성할 수 있습니다. 자세한 내용은 [실험 단계 Node.js 실험 기능](lambda-nodejs.md#nodejs-experimental-features)을 참조하세요.

다음 예제에서는 ES 모듈과 CommonJS 모듈을 모두 사용하여 작성된 함수 핸들러를 보여줍니다. 이 페이지의 나머지 예제에서는 모두 ES 모듈을 사용합니다.

## Node.js 초기화
<a name="typescript-initialization"></a>

Node.js는 이벤트 루프를 사용하는 효율적인 비동기 작업을 지원하는 비차단 I/O 모델을 사용합니다. 예를 들어 Node.js가 네트워크를 직접 호출할 때 함수는 네트워크 응답을 차단하지 않고 다른 작업을 계속 처리합니다. 네트워크 응답이 수신되면 콜백 대기열에 배치됩니다. 대기열의 태스크는 현재 태스크가 완료되면 처리됩니다.

Lambda에서는 실행 환경 초기화 도중 시작된 비동기식 태스크가 초기화 중에 완료되도록 최상위 레벨 대기 사용이 권장됩니다. 초기화 중에 완료되지 않은 비동기식 태스크는 일반적으로 첫 번째 함수 간접 호출 중에 실행됩니다. 이 경우 예상하지 못한 동작 또는 오류가 발생할 수 있습니다. 예를 들어 함수 초기화로 네트워크를 직접 호출하고 AWS Parameter Store에서 파라미터를 가져올 수 있습니다. 초기화 도중 이 태스크가 완료되지 않으면 간접 호출 중에 값이 null일 수 있습니다. 또한 초기화와 간접 호출 간에 지연이 발생하여 시간에 민감한 작업에서 오류가 트리거될 수 있습니다. 특히 AWS 서비스 직접 호출은 시간에 민감한 요청 서명을 사용할 수 있습니다. 초기화 단계 중에 직접 호출이 완료되지 않으면 서비스 호출에 실패합니다. 초기화 중에 태스크를 완료하면 일반적으로 콜드 스타트 성능이 향상되고 프로비저닝된 동시성을 사용할 때 첫 번째 간접 호출 성능이 향상됩니다. 자세한 내용과 예제는 [AWS Lambda에서 Node.js ES 모듈 및 최상위 레벨 대기](https://aws.amazon.com/blogs/compute/using-node-js-es-modules-and-top-level-await-in-aws-lambda)를 참조하세요.

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

함수를 구성할 때 [핸들러](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html#lambda-CreateFunction-request-Handler) 설정 값은 파일 이름과 내보낸 핸들러 메서드의 이름이며, 점으로 구분됩니다. 콘솔에서 생성된 함수의 기본값은 예를 들어, 이 가이드에서는 `index.handler`입니다. 이는 `index.js` 또는 `index.mjs` 파일에서 내보낸 `handler` 메서드를 나타냅니다.

콘솔에서 다른 파일 이름 또는 함수 핸들러 이름을 사용하여 함수를 생성하는 경우 기본 핸들러 이름을 편집해야 합니다.

**함수 핸들러 이름 변경(콘솔)**

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

1. **Code**(코드) 탭을 선택합니다.

1. 아래로 스크롤하여 **런타임 설정** 창으로 이동한 다음 **편집**을 선택합니다.

1. **핸들러**에서 함수 핸들러의 새 이름을 입력합니다.

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

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

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

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

TypeScript에서 Lambda 함수로 작업할 때 유형 또는 인터페이스를 사용하여 입력 이벤트의 셰이프를 정의할 수 있습니다. 이 예제에서는 유형을 사용하여 이벤트 구조를 정의합니다.

```
type OrderEvent = {
    order_id: string;
    amount: number;
    item: string;
}
```

유형 또는 인터페이스를 정의한 후 핸들러의 서명에 사용하여 유형 안전을 보장합니다.

```
export const handler = async (event: OrderEvent): Promise<string> => {
```

컴파일하는 동안 TypeScript는 이벤트 객체에 올바른 유형의 필수 필드가 포함되어 있는지 확인합니다. 예를 들어, `event.order_id`를 숫자로 사용하거나 `event.amount`를 문자열로 사용하려고 하면 TypeScript 컴파일러가 오류를 보고합니다.

## TypeScript 함수에 유효한 핸들러 패턴
<a name="typescript-handler-signatures"></a>

[콜백](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/using-a-callback-function.html)을 사용하는 대신 [async/await](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/using-async-await.html)를 사용하여 함수 핸들러를 선언하는 것이 좋습니다. async/await는 중첩된 콜백이나 체인 프라미스 없이 비동기 코드를 작성할 수 있는 간결하고 읽기 쉬운 방법입니다. 비동기/대기를 사용하면 비동기 및 비차단 상태를 유지하면서 동기 코드처럼 읽는 코드를 작성할 수 있습니다.

이 섹션의 예제에서는 `S3Event` 유형을 사용합니다. 그러나 [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) 패키지에 다른 AWS 이벤트 유형을 사용하거나 이벤트 유형을 직접 정의할 수 있습니다. @types/aws-lambda의 유형을 사용하려면 다음을 수행하세요.

1. @types/aws-lambda 패키지를 개발 종속성으로 추가합니다.

   ```
   npm install -D @types/aws-lambda
   ```

1. `Context`, `S3Event`, `Callback` 등 필요한 유형을 가져옵니다.

### 비동기 함수 핸들러(권장)
<a name="typescript-handler-async"></a>

`async` 키워드는 함수를 비동기로 표시하고 `await` 키워드는 `Promise`이 해결될 때까지 함수 실행을 일시 중지합니다. 핸들러에 사용할 수 있는 인수는 다음과 같습니다.
+ `event`: 함수에 전달된 입력 데이터가 들어 있습니다.
+ `context`: 간접 호출, 함수 및 실행 환경에 대한 정보가 들어 있습니다. 자세한 내용은 [Lambda 컨텍스트 객체를 사용하여 TypeScript 함수 정보 검색](typescript-context.md) 섹션을 참조하세요.

다음은 async/await 패턴에 유효한 서명입니다.

```
export const handler = async (event: S3Event): Promise<void> => { };
```

```
export const handler = async (event: S3Event, context: Context): Promise<void> => { };
```

**참고**  
항목 배열을 비동기적으로 처리하는 경우 `Promise.all`과 함께 await를 사용하여 모든 작업이 완료되도록 해야 합니다. `forEach`와 같은 메서드는 async 콜백이 완료될 때까지 기다리지 않습니다. 자세한 내용은 Mozilla 설명서의 [Array.prototype.forEach()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)를 참조하세요.

### 동기 함수 핸들러
<a name="typescript-handler-synchronous"></a>

함수가 비동기식 태스크를 수행하지 않는 경우 다음 함수 서명 중 하나를 사용하여 동기식 함수 핸들러를 사용할 수 있습니다.

```
export const handler = (event: S3Event): void => { };
```

```
export const handler = (event: S3Event, context: Context): void => { };
```

### 응답 스트리밍 함수 핸들러
<a name="typescript-handler-response-streaming"></a>

Lambda는 Node.js를 사용한 응답 스트리밍을 지원합니다. 응답 스트리밍 함수 핸들러는 awslambda.streamifyResponse() 데코레이터를 사용하고 event, responseStream, context라는 3가지 파라미터를 사용합니다. 함수 서명은 다음과 같습니다.

```
export const handler = awslambda.streamifyResponse(async (event: APIGatewayProxyEvent, responseStream: NodeJS.WritableStream, context: Context) => { });
```

자세한 내용은 Lambda 함수의 응답 스트리밍을 참조하세요.

### 콜백 기반 함수 핸들러
<a name="typescript-handler-callback"></a>

**참고**  
콜백 기반 함수 핸들러는 Node.js 22까지만 지원됩니다. Node.js 24부터 비동기식 태스크는 비동기 함수 핸들러를 사용하여 구현해야 합니다.

콜백 기반 함수 핸들러는 이벤트, 컨텍스트 및 콜백 인수를 사용할 수 있습니다. 콜백 인수는 `Error`와 JSON 직렬화가 가능한 응답을 예상합니다.

다음은 콜백 핸들러 패턴에 유효한 서명입니다.

```
export const handler = (event: S3Event, context: Context, callback: Callback<void>): void => { };
```

[이벤트 루프](https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/)가 비어 있거나 함수 시간이 초과될 때까지 함수가 계속 실행됩니다. 응답은 모든 이벤트 루프 작업이 완료될 때까지 간접 호출자에게 전송되지 않습니다. 함수 제한 시간을 초과하면, 대신 오류가 반환됩니다. [context.callbackWaitsForEmptyEventLoop](typescript-context.md)를 false로 설정하여 즉시 응답을 전송하도록 런타임을 구성할 수 있습니다.

**Example 콜백이 있는 TypeScript 함수**  
다음 예제에서는 API Gateway 통합에 특화된 콜백 유형인 `APIGatewayProxyCallback`을 사용합니다. 대부분의 AWS 이벤트 소스는 위의 서명에 표시된 일반 `Callback` 유형을 사용합니다.  

```
import { Context, APIGatewayProxyCallback, APIGatewayEvent } from 'aws-lambda';

export const lambdaHandler = (event: APIGatewayEvent, context: Context, callback: APIGatewayProxyCallback): void => {
    console.log(`Event: ${JSON.stringify(event, null, 2)}`);
    console.log(`Context: ${JSON.stringify(context, null, 2)}`);
    callback(null, {
        statusCode: 200,
        body: JSON.stringify({
            message: 'hello world',
        }),
    });
};
```

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

종종 Lambda 함수를 사용하여 다른 AWS 리소스와 상호 작용하거나 업데이트하는 경우가 있습니다. 이러한 리소스와 상호 작용하는 가장 간단한 방법은 AWS SDK for JavaScript을 사용하는 것입니다. 지원되는 모든 Lambda Node.js 런타임에는 [SDK for JavaScript 버전 3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/introduction/)가 포함되어 있습니다. 그러나 배포 패키지에 필요한 AWS SDK 클라이언트를 포함하는 것이 좋습니다. 이렇게 하면 향후 Lambda 런타임 업데이트 중 [이전 버전과의 호환성](runtimes-update.md#runtime-update-compatibility)이 극대화됩니다.

함수에 SDK 종속성을 추가하려면 필요한 특정 SDK 클라이언트에 `npm install` 명령을 사용하세요. 예제 코드에서는 [Amazon S3 클라이언트](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/)를 사용했습니다. `package.json` 파일이 포함된 디렉터리에서 다음 명령을 실행하여 이러한 종속성을 추가합니다.

```
npm install @aws-sdk/client-s3
```

예제 함수와 같이 함수 코드에서 필요한 클라이언트와 명령을 가져옵니다.

```
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
```

그런 다음 [Amazon S3 클라이언트](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/)를 초기화합니다.

```
const s3Client = new S3Client();
```

이 예제에서는 함수를 간접적으로 호출할 때마다 초기화할 필요가 없도록 기본 핸들러 함수에서 Amazon S3 클라이언트를 초기화했습니다. SDK 클라이언트를 초기화한 후 이를 사용하여 해당 AWS 서비스에 대한 API 직접 호출을 수행할 수 있습니다. 예제 코드는 다음과 같이 Amazon S3 [PutObject](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/command/PutObjectCommand/) API 작업을 직접적으로 호출합니다.

```
const command = new PutObjectCommand({
    Bucket: bucketName,
    Key: key,
    Body: receiptContent
});
```

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

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

```
// Access environment variables
const bucketName = process.env.RECEIPT_BUCKET;
if (!bucketName) {
    throw new Error('RECEIPT_BUCKET environment variable is not set');
}
```

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

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

예제 코드에서 S3 클라이언트 초기화 코드는 핸들러 외부에 있습니다. 런타임은 함수가 첫 번째 이벤트를 처리하기 전에 클라이언트를 초기화하며, 클라이언트는 모든 간접 호출에서 재사용할 수 있는 상태로 유지됩니다.

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

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

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

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

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

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

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

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

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

# .zip 파일 아카이브를 사용하여 Lambda에 트랜스파일된 TypeScript 코드 배포
<a name="typescript-package"></a>

TypeScript 코드를 AWS Lambda에 배포하려면 먼저 JavaScript로 트랜스파일해야 합니다. 이 페이지에서는 .zip 파일 아카이브를 사용하여 TypeScript 코드를 빌드하고 Lambda에 배포하는 세 가지 방법을 설명합니다.
+ [AWS Serverless Application Model(AWS SAM) 사용](#aws-sam-ts)
+ [AWS Cloud Development Kit (AWS CDK)](#aws-cdk-ts) 사용
+ [AWS Command Line Interface(AWS CLI) 및 esbuild 사용](#aws-cli-ts)

AWS SAM과 AWS CDK는 TypeScript 함수의 빌드 및 배포를 간소화합니다. [AWS SAM 템플릿 사양](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification.html)에서는 서버리스 애플리케이션을 구성하는 Lambda 함수, API, 권한, 구성 및 이벤트를 설명하는 간단하고 깔끔한 구문을 제공합니다. [AWS CDK](https://docs.aws.amazon.com/cdk/v2/guide/home.html)를 사용하면 프로그래밍 언어의 우수한 표현력을 활용하여 클라우드에서 신뢰할 수 있고 확장 가능하며 비용 효율적인 애플리케이션을 빌드할 수 있습니다. AWS CDK는 중급 또는 고급의 숙련도를 갖춘 AWS 사용자를 대상으로 합니다. AWS CDK 및 AWS SAM 둘 다 esbuild를 사용하여 TypeScript 코드를 JavaScript로 프랜스파일합니다.

## AWS SAM을 사용하여 Lambda에 TypeScript 코드 배포
<a name="aws-sam-ts"></a>

다음 단계를 따라 AWS SAM을 사용하여 샘플 Hello World TypeScript 애플리케이션을 다운로드, 빌드 및 배포합니다. 이 애플리케이션은 기본적인 API 백엔드를 구현합니다. 이 구성에는 Amazon API Gateway 엔드포인트와 Lambda 함수가 포함됩니다. API Gateway 엔드포인트에 GET 요청을 보내면 Lambda 함수가 간접 호출됩니다. 이 함수는 `hello world` 메시지를 반환합니다.

**참고**  
AWS SAM은 esbuild를 사용하여 TypeScript 코드에서 Node.js Lambda 함수를 생성합니다. esbuild 지원은 현재 공개 미리 보기로 제공됩니다. 공개 평가판으로 제공되는 동안에는 esbuild 지원에 이전 버전과 호환되지 않는 변경 사항이 적용될 수 있습니다.

**사전 조건**

이 섹션의 단계를 완료하려면 다음이 필요합니다.
+ [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)
+ Node.js

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

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

   ```
   sam init --app-template hello-world-typescript --name sam-app --package-type Zip --runtime nodejs24.x
   ```

1. (선택 사항) 샘플 애플리케이션에는 코드 린팅을 위한 [ESLlint](https://eslint.org/) 및 단위 테스트를 위한 [Jest](https://jestjs.io/) 등의 일반적으로 사용되는 도구에 대한 구성이 포함되어 있습니다. lint 및 test 명령 실행

   ```
   cd sam-app/hello-world
   npm install
   npm run lint
   npm run test
   ```

1. 앱을 빌드합니다.

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

1. 앱을 배포합니다.

   ```
   sam deploy --guided
   ```

1. 화면에 표시되는 프롬프트를 따릅니다. 대화형 환경에서 제공되는 기본 옵션을 수락하려면 `Enter`로 응답합니다.

1. 출력에는 REST API에 대한 엔드포인트가 표시됩니다. 함수를 테스트하려면 브라우저에서 엔드포인트를 엽니다. 다음과 같은 응답이 표시되어야 합니다.

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

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

   ```
   sam delete
   ```

## AWS CDK를 사용하여 Lambda에 TypeScript 코드 배포
<a name="aws-cdk-ts"></a>

다음 단계를 따라 AWS CDK를 사용하여 샘플 TypeScript 애플리케이션을 빌드 및 배포합니다. 이 애플리케이션은 기본적인 API 백엔드를 구현합니다. 이 구성에는 Amazon API Gateway 엔드포인트와 Lambda 함수가 포함됩니다. API Gateway 엔드포인트에 GET 요청을 보내면 Lambda 함수가 간접 호출됩니다. 이 함수는 `hello world` 메시지를 반환합니다.

**사전 조건**

이 섹션의 단계를 완료하려면 다음이 필요합니다.
+ [AWS CLI 버전 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ [AWS CDK 버전 2](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html#getting_started_prerequisites)
+ Node.js
+ [도커](https://www.docker.com/get-started/) 또는 [esbuild](https://esbuild.github.io/)

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

1. 새 애플리케이션용 프로젝트 디렉터리를 생성합니다.

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

1. 앱을 초기화합니다.

   ```
   cdk init app --language typescript
   ```

1. [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) 패키지를 개발 종속성으로 추가합니다. 이 패키지에는 Lambda에 대한 유형 정의가 들어 있습니다.

   ```
   npm install -D @types/aws-lambda
   ```

1. **lib** 디렉터리를 엽니다. **hello-world-stack.ts**라는 이름의 파일이 있어야 합니다. 이 디렉터리에 **hello-world.function.ts**와 **hello-world.ts**라는 2개의 새 파일을 만듭니다.

1. **hello-world.function.ts**를 열고 파일에 다음 코드를 추가합니다. Lambda 함수의 코드입니다.
**참고**  
`import` 문은 [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda)에서 유형 정의를 가져옵니다. 관련 없는 타사 도구인 `aws-lambda` NPM 패키지는 가져오지 않습니다. 자세한 내용은 DefinitelyTyped GitHub 리포지토리의 [aws-lambda](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/aws-lambda)를 참조하세요.

   ```
   import { Context, APIGatewayProxyResult, APIGatewayEvent } from 'aws-lambda';
   
   export const handler = async (event: APIGatewayEvent, context: Context): Promise<APIGatewayProxyResult> => {
       console.log(`Event: ${JSON.stringify(event, null, 2)}`);
       console.log(`Context: ${JSON.stringify(context, null, 2)}`);
       return {
           statusCode: 200,
           body: JSON.stringify({
               message: 'hello world',
           }),
       };
   };
   ```

1. **hello-world.ts**를 열고 파일에 다음 코드를 추가합니다. 여기에는 Lambda 함수를 생성하는 [NodejsFunction 구문](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs-readme.html) 및 REST API를 생성하는 [LambdaRestApi 구문](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.LambdaRestApi.html)이 포함됩니다.

   ```
   import { Construct } from 'constructs';
   import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';
   import { LambdaRestApi } from 'aws-cdk-lib/aws-apigateway';
     
   export class HelloWorld extends Construct {
     constructor(scope: Construct, id: string) {
       super(scope, id);
       const helloFunction = new NodejsFunction(this, 'function');
       new LambdaRestApi(this, 'apigw', {
         handler: helloFunction,
       });
     }
   }
   ```

   `NodejsFunction` 구문에서는 기본적으로 다음 사항을 가정합니다.
   + 함수 핸들러는 `handler`라고 부릅니다.
   + 함수 코드가 포함된 .ts 파일(**hello-world.function.ts**)은 구문을 포함하는 .ts 파일(**hello-world.ts**)과 동일한 디렉터리에 있습니다. 이 구문은 구문의 ID(‘hello-world’) 및 Lambda 핸들러 파일 이름(‘function’)을 사용하여 함수 코드를 찾습니다. 예를 들어, 함수 코드가 **hello-world.my-function.ts**라는 파일에 있는 경우 **hello-world.ts** 파일은 다음과 같은 함수 코드를 참조해야 합니다.

     ```
     const helloFunction = new NodejsFunction(this, 'my-function');
     ```

   이 동작을 변경하고 다른 esbuild 파라미터를 구성할 수 있습니다. 자세한 내용은 AWS CDK API 참조의 [esbuild 구성](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs-readme.html#configuring-esbuild)을 참조하세요.

1. **hello-world-stack.ts**를 엽니다. 이 코드는 [AWS CDK 스택](https://docs.aws.amazon.com/cdk/v2/guide/stacks.html)을 정의하는 코드입니다. 코드를 다음으로 바꿉니다.

   ```
   import { Stack, StackProps } from 'aws-cdk-lib';
   import { Construct } from 'constructs';
   import { HelloWorld } from './hello-world';
     
   export class HelloWorldStack extends Stack {
     constructor(scope: Construct, id: string, props?: StackProps) {
       super(scope, id, props);
       new HelloWorld(this, 'hello-world');
     }
   }
   ```

1. `cdk.json` 파일이 들어 있는 `hello-world` 디렉터리에서 애플리케이션을 배포합니다.

   ```
   cdk deploy
   ```

1. AWS CDK는 esbuild를 사용하여 Lambda 함수를 빌드하고 패키징한 다음, 함수를 Lambda 런타임에 배포합니다. 출력에는 REST API에 대한 엔드포인트가 표시됩니다. 함수를 테스트하려면 브라우저에서 엔드포인트를 엽니다. 다음과 같은 응답이 표시되어야 합니다.

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

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

## AWS CLI 및 esbuild를 사용하여 Lambda에 TypeScript 코드 배포
<a name="aws-cli-ts"></a>

다음 예에서는 esbuild 및 AWS CLI를 사용하여 TypeScript 코드를 트랜스파일하고 Lambda에 배포하는 방법을 보여줍니다. esbuild는 모든 종속성이 포함된 하나의 JavaScript 파일을 생성합니다. 이 파일이 .zip 아카이브에 추가해야 하는 유일한 파일입니다.

**사전 조건**

이 섹션의 단계를 완료하려면 다음이 필요합니다.
+ [AWS CLI 버전 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ Node.js
+ Lambda 함수용 [실행 역할](lambda-intro-execution-role.md)
+ Windows 사용자의 경우 [7zip](https://www.7-zip.org/download.html)과 같은 zip 파일 유틸리티가 필요합니다.

**샘플 함수 배포**

1. 로컬 컴퓨터에서 새 함수에 대한 프로젝트 디렉터리를 생성합니다.

1. 선택한 npm 또는 패키지 관리자를 사용하여 새 Node.js 프로젝트를 생성합니다.

   ```
   npm init
   ```

1. [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) 및 [esbuild](https://esbuild.github.io/) 패키지를 개발 종속성으로 추가합니다. `@types/aws-lambda` 패키지에는 Lambda에 대한 유형 정의가 들어 있습니다.

   ```
   npm install -D @types/aws-lambda esbuild
   ```

1. **index.ts**라는 이름의 새 파일을 만듭니다. 다음 코드를 새 파일에 추가합니다. Lambda 함수에 대한 코드입니다. 이 함수는 `hello world` 메시지를 반환합니다. 이 함수는 어떠한 API Gateway 리소스도 생성하지 않습니다.
**참고**  
`import` 문은 [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda)에서 유형 정의를 가져옵니다. 관련 없는 타사 도구인 `aws-lambda` NPM 패키지는 가져오지 않습니다. 자세한 내용은 DefinitelyTyped GitHub 리포지토리의 [aws-lambda](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/aws-lambda)를 참조하세요.

   ```
   import { Context, APIGatewayProxyResult, APIGatewayEvent } from 'aws-lambda';
   
   export const handler = async (event: APIGatewayEvent, context: Context): Promise<APIGatewayProxyResult> => {
     console.log(`Event: ${JSON.stringify(event, null, 2)}`);
     console.log(`Context: ${JSON.stringify(context, null, 2)}`);
     return {
         statusCode: 200,
         body: JSON.stringify({
             message: 'hello world',
         }),
      };
   };
   ```

1. 빌드 스크립트를 **package.json** 파일에 추가합니다. 이렇게 하면 .zip 배포 패키지를 자동으로 생성하도록 esbuild가 구성됩니다. 자세한 내용은 esbuild 설명서의 [빌드 스크립트](https://esbuild.github.io/getting-started/#build-scripts)를 참조하세요.

------
#### [ Linux and MacOS ]

   ```
   "scripts": {
     "prebuild": "rm -rf dist",
     "build": "esbuild index.ts --bundle --minify --sourcemap --platform=node --target=es2020 --outfile=dist/index.js",
     "postbuild": "cd dist && zip -r index.zip index.js*"
   },
   ```

------
#### [ Windows ]

   이 예제에서 `"postbuild"` 명령은 [7zip](https://www.7-zip.org/download.html) 유틸리티를 사용하여.zip 파일을 만듭니다. 선호하는 Windows zip 유틸리티를 사용하고 필요에 따라 명령을 수정하십시오.

   ```
   "scripts": {
     "prebuild": "del /q dist",
     "build": "esbuild index.ts --bundle --minify --sourcemap --platform=node --target=es2020 --outfile=dist/index.js",
     "postbuild": "cd dist && 7z a -tzip index.zip index.js*"
   },
   ```

------

1. 패키지를 빌드합니다.

   ```
   npm run build
   ```

1. .zip 배포 패키지를 사용하여 Lambda 함수를 생성합니다. 강조 표시된 텍스트를 [실행 역할](lambda-intro-execution-role.md)의 Amazon 리소스 이름(ARN)으로 바꿉니다.

   ```
   aws lambda create-function --function-name hello-world --runtime "nodejs24.x" --role arn:aws:iam::123456789012:role/lambda-ex --zip-file "fileb://dist/index.zip" --handler index.handler
   ```

1. [테스트 이벤트를 실행](testing-functions.md)하여 함수가 다음 응답을 반환하는지 확인합니다. API Gateway를 사용하여 이 함수를 간접 호출하려면 [REST API를 생성하고 구성합니다](https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-create-api.html).

   ```
   {
     "statusCode": 200,
     "body": "{\"message\":\"hello world\"}"
   }
   ```

# 컨테이너 이미지를 사용하여 Lambda에 트랜스파일된 TypeScript 코드 배포
<a name="typescript-image"></a>

TypeScript 코드를 Node.js [컨테이너 이미지](images-create.md)로 AWS Lambda 함수에 배포할 수 있습니다. AWS는 컨테이너 이미지를 빌드하는 데 도움이 되는 Node.js용 [기본 이미지](nodejs-image.md#nodejs-image-base)를 제공합니다. 이러한 기본 이미지는 Lambda에서 이미지를 실행하는 데 필요한 언어 런타임 및 기타 구성 요소가 미리 로드되어 있습니다. AWS는 컨테이너 이미지를 빌드하는 데 도움이 되는 각 기본 이미지의 Dockerfile을 제공합니다.

커뮤니티 또는 사기업에서 제공하는 기본 이미지를 사용하는 경우 Lambda와 호환될 수 있도록 기본 이미지에 [Node.js 런타임 인터페이스 클라이언트(RIC)를 추가](nodejs-image.md#nodejs-image-clients)해야 합니다.

Lambda는 로컬 테스트를 위한 런타임 인터페이스 에뮬레이터를 제공합니다. Node.js용 AWS 기본 이미지에는 런타임 인터페이스 에뮬레이터가 포함되어 있습니다. Alpine Linux 또는 Debian 이미지와 같은 대체 기본 이미지를 사용하는 경우 [에뮬레이터를 이미지에 빌드](https://github.com/aws/aws-lambda-runtime-interface-emulator/?tab=readme-ov-file#build-rie-into-your-base-image)하거나 [로컬 시스템에 설치](https://github.com/aws/aws-lambda-runtime-interface-emulator/?tab=readme-ov-file#test-an-image-without-adding-rie-to-the-image)할 수 있습니다.

## Node.js 기본 이미지를 사용하여 TypeScript 함수 코드 빌드 및 패키징
<a name="base-image-typescript"></a>

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

이 섹션의 단계를 완료하려면 다음이 필요합니다.
+ [AWS CLI 버전 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ [Docker](https://docs.docker.com/get-docker)(최소 버전 25.0.0)
+ Docker [buildx 플러그인](https://github.com/docker/buildx/blob/master/README.md)
+ Node.js 22.x

### 기본 이미지에서 이미지 생성
<a name="typescript-image-create"></a>

**Lambda용 AWS 기본 이미지에서 이미지를 생성하려면**

1. 로컬 컴퓨터에서 새 함수에 대한 프로젝트 디렉터리를 생성합니다.

1. 선택한 `npm` 또는 패키지 관리자를 사용하여 새 Node.js 프로젝트를 생성합니다.

   ```
   npm init
   ```

1. [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) 및 [esbuild](https://esbuild.github.io/) 패키지를 개발 종속성으로 추가합니다. `@types/aws-lambda` 패키지에는 Lambda에 대한 유형 정의가 들어 있습니다.

   ```
   npm install -D @types/aws-lambda esbuild
   ```

1. `package.json` 파일에 [빌드 스크립트](https://esbuild.github.io/getting-started/#build-scripts)를 추가합니다.

   ```
     "scripts": {
     "build": "esbuild index.ts --bundle --minify --sourcemap --platform=node --target=es2020 --outfile=dist/index.js"
   }
   ```

1. `index.ts`라는 파일을 새로 생성합니다. 다음 샘플 코드를 새 파일에 추가합니다. Lambda 함수에 대한 코드입니다. 이 함수는 `hello world` 메시지를 반환합니다.
**참고**  
`import` 문은 [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda)에서 유형 정의를 가져옵니다. 관련 없는 타사 도구인 `aws-lambda` NPM 패키지는 가져오지 않습니다. 자세한 내용은 DefinitelyTyped GitHub 리포지토리의 [aws-lambda](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/aws-lambda)를 참조하세요.

   ```
   import { Context, APIGatewayProxyResult, APIGatewayEvent } from 'aws-lambda';
   
   export const handler = async (event: APIGatewayEvent, context: Context): Promise<APIGatewayProxyResult> => {
       console.log(`Event: ${JSON.stringify(event, null, 2)}`);
       console.log(`Context: ${JSON.stringify(context, null, 2)}`);
       return {
           statusCode: 200,
           body: JSON.stringify({
               message: 'hello world',
           }),
       };
   };
   ```

1. 다음 구성으로 새 Dockerfile을 생성합니다.
   + `FROM` 속성을 기본 이미지의 URI로 설정합니다.
   + `CMD` 인수를 설정하여 Lambda 함수 핸들러를 지정합니다.

   다음 예제 Dockerfile은 다단계 빌드를 사용합니다. 첫 번째 단계에서는 TypeScript 코드를 JavaScript로 트랜스파일합니다. 두 번째 단계에서는 JavaScript 파일 및 프로덕션 종속성만 포함하는 컨테이너 이미지를 생성합니다.

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

   ```
   FROM public.ecr.aws/lambda/nodejs:22 as builder
   WORKDIR /usr/app
   COPY package.json index.ts  ./
   RUN npm install
   RUN npm run build
       
   FROM public.ecr.aws/lambda/nodejs:22
   WORKDIR ${LAMBDA_TASK_ROOT}
   COPY --from=builder /usr/app/dist/* ./
   CMD ["index.handler"]
   ```

1. [docker build](https://docs.docker.com/engine/reference/commandline/build/) 명령으로 도커 이미지를 빌드합니다. 다음 예제에서는 이미지 이름을 `docker-image`로 지정하고 `test` [태그](https://docs.docker.com/engine/reference/commandline/build/#tag)를 지정합니다. 이미지를 Lambda와 호환되게 만들려면 `--provenance=false` 옵션을 사용해야 합니다.

   ```
   docker buildx build --platform linux/amd64 --provenance=false -t docker-image:test .
   ```
**참고**  
이 명령은 빌드 머신의 아키텍처에 관계없이 컨테이너가 Lambda 실행 환경과 호환되는지 확인하기 위해 `--platform linux/amd64` 옵션을 지정합니다. ARM64 명령 세트 아키텍처를 사용하여 Lambda 함수를 생성하려는 경우 `--platform linux/arm64` 옵션을 대신 사용하도록 명령을 변경해야 합니다.

### (선택 사항) 로컬에서 이미지 테스트
<a name="typescript-image-test"></a>

1. **docker run** 명령을 사용하여 Docker 이미지를 시작합니다. 이 예제에서 `docker-image`는 이미지 이름이고 `test`는 태그입니다.

   ```
   docker run --platform linux/amd64 -p 9000:8080 docker-image:test
   ```

   이 명령은 이미지를 컨테이너로 실행하고 `localhost:9000/2015-03-31/functions/function/invocations`에 로컬 엔드포인트를 생성합니다.
**참고**  
ARM64 명령 세트 아키텍처를 위한 도커 이미지를 빌드한 경우 `--platform linux/arm64` 옵션을 `--platform linux/amd64` 대신 사용해야 합니다.

1. 새 터미널 창에서 로컬 엔드포인트에 이벤트를 게시합니다.

------
#### [ Linux/macOS ]

   Linux 및 macOS에서 다음 `curl` 명령을 실행합니다.

   ```
   curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
   ```

   이 명령은 빈 이벤트와 함께 함수를 간접 호출하고 응답을 반환합니다. 샘플 함수 코드가 아닌 자체 함수 코드를 사용하는 경우 JSON 페이로드로 함수를 간접 호출할 수 있습니다. 예제:

   ```
   curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"payload":"hello world!"}'
   ```

------
#### [ PowerShell ]

   PowerShell에서 다음 `Invoke-WebRequest` 명령을 실행합니다.

   ```
   Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{}' -ContentType "application/json"
   ```

   이 명령은 빈 이벤트와 함께 함수를 간접 호출하고 응답을 반환합니다. 샘플 함수 코드가 아닌 자체 함수 코드를 사용하는 경우 JSON 페이로드로 함수를 간접 호출할 수 있습니다. 예제:

   ```
   Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{"payload":"hello world!"}' -ContentType "application/json"
   ```

------

1. 컨테이너 ID를 가져옵니다.

   ```
   docker ps
   ```

1. [docker kill](https://docs.docker.com/engine/reference/commandline/kill/) 명령을 사용하여 컨테이너를 중지합니다. 이 명령에서 `3766c4ab331c`를 이전 단계의 컨테이너 ID로 바꿉니다.

   ```
   docker kill 3766c4ab331c
   ```

### 이미지 배포
<a name="typescript-image-deploy"></a>

**Amazon ECR에 이미지 배포 및 Lambda 함수 생성**

1. [get-login-password](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecr/get-login-password.html) 명령을 실행하여 Amazon ECR 레지스트리에 대해 Docker CLI를 인증합니다.
   + `--region` 값을 Amazon ECR 리포지토리를 생성하려는 AWS 리전으로 설정합니다.
   + `111122223333`를 사용자의 AWS 계정 ID로 바꿉니다.

   ```
   aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 111122223333.dkr.ecr.us-east-1.amazonaws.com
   ```

1. [create-repository](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecr/create-repository.html) 명령을 사용하여 Amazon ECR에 리포지토리를 생성합니다.

   ```
   aws ecr create-repository --repository-name hello-world --region us-east-1 --image-scanning-configuration scanOnPush=true --image-tag-mutability MUTABLE
   ```
**참고**  
Amazon ECR 리포지토리는 Lambda 함수와 동일한 AWS 리전 내에 있어야 합니다.

   성공하면 다음과 같은 응답이 표시됩니다.

   ```
   {
       "repository": {
           "repositoryArn": "arn:aws:ecr:us-east-1:111122223333:repository/hello-world",
           "registryId": "111122223333",
           "repositoryName": "hello-world",
           "repositoryUri": "111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world",
           "createdAt": "2023-03-09T10:39:01+00:00",
           "imageTagMutability": "MUTABLE",
           "imageScanningConfiguration": {
               "scanOnPush": true
           },
           "encryptionConfiguration": {
               "encryptionType": "AES256"
           }
       }
   }
   ```

1. 이전 단계의 출력에서 `repositoryUri`를 복사합니다.

1. [docker tag](https://docs.docker.com/engine/reference/commandline/tag/) 명령을 실행하여 로컬 이미지를 Amazon ECR 리포지토리에 최신 버전으로 태깅합니다. 이 명령에서:
   + `docker-image:test`는 Docker 이미지의 이름과 [태그](https://docs.docker.com/engine/reference/commandline/build/#tag)입니다. `docker build` 명령에서 지정한 이미지 이름 및 태그입니다.
   + `<ECRrepositoryUri>`를 복사한 `repositoryUri`로 바꿉니다. URI 끝에 `:latest`를 포함해야 합니다.

   ```
   docker tag docker-image:test <ECRrepositoryUri>:latest
   ```

   예제:

   ```
   docker tag docker-image:test 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
   ```

1. [docker push](https://docs.docker.com/engine/reference/commandline/push/) 명령을 실행하여 Amazon ECR 리포지토리에 로컬 이미지를 배포합니다. 리포지토리 URI 끝에 `:latest`를 포함해야 합니다.

   ```
   docker push 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
   ```

1. 함수에 대한 실행 역할이 아직 없는 경우 하나 [생성](lambda-intro-execution-role.md#permissions-executionrole-api)합니다. 다음 단계에서는 역할의 Amazon 리소스 이름(ARN)이 필요합니다.

1. Lambda 함수를 생성합니다. `ImageUri`의 경우 이전의 리포지토리 URI를 지정합니다. URI 끝에 `:latest`를 포함해야 합니다.

   ```
   aws lambda create-function \
     --function-name hello-world \
     --package-type Image \
     --code ImageUri=111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest \
     --role arn:aws:iam::111122223333:role/lambda-ex
   ```
**참고**  
이미지가 Lambda 함수와 동일한 리전에 있는 한 다른 AWS 계정의 이미지를 사용하여 함수를 생성할 수 있습니다. 자세한 내용은 [Amazon ECR 교차 계정 권한](images-create.md#configuration-images-xaccount-permissions) 섹션을 참조하세요.

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

   ```
   aws lambda invoke --function-name hello-world response.json
   ```

   다음과 같은 응답이 표시되어야 합니다.

   ```
   {
     "ExecutedVersion": "$LATEST", 
     "StatusCode": 200
   }
   ```

1. 함수의 출력을 보려면 `response.json` 파일을 확인합니다.

함수 코드를 업데이트하려면 이미지를 다시 빌드하고 Amazon ECR 리포지토리에 새 이미지를 업로드한 다음 [update-function-code](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html) 명령을 사용하여 이미지를 Lambda 함수에 배포해야 합니다.

Lambda는 이미지 태그를 특정 이미지 다이제스트로 확인합니다. 즉, 함수를 배포하는 데 사용된 이미지 태그가 Amazon ECR의 새 이미지로 가리키는 경우 Lambda는 새 이미지를 사용하도록 함수를 자동으로 업데이트하지 않습니다.

새 이미지를 동일한 Lambda 함수에 배포하려면 Amazon ECR의 이미지 태그가 동일하게 유지되더라도 [update-function-code](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html) 명령을 사용해야 합니다. 다음 예제에서 `--publish` 옵션은 업데이트된 컨테이너 이미지를 사용하여 새 버전의 함수를 생성합니다.

```
aws lambda update-function-code \
  --function-name hello-world \
  --image-uri 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest \
  --publish
```

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

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

컨텍스트 객체에 대한 유형 확인을 활성화하려면 [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) 패키지를 개발 종속성으로 추가하고 `Context` 유형을 가져와야 합니다. 자세한 내용은 [Lambda에 대한 유형 정의](lambda-typescript.md#typescript-type-definitions) 섹션을 참조하세요.

**컨텍스트 메서드**
+ `getRemainingTimeInMillis()` – 실행 시간이 초과되기까지 남은 시간(밀리초)을 반환합니다.

**컨텍스트 속성**
+ `functionName` – Lambda 함수의 이름입니다.
+ `functionVersion` – 함수의 [버전](configuration-versions.md)입니다.
+ `invokedFunctionArn` – 함수를 간접 호출할 때 사용하는 Amazon 리소스 이름(ARN)입니다. 간접 호출자가 버전 번호 또는 별칭을 지정했는지 여부를 나타냅니다.
+ `memoryLimitInMB` – 함수에 할당된 메모리의 양입니다.
+ `awsRequestId` – 호출 요청의 식별자입니다.
+ `logGroupName` – 함수에 대한 로그 그룹입니다.
+ `logStreamName` – 함수 인스턴스에 대한 로그 스트림입니다.
+ `identity` – (모바일 앱) 요청을 승인한 Amazon Cognito 자격 증명에 대한 정보입니다.
  + `cognitoIdentityId`— 인증된 Amazon Cognito ID입니다.
  + `cognitoIdentityPoolId` – 호출에 대한 권한을 부여한 Amazon Cognito ID 풀입니다.
+ `clientContext` – (모바일 앱) 클라이언트 애플리케이션이 Lambda에게 제공한 클라이언트 컨텍스트입니다.
  + `client.installation_id`
  + `client.app_title`
  + `client.app_version_name`
  + `client.app_version_code`
  + `client.app_package_name`
  + `env.platform_version`
  + `env.platform`
  + `env.make`
  + `env.model`
  + `env.locale`
  + `Custom` – 클라이언트 애플리케이션에 의해 지정되는 사용자 지정 값입니다.
+ `callbackWaitsForEmptyEventLoop` - 기본값(`true`), 콜백 기반 함수 핸들러를 사용하는 경우 Lambda는 함수 간접 호출을 종료하기 전에 콜백이 실행된 후 이벤트 루프가 비어 있을 때까지 기다립니다. `false`로 설정하면 응답을 보내고 이벤트 루프가 비어 있을 때까지 기다리는 대신 콜백이 실행된 직후 간접 호출을 종료합니다. 대기 중인 이벤트는 다음 번 간접 호출 중에 계속 실행됩니다. Lambda는 Node.js 22 이전 버전의 런타임에 대해서만 콜백 기반 함수 핸들러를 지원합니다.

**Example index.ts 파일**  
다음 예제 함수는 컨텍스트 정보를 로깅하고 로그의 위치를 반환합니다.  
Lambda 함수에서 이 코드를 사용하기 전에 [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) 패키지를 개발 종속 항목으로 추가해야 합니다. 이 패키지에는 Lambda에 대한 유형 정의가 들어 있습니다. 자세한 내용은 [Lambda에 대한 유형 정의](lambda-typescript.md#typescript-type-definitions) 섹션을 참조하세요.

```
import { Context } from 'aws-lambda';
export const lambdaHandler = async (event: string, context: Context): Promise<string> => {
  console.log('Remaining time: ', context.getRemainingTimeInMillis());
  console.log('Function name: ', context.functionName);
  return context.logStreamName;
};
```

# TypeScript Lambda 함수 로깅 및 모니터링
<a name="typescript-logging"></a>

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

함수 코드의 로그를 출력하려면 [콘솔 객체](https://nodejs.org/docs/latest-v18.x/api/console.html)의 메서드를 사용합니다. 보다 자세한 로깅을 위해 `stdout` 또는 `stderr`에 쓰는 로깅 라이브러리를 사용할 수 있습니다.

**Topics**
+ [로깅 도구 및 라이브러리 사용](#typescript-tools-libraries)
+ [구조화된 로깅에 Powertools for AWS Lambda(TypeScript) 및 AWS SAM 사용](#typescript-logging-sam)
+ [구조화된 로깅에 Powertools for AWS Lambda(TypeScript) 및 AWS CDK 사용](#typescript-logging-cdk)
+ [Lambda 콘솔에서 로그 보기](#typescript-logging-console)
+ [CloudWatch 콘솔에서 로그 보기](#typescript-logging-cwconsole)

## 로깅 도구 및 라이브러리 사용
<a name="typescript-tools-libraries"></a>

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

## 구조화된 로깅에 Powertools for AWS Lambda(TypeScript) 및 AWS SAM 사용
<a name="typescript-logging-sam"></a>

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

**사전 조건**

이 섹션의 단계를 완료하려면 다음이 필요합니다.
+ Node.js 20 이상
+ [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-typescript --name sam-app --package-type Zip --runtime nodejs24.x
   ```

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 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/01/31/[$LATEST]4d53e8d279824834a1ccd35511a4949c 2025-08-31T09:33:10.552000 START RequestId: 70693159-7e94-4102-a2af-98a6343fb8fb Version: $LATEST
   2025/01/31/[$LATEST]4d53e8d279824834a1ccd35511a4949c 2025-08-31T09:33:10.594000 2025-08-31T09:33:10.557Z 70693159-7e94-4102-a2af-98a6343fb8fb INFO {"_aws":{"Timestamp":1661938390556,"CloudWatchMetrics":[{"Namespace":"sam-app","Dimensions":[["service"]],"Metrics":[{"Name":"ColdStart","Unit":"Count"}]}]},"service":"helloWorld","ColdStart":1}
   2025/01/31/[$LATEST]4d53e8d279824834a1ccd35511a4949c 2025-08-31T09:33:10.595000 2025-08-31T09:33:10.595Z 70693159-7e94-4102-a2af-98a6343fb8fb INFO {"level":"INFO","message":"This is an INFO log - sending HTTP 200 - hello world response","service":"helloWorld","timestamp":"2025-08-31T09:33:10.594Z"}
   2025/01/31/[$LATEST]4d53e8d279824834a1ccd35511a4949c 2025-08-31T09:33:10.655000 2025-08-31T09:33:10.655Z 70693159-7e94-4102-a2af-98a6343fb8fb INFO {"_aws":{"Timestamp":1661938390655,"CloudWatchMetrics":[{"Namespace":"sam-app","Dimensions":[["service"]],"Metrics":[]}]},"service":"helloWorld"}
   2025/01/31/[$LATEST]4d53e8d279824834a1ccd35511a4949c 2025-08-31T09:33:10.754000 END RequestId: 70693159-7e94-4102-a2af-98a6343fb8fb
   2025/01/31/[$LATEST]4d53e8d279824834a1ccd35511a4949c 2025-08-31T09:33:10.754000 REPORT RequestId: 70693159-7e94-4102-a2af-98a6343fb8fb Duration: 201.55 ms Billed Duration: 202 ms Memory Size: 128 MB Max Memory Used: 66 MB Init Duration: 252.42 ms
   XRAY TraceId: 1-630f2ad5-1de22b6d29a658a466e7ecf5 SegmentId: 567c116658fbf11a Sampled: true
   ```

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

   ```
   sam delete
   ```

### 로그 보존 관리
<a name="typescript-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
```

## 구조화된 로깅에 Powertools for AWS Lambda(TypeScript) 및 AWS CDK 사용
<a name="typescript-logging-cdk"></a>

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

**사전 조건**

이 섹션의 단계를 완료하려면 다음이 필요합니다.
+ Node.js 20 이상
+ [AWS CLI 버전 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ [AWS CDK 버전 2](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html#getting_started_prerequisites)
+ [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 CDK 애플리케이션 배포**

1. 새 애플리케이션용 프로젝트 디렉터리를 생성합니다.

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

1. 앱을 초기화합니다.

   ```
   cdk init app --language typescript
   ```

1. [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) 패키지를 개발 종속성으로 추가합니다.

   ```
   npm install -D @types/aws-lambda
   ```

1. Powertools [Logger 유틸리티](https://docs.aws.amazon.com/powertools/typescript/latest/features/logger/)를 설치합니다.

   ```
   npm install @aws-lambda-powertools/logger
   ```

1. **lib** 디렉터리를 엽니다. **hello-world-stack.ts**라는 이름의 파일이 있어야 합니다. 이 디렉터리에 **hello-world.function.ts**와 **hello-world.ts**하는 2개의 새 파일을 만듭니다.

1. **hello-world.function.ts**를 열고 파일에 다음 코드를 추가합니다. Lambda 함수의 코드입니다.

   ```
   import { APIGatewayEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
   import { Logger } from '@aws-lambda-powertools/logger';
   const logger = new Logger();
     
   export const handler = async (event: APIGatewayEvent, context: Context): Promise<APIGatewayProxyResult> => {
     logger.info('This is an INFO log - sending HTTP 200 - hello world response');
     return {
       statusCode: 200,
       body: JSON.stringify({
         message: 'hello world',
       }),
     };
   };
   ```

1. **hello-world.ts**를 열고 파일에 다음 코드를 추가합니다. 여기에는 Lambda 함수를 생성하고, Powertools용 환경 변수를 구성하고, 로그 보존을 1주일로 설정하는 [NodeJSFunction 구성체](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs-readme.html)가 포함됩니다. 또한 REST API를 생성하는 [LambdaRestAPI 구성체](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.LambdaRestApi.html)도 포함되어 있습니다.

   ```
   import { Construct } from 'constructs';
   import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';
   import { LambdaRestApi } from 'aws-cdk-lib/aws-apigateway';
   import { RetentionDays } from 'aws-cdk-lib/aws-logs';
   import { CfnOutput } from 'aws-cdk-lib';
     
   export class HelloWorld extends Construct {
     constructor(scope: Construct, id: string) {
       super(scope, id);
       const helloFunction = new NodejsFunction(this, 'function', {
         environment: {
           Powertools_SERVICE_NAME: 'helloWorld',
           LOG_LEVEL: 'INFO',
         },
         logRetention: RetentionDays.ONE_WEEK,
       });
       const api = new LambdaRestApi(this, 'apigw', {
         handler: helloFunction,
       });
       new CfnOutput(this, 'apiUrl', {
         exportName: 'apiUrl',
         value: api.url,
       });
     }
   }
   ```

1. **hello-world-stack.ts**를 엽니다. 이 코드는 [AWS CDK 스택](https://docs.aws.amazon.com/cdk/v2/guide/stacks.html)을 정의하는 코드입니다. 코드를 다음으로 바꿉니다.

   ```
   import { Stack, StackProps } from 'aws-cdk-lib';
   import { Construct } from 'constructs';
   import { HelloWorld } from './hello-world';
       
   export class HelloWorldStack extends Stack {
     constructor(scope: Construct, id: string, props?: StackProps) {
       super(scope, id, props);
       new HelloWorld(this, 'hello-world');
     }
   }
   ```

1. 프로젝트 디렉터리로 돌아갑니다.

   ```
   cd hello-world
   ```

1. 애플리케이션 배포

   ```
   cdk deploy
   ```

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

   ```
   aws cloudformation describe-stacks --stack-name HelloWorldStack --query 'Stacks[0].Outputs[?ExportName==`apiUrl`].OutputValue' --output text
   ```

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

   ```
   curl <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 HelloWorldStack
   ```

   출력은 다음과 같습니다.

   ```
   2025/01/31/[$LATEST]2ca67f180dcd4d3e88b5d68576740c8e 2025-08-31T14:48:37.047000 START RequestId: 19ad1007-ff67-40ce-9afe-0af0a9eb512c Version: $LATEST
   2025/01/31/[$LATEST]2ca67f180dcd4d3e88b5d68576740c8e 2025-08-31T14:48:37.050000 {
   "level": "INFO",
   "message": "This is an INFO log - sending HTTP 200 - hello world response",
   "service": "helloWorld",
   "timestamp": "2025-08-31T14:48:37.048Z",
   "xray_trace_id": "1-630f74c4-2b080cf77680a04f2362bcf2"
   }
   2025/01/31/[$LATEST]2ca67f180dcd4d3e88b5d68576740c8e 2025-08-31T14:48:37.082000 END RequestId: 19ad1007-ff67-40ce-9afe-0af0a9eb512c
   2025/01/31/[$LATEST]2ca67f180dcd4d3e88b5d68576740c8e 2025-08-31T14:48:37.082000 REPORT RequestId: 19ad1007-ff67-40ce-9afe-0af0a9eb512c Duration: 34.60 ms Billed Duration: 35 ms Memory Size: 128 MB Max Memory Used: 57 MB Init Duration: 173.48 ms
   ```

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

   ```
   cdk destroy
   ```

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

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

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

## CloudWatch 콘솔에서 로그 보기
<a name="typescript-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 Lambda에서 TypeScript 코드 추적
<a name="typescript-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 Node.js](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-nodejs.html) – 트레이스 데이터를 생성하고 X-Ray에 전송하는 SDK입니다.
+ [Powertools for AWS Lambda(TypeScript)](https://docs.aws.amazon.com/powertools/typescript/latest/) - 서버리스 모범 사례를 구현하고 개발자 속도를 높이기 위한 개발자 도구 키트입니다.

각 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(TypeScript) 및 AWS SAM 사용](#typescript-tracing-sam)
+ [추적에 Powertools for AWS Lambda(TypeScript) 및 AWS CDK 사용](#typescript-tracing-cdk)
+ [X-Ray 추적 해석](#typescript-tracing-interpretation)

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

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

**사전 조건**

이 섹션의 단계를 완료하려면 다음이 필요합니다.
+ Node.js
+ [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-typescript --name sam-app --package-type Zip --runtime nodejs24.x --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
   ```

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

   ```
   XRay Event [revision 1] at (2023-01-31T11:29:40.527000) with id (1-11a2222-111a222222cb33de3b95daf9) and duration (0.483s)
     - 0.425s - sam-app/Prod [HTTP: 200]
       - 0.422s - Lambda [HTTP: 200]
     - 0.406s - sam-app-HelloWorldFunction-Xyzv11a1bcde [HTTP: 200]
     - 0.172s - sam-app-HelloWorldFunction-Xyzv11a1bcde
       - 0.179s - Initialization
       - 0.112s - Invocation
         - 0.052s - ## app.lambdaHandler
           - 0.001s - ### MySubSegment
       - 0.059s - Overhead
   ```

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

   ```
   sam delete
   ```

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

## 추적에 Powertools for AWS Lambda(TypeScript) 및 AWS CDK 사용
<a name="typescript-tracing-cdk"></a>

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

**사전 조건**

이 섹션의 단계를 완료하려면 다음이 필요합니다.
+ Node.js
+ [AWS CLI 버전 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ [AWS CDK 버전 2](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html#getting_started_prerequisites)
+ [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 Cloud Development Kit (AWS CDK) 애플리케이션 배포**

1. 새 애플리케이션용 프로젝트 디렉터리를 생성합니다.

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

1. 앱을 초기화합니다.

   ```
   cdk init app --language typescript
   ```

1. [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) 패키지를 개발 종속성으로 추가합니다.

   ```
   npm install -D @types/aws-lambda
   ```

1. Powertools [Tracer 유틸리티](https://docs.aws.amazon.com/powertools/typescript/latest/features/tracer/)를 설치합니다.

   ```
   npm install @aws-lambda-powertools/tracer
   ```

1. **lib** 디렉터리를 엽니다. **hello-world-stack.ts**라는 이름의 파일이 있어야 합니다. 이 디렉터리에 **hello-world.function.ts**와 **hello-world.ts**하는 2개의 새 파일을 만듭니다.

1. **hello-world.function.ts**를 열고 파일에 다음 코드를 추가합니다. Lambda 함수의 코드입니다.

   ```
   import { APIGatewayEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
   import { Tracer } from '@aws-lambda-powertools/tracer';
   const tracer = new Tracer();
   
   export const handler = async (event: APIGatewayEvent, context: Context): Promise<APIGatewayProxyResult> => {
     // Get facade segment created by Lambda
     const segment = tracer.getSegment();
   
     // Create subsegment for the function and set it as active
     const handlerSegment = segment.addNewSubsegment(`## ${process.env._HANDLER}`);
     tracer.setSegment(handlerSegment);
   
     // Annotate the subsegment with the cold start and serviceName
     tracer.annotateColdStart();
     tracer.addServiceNameAnnotation();
   
     // Add annotation for the awsRequestId
     tracer.putAnnotation('awsRequestId', context.awsRequestId);
     // Create another subsegment and set it as active
     const subsegment = handlerSegment.addNewSubsegment('### MySubSegment');
     tracer.setSegment(subsegment);
     let response: APIGatewayProxyResult = {
       statusCode: 200,
       body: JSON.stringify({
         message: 'hello world',
       }),
     };
     // Close subsegments (the Lambda one is closed automatically)
     subsegment.close(); // (### MySubSegment)
     handlerSegment.close(); // (## index.handler)
   
     // Set the facade segment as active again (the one created by Lambda)
     tracer.setSegment(segment);
     return response;
   };
   ```

1. **hello-world.ts**를 열고 파일에 다음 코드를 추가합니다. 여기에는 Lambda 함수를 생성하고, Powertools용 환경 변수를 구성하고, 로그 보존을 1주일로 설정하는 [NodeJSFunction 구성체](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs-readme.html)가 포함됩니다. 또한 REST API를 생성하는 [LambdaRestAPI 구성체](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.LambdaRestApi.html)도 포함되어 있습니다.

   ```
   import { Construct } from 'constructs';
   import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';
   import { LambdaRestApi } from 'aws-cdk-lib/aws-apigateway';
   import { CfnOutput } from 'aws-cdk-lib';
   import { Tracing } from 'aws-cdk-lib/aws-lambda';
   
   export class HelloWorld extends Construct {
     constructor(scope: Construct, id: string) {
       super(scope, id);
       const helloFunction = new NodejsFunction(this, 'function', {
         environment: {
           POWERTOOLS_SERVICE_NAME: 'helloWorld',
         },
         tracing: Tracing.ACTIVE,
       });
       const api = new LambdaRestApi(this, 'apigw', {
         handler: helloFunction,
       });
       new CfnOutput(this, 'apiUrl', {
         exportName: 'apiUrl',
         value: api.url,
       });
     }
   }
   ```

1. **hello-world-stack.ts**를 엽니다. 이 코드는 [AWS CDK 스택](https://docs.aws.amazon.com/cdk/v2/guide/stacks.html)을 정의하는 코드입니다. 코드를 다음으로 바꿉니다.

   ```
   import { Stack, StackProps } from 'aws-cdk-lib';
   import { Construct } from 'constructs';
   import { HelloWorld } from './hello-world';
     
   export class HelloWorldStack extends Stack {
     constructor(scope: Construct, id: string, props?: StackProps) {
       super(scope, id, props);
       new HelloWorld(this, 'hello-world');
     }
   }
   ```

1. 애플리케이션 배포

   ```
   cd ..
   cdk deploy
   ```

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

   ```
   aws cloudformation describe-stacks --stack-name HelloWorldStack --query 'Stacks[0].Outputs[?ExportName==`apiUrl`].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
   ```

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

   ```
   XRay Event [revision 1] at (2023-01-31T11:50:06.997000) with id (1-11a2222-111a222222cb33de3b95daf9) and duration (0.449s)
     - 0.350s - HelloWorldStack-helloworldfunction111A2BCD-Xyzv11a1bcde [HTTP: 200]
     - 0.157s - HelloWorldStack-helloworldfunction111A2BCD-Xyzv11a1bcde
       - 0.169s - Initialization
       - 0.058s - Invocation
         - 0.055s - ## index.handler
           - 0.000s - ### MySubSegment
       - 0.099s - Overhead
   ```

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

   ```
   cdk destroy
   ```

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

활성 추적을 구성하면 애플리케이션을 통해 특정 요청을 관찰할 수 있습니다. [X-Ray 트레이스 맵](https://docs.aws.amazon.com/xray/latest/devguide/xray-console-servicemap.html)에서는 애플리케이션 및 모든 구성 요소에 대한 정보를 제공합니다. 다음 예제에서는 샘플 애플리케이션의 추적을 보여줍니다.

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