콘텐츠로 이동

Smithy TypeScript API

Filter this guidePick generator option values to hide sections that don't apply.

Smithy는 모델 기반 방식으로 API를 작성하기 위한 프로토콜 독립적 인터페이스 정의 언어입니다.

Smithy TypeScript API 생성기는 서비스 정의를 위해 Smithy를 사용하고, 구현을 위해 Smithy TypeScript Server SDK를 사용하여 새로운 API를 생성합니다. 생성기는 AWS Lambda에 서비스를 배포하고 AWS API Gateway REST API를 통해 노출하기 위한 CDK 또는 Terraform 인프라 코드를 제공합니다. Smithy 모델에서 자동 코드 생성을 통해 타입 안전한 API 개발을 제공합니다. 생성된 핸들러는 로깅, AWS X-Ray 추적 및 CloudWatch Metrics를 포함한 관찰성을 위해 AWS Lambda Powertools for TypeScript를 사용합니다.

두 가지 방법으로 새로운 Smithy TypeScript API를 생성할 수 있습니다:

Terminal window
pnpm nx g @aws/nx-plugin:ts#api --framework=smithy
어떤 파일이 변경될지 확인하기 위해 드라이 런을 수행할 수도 있습니다
Terminal window
pnpm nx g @aws/nx-plugin:ts#api --framework=smithy --dry-run
매개변수타입기본값설명
name 필수string-API의 이름 (필수). 클래스 이름과 파일 경로를 생성하는 데 사용됩니다.
framework trpc | smithytrpc사용할 API 프레임워크.
namespace string-Smithy API의 네임스페이스입니다 (smithy 프레임워크에만 적용됨). 기본값은 모노레포 스코프입니다
integrationPattern isolated | sharedisolatedAPI에 대한 API Gateway 통합이 생성되는 방식입니다. isolated (기본값) 또는 shared 중에서 선택하세요.
auth iam | cognito | customiamAPI 인증에 사용할 방법입니다. iam(기본값), cognito 또는 custom 중에서 선택하세요.
directory stringpackages애플리케이션을 저장할 디렉토리입니다.
subDirectory string-프로젝트가 배치되는 하위 디렉토리입니다. 기본값은 프로젝트 이름입니다.
iac inherit | cdk | terraforminherit선호하는 IaC 공급자입니다. 기본적으로 초기 선택에서 상속됩니다.
infra rest-lambda | http-lambda | nonerest-lambda이 API를 배포하는 데 사용할 인프라 유형입니다.
preferInstallDependencies booleantrue생성기 실행 후 의존성 설치를 선호할지 여부입니다. 여러 생성기를 일괄 처리할 때 설치를 연기하려면 false로 설정하세요(후속 생성기가 Nx 프로젝트 그래프를 계산할 수 있도록 필요한 경우 설치는 여전히 실행됩니다). 마지막에 한 번만 설치하세요.

생성기는 <directory>/<api-name> 디렉토리에 두 개의 관련 프로젝트를 생성합니다:

  • 디렉터리model/ Smithy 모델 프로젝트
    • package.json 프로젝트의 패키지 이름과 의존성을 정의하는 프로젝트 매니페스트
    • project.json 프로젝트 구성 및 빌드 타겟
    • smithy-build.json Smithy 빌드 구성
    • ssdk.rolldown.config.mjs 생성된 TypeScript Server SDK를 번들링
    • 디렉터리src/
      • main.smithy 메인 서비스 정의
      • 디렉터리operations/
        • echo.smithy 예제 작업 정의
  • 디렉터리backend/ TypeScript 백엔드 구현
    • project.json 프로젝트 구성 및 빌드 타겟
    • rolldown.config.ts 번들 구성
    • 디렉터리src/
      • handler.ts AWS Lambda 핸들러
      • local-server.ts 로컬 개발 서버
      • service.ts 서비스 구현
      • context.ts 서비스 컨텍스트 정의
      • 디렉터리operations/
        • echo.ts 예제 작업 구현
      • 디렉터리generated/ 생성된 TypeScript SDK (빌드 중 생성됨)

이 생성기는 선택한 iac를 기반으로 인프라 코드를 생성하므로, 관련 CDK 구성 요소 또는 Terraform 모듈을 포함하는 packages/common에 프로젝트를 생성합니다.

공통 인프라 코드 프로젝트는 다음과 같이 구성됩니다:

  • 디렉터리packages/common/constructs
    • 디렉터리src
      • 디렉터리app/ 프로젝트/생성기에 특정한 인프라를 위한 구성 요소
        • 디렉터리apis/
          • <project-name>.ts API를 배포하기 위한 CDK 구성 요소
      • 디렉터리core/ app의 구성 요소에서 재사용되는 일반 구성 요소
        • 디렉터리api/
          • rest-api.ts REST API를 배포하기 위한 CDK 구성 요소
          • utils.ts API 구성 요소를 위한 유틸리티
      • index.ts app에서 구성 요소를 내보내는 진입점
    • project.json 프로젝트 빌드 타겟 및 구성

배포된 Smithy API는 API Gateway 스테이지 앞에 AWS WAFv2 Web ACL이 있는 다음과 같은 아키텍처를 가집니다:

ClientWAFAPI Gateway(REST API)Lambda(Smithy Server SDK)CloudWatch(Logs, Metrics)X-Ray(Traces)

작업은 모델 프로젝트 내의 Smithy 파일에 정의됩니다. 메인 서비스 정의는 main.smithy에 있습니다:

$version: "2.0"
namespace your.namespace
use aws.protocols#restJson1
use smithy.framework#ValidationException
@title("YourService")
@restJson1
service YourService {
version: "1.0.0"
operations: [
Echo,
// Add your operations here
]
errors: [
ValidationException
]
}

개별 작업은 operations/ 디렉토리의 별도 파일에 정의됩니다:

$version: "2.0"
namespace your.namespace
@http(method: "POST", uri: "/echo")
operation Echo {
input: EchoInput
output: EchoOutput
}
structure EchoInput {
@required
message: String
foo: Integer
bar: String
}
structure EchoOutput {
@required
message: String
}

동일한 데이터 타입을 공유하는 여러 Smithy API가 있는 경우, 각 모델에서 중복하는 대신 shape 라이브러리에서 해당 타입을 한 번 정의할 수 있습니다. shape 라이브러리는 서비스가 없는 Smithy 프로젝트로, 재사용 가능한 shape만 있으며 여러 Smithy 프로젝트가 의존할 수 있습니다.

smithy#project 생성기로 하나를 생성하세요:

Terminal window
pnpm nx g @aws/nx-plugin:smithy#project --name=my-shapes --type=shapes
어떤 파일이 변경될지 확인하기 위해 드라이 런을 수행할 수도 있습니다
Terminal window
pnpm nx g @aws/nx-plugin:smithy#project --name=my-shapes --type=shapes --dry-run

그러면 API의 모델이 use를 사용하여 해당 shape를 참조할 수 있습니다:

$version: "2.0"
namespace com.example.api
use com.example.shared#Customer
structure GetCustomerOutput {
@required
customer: Customer
}

shape 라이브러리를 생성하고 API 모델의 의존성으로 연결하는 방법은 Smithy 프로젝트 가이드를 참조하세요.

작업 구현은 백엔드 프로젝트의 src/operations/ 디렉토리에 있습니다. 각 작업은 TypeScript Server SDK에서 생성된 타입을 사용하여 구현됩니다(Smithy 모델에서 빌드 시 생성됨).

import { ServiceContext } from '../context.js';
import { Echo as EchoOperation } from '../generated/ssdk/index.js';
export const Echo: EchoOperation<ServiceContext> = async (input) => {
// Your business logic here
return {
message: `Echo: ${input.message}` // type-safe based on your Smithy model
};
};

작업은 src/service.ts의 서비스 정의에 등록되어야 합니다:

import { ServiceContext } from './context.js';
import { YourServiceService } from './generated/ssdk/index.js';
import { Echo } from './operations/echo.js';
// Import other operations here
// Register operations to the service here
export const Service: YourServiceService<ServiceContext> = {
Echo,
// Add other operations here
};

context.ts에서 작업에 대한 공유 컨텍스트를 정의할 수 있습니다:

export interface ServiceContext {
// Powertools tracer, logger and metrics are provided by default
tracer: Tracer;
logger: Logger;
metrics: Metrics;
// Add shared dependencies, database connections, etc.
dbClient: any;
userIdentity: string;
}

이 컨텍스트는 모든 작업 구현에 전달되며 데이터베이스 연결, 구성 또는 로깅 유틸리티와 같은 리소스를 공유하는 데 사용할 수 있습니다.

AWS Lambda Powertools를 사용한 관찰성

섹션 제목: “AWS Lambda Powertools를 사용한 관찰성”

생성기는 Middy 미들웨어를 통한 자동 컨텍스트 주입과 함께 AWS Lambda Powertools를 사용하여 구조화된 로깅을 구성합니다.

handler.ts
export const handler = middy<APIGatewayProxyEvent, APIGatewayProxyResult>()
.use(captureLambdaHandler(tracer))
.use(injectLambdaContext(logger))
.use(logMetrics(metrics))
.handler(lambdaHandler);

컨텍스트를 통해 작업 구현에서 로거를 참조할 수 있습니다:

operations/echo.ts
import { ServiceContext } from '../context.js';
import { Echo as EchoOperation } from '../generated/ssdk/index.js';
export const Echo: EchoOperation<ServiceContext> = async (input, ctx) => {
ctx.logger.info('Your log message');
// ...
};

AWS X-Ray 추적은 captureLambdaHandler 미들웨어를 통해 자동으로 구성됩니다.

handler.ts
export const handler = middy<APIGatewayProxyEvent, APIGatewayProxyResult>()
.use(captureLambdaHandler(tracer))
.use(injectLambdaContext(logger))
.use(logMetrics(metrics))
.handler(lambdaHandler);

작업에서 추적에 사용자 정의 하위 세그먼트를 추가할 수 있습니다:

operations/echo.ts
import { ServiceContext } from '../context.js';
import { Echo as EchoOperation } from '../generated/ssdk/index.js';
export const Echo: EchoOperation<ServiceContext> = async (input, ctx) => {
// Creates a new subsegment
const subsegment = ctx.tracer.getSegment()?.addNewSubsegment('custom-operation');
try {
// Your logic here
} catch (error) {
subsegment?.addError(error as Error);
throw error;
} finally {
subsegment?.close();
}
};

CloudWatch 메트릭은 logMetrics 미들웨어를 통해 각 요청에 대해 자동으로 수집됩니다.

handler.ts
export const handler = middy<APIGatewayProxyEvent, APIGatewayProxyResult>()
.use(captureLambdaHandler(tracer))
.use(injectLambdaContext(logger))
.use(logMetrics(metrics))
.handler(lambdaHandler);

작업에서 사용자 정의 메트릭을 추가할 수 있습니다:

operations/echo.ts
import { MetricUnit } from '@aws-lambda-powertools/metrics';
import { ServiceContext } from '../context.js';
import { Echo as EchoOperation } from '../generated/ssdk/index.js';
export const Echo: EchoOperation<ServiceContext> = async (input, ctx) => {
ctx.metrics.addMetric("CustomMetric", MetricUnit.Count, 1);
// ...
};

Smithy는 내장 오류 처리를 제공합니다. Smithy 모델에서 사용자 정의 오류를 정의할 수 있습니다:

@error("client")
@httpError(400)
structure InvalidRequestError {
@required
message: String
}

그리고 작업/서비스에 등록합니다:

operation MyOperation {
...
errors: [InvalidRequestError]
}

그런 다음 TypeScript 구현에서 던집니다:

import { InvalidRequestError } from '../generated/ssdk/index.js';
export const MyOperation: MyOperationHandler<ServiceContext> = async (input) => {
if (!input.requiredField) {
throw new InvalidRequestError({
message: "Required field is missing"
});
}
return { /* success response */ };
};

API가 인증으로 보호되는 경우, 작업은 종종 누가 호출하는지 알아야 합니다. 권장되는 접근 방식은 핸들러에서 호출자의 신원을 한 번 확인하고 특정 작업에서 사용할 수 있도록 서비스 컨텍스트를 통해 전달하는 것입니다.

무단 케이스를 Smithy 오류로 모델링하여 적절한 403 응답으로 직렬화되도록 합니다. 예를 들어 model/src/operations/errors.smithy에 추가하고 신원이 필요한 모든 작업에서 참조합니다:

$version: "2.0"
namespace your.namespace
/// Thrown when the calling user cannot be determined
@error("client")
@httpError(403)
structure UnauthorizedError {
@required
message: String
}

먼저, src/context.ts에서 서비스 컨텍스트에 확인된 신원을 노출합니다. UnauthorizedError가 작업 내에서 던져지도록(Server SDK가 이를 403으로 직렬화하는 곳) 함수로 제공합니다:

import { Logger } from '@aws-lambda-powertools/logger';
import { Metrics } from '@aws-lambda-powertools/metrics';
import { Tracer } from '@aws-lambda-powertools/tracer';
export interface Identity {
sub: string;
username: string;
}
/**
* Context provided to all operations.
*/
export interface ServiceContext {
tracer: Tracer;
logger: Logger;
metrics: Metrics;
getIdentity: () => Promise<Identity>;
}

다음으로, src/identity.ts에 리졸버를 작성합니다. 호출자를 확인할 수 없을 때 UnauthorizedError를 던집니다. 구현은 선택한 auth 방법에 따라 다릅니다:

auth = iam

IAM 인증의 경우, API Gateway 이벤트에서 추출한 sub를 사용하여 Cognito에서 호출자를 조회합니다:

import { CognitoIdentityProvider } from '@aws-sdk/client-cognito-identity-provider';
import type { APIGatewayProxyEvent } from 'aws-lambda';
import { Identity } from './context.js';
import { UnauthorizedError } from './generated/ssdk/index.js';
const cognito = new CognitoIdentityProvider();
export const getIdentity = async (
event: APIGatewayProxyEvent,
): Promise<Identity> => {
const cognitoAuthenticationProvider =
event.requestContext?.identity?.cognitoAuthenticationProvider;
let sub: string | undefined = undefined;
if (cognitoAuthenticationProvider) {
const providerParts = cognitoAuthenticationProvider.split(':');
sub = providerParts[providerParts.length - 1];
}
if (!sub) {
throw new UnauthorizedError({ message: 'Unable to determine calling user' });
}
const { Users } = await cognito.listUsers({
// Assumes user pool id is configured in lambda environment
UserPoolId: process.env.USER_POOL_ID!,
Limit: 1,
Filter: `sub="${sub}"`,
});
if (!Users || Users.length !== 1) {
throw new UnauthorizedError({ message: `No user found with subjectId ${sub}` });
}
return { sub, username: Users[0].Username! };
};
auth = cognito

auth: 'cognito'를 사용하면 API Gateway Cognito User Pools 권한 부여자가 호출자가 Authorization 헤더에 제공하는 JWT를 확인하고 확인된 클레임을 event.requestContext.authorizer.claims의 이벤트에 배치합니다:

import type { APIGatewayProxyEvent } from 'aws-lambda';
import { Identity } from './context.js';
import { UnauthorizedError } from './generated/ssdk/index.js';
export const getIdentity = async (
event: APIGatewayProxyEvent,
): Promise<Identity> => {
const claims = event.requestContext?.authorizer?.claims as
| Record<string, string>
| undefined;
const sub = claims?.sub;
const username = claims?.username;
if (!sub || !username) {
throw new UnauthorizedError({ message: 'Unable to determine calling user' });
}
return { sub, username };
};

그런 다음 src/handler.ts에서 리졸버를 컨텍스트에 연결합니다:

import { Service } from './service.js';
import { getIdentity } from './identity.js';
// ...
const httpResponse = await serviceHandler.handle(httpRequest, {
tracer,
logger,
metrics,
getIdentity: () => getIdentity(event),
});

이제 작업에서 확인된 신원을 사용할 수 있습니다. 예를 들어 src/operations/echo.ts에서:

import { ServiceContext } from '../context.js';
import { Echo as EchoOperation } from '../generated/ssdk/index.js';
export const Echo: EchoOperation<ServiceContext> = async (input, ctx) => {
const identity = await ctx.getIdentity();
return { message: `${identity.username} says ${input.message}` };
};

Smithy 모델 프로젝트는 Smithy CLI를 사용하여 Smithy 아티팩트를 빌드하고 TypeScript Server SDK를 생성합니다:

Terminal window
pnpm nx build <model-project>

macOS 및 Linux에서 CLI는 mise에 의해 확인되며, 빌드가 필요에 따라 가져오므로 설치할 것이 없습니다 — 처음 빌드할 때 고정된 버전을 다운로드하고 캐시합니다.

이 프로세스는:

  1. Smithy 모델을 컴파일하고 검증합니다
  2. Smithy 모델에서 OpenAPI 사양을 생성합니다
  3. 타입 안전한 작업 인터페이스로 TypeScript Server SDK를 생성합니다
  4. dist/<model-project>/build/빌드 아티팩트를 출력합니다

백엔드 프로젝트는 컴파일 중에 생성된 SDK를 자동으로 복사합니다:

Terminal window
pnpm nx copy-ssdk <backend-project>

mise는 npm에 Windows 패키지를 게시하지 않으므로 Windows에서는 Smithy CLI를 직접 설치해야 하는 전제 조건입니다. Smithy CLI 설치 가이드를 따라 한 번 설치하고(예: winget install smithy 또는 scoop install smithy), smithyPATH에 있는지 확인하세요. Windows에서 생성된 Smithy 프로젝트는 mise를 통하지 않고 smithy를 직접 실행합니다.

또는 WSL 내에서 개발하면 빌드가 Linux 경로를 실행하고 mise가 CLI를 확인합니다 — 설치할 것이 없습니다.

Windows에서 생성된 프로젝트는 smithy를 직접 호출하는 compile 타겟을 커밋하므로 macOS 또는 Linux를 포함하여 다른 사람도 PATH에 Smithy CLI가 필요합니다. 해당 머신이 대신 mise를 통해 CLI를 확인하도록 하려면 아래 설명대로 타겟을 mise 명령으로 전환하세요.

macOS 및 Linux는 mise를 통해 CLI를 확인하고 Windows는 전역으로 설치된 CLI를 사용하지만, 모델 프로젝트의 project.json에서 compile 타겟의 명령을 편집하여 모든 플랫폼에서 둘 중 하나를 선택할 수 있습니다.

mise 대신 전역으로 설치된 Smithy CLI를 사용하려면 mise 접두사를 smithy로 바꾸세요:

project.json
{
"targets": {
"compile": {
"options": {
"commands": ["... npx -y mise@<version> exec smithy@<version> -- smithy build ..."]
"commands": ["... smithy build ..."]
}
}
}
}

mise가 CLI를 확인하도록 되돌리려면 npx -y mise@<version> exec smithy@<version> -- 접두사를 복원하세요.

제너레이터는 Rolldown을 사용하여 배포 패키지를 생성하는 bundle 타겟을 자동으로 구성합니다:

Terminal window
pnpm nx bundle <project-name>

Rolldown 구성은 rolldown.config.ts에서 찾을 수 있으며, 생성할 번들마다 항목이 있습니다. Rolldown은 정의된 경우 여러 번들을 병렬로 생성하는 것을 관리합니다.

생성기는 핫 리로딩이 있는 로컬 개발 서버를 구성합니다:

Terminal window
pnpm nx serve <backend-project>

생성기는 선택한 iac를 기반으로 CDK 또는 Terraform 인프라를 생성합니다.

API를 배포하기 위한 CDK 구성 요소는 common/constructs 폴더에 있습니다:

import { MyApi } from '@my-scope/common-constructs';
export class ExampleStack extends Stack {
constructor(scope: Construct, id: string) {
// Add the API to your stack
const api = new MyApi(this, 'MyApi', {
integrations: MyApi.defaultIntegrations(this).build(),
});
}
}

이것은 다음을 설정합니다:

  1. Smithy 서비스를 위한 AWS Lambda 함수
  2. 함수 트리거로서의 API Gateway REST API
  3. IAM 역할 및 권한
  4. CloudWatch 로그 그룹
  5. X-Ray 추적 구성
auth = cognito
auth = custom

REST API의 경우, 생성된 구성 요소는 기본적으로 AWS WAFv2 Web ACL을 API Gateway 스테이지와 연결합니다. Web ACL은 AWS 관리형 기본 규칙 세트(AWSManagedRulesCommonRuleSetAWSManagedRulesKnownBadInputsRuleSet)를 사용하여 OWASP Top 10을 포함한 일반적인 웹 공격으로부터 보호합니다. WAF 요청 로그는 CloudWatch Logs 그룹에 기록됩니다.

생성된 rest-api 구성 요소를 편집하여 규칙을 추가, 제거 또는 조정할 수 있습니다(예: 속도 기반 규칙 또는 추가 관리형 규칙 그룹 추가).

옵트아웃하려면(예: 자체 Web ACL을 연결하려면) enableWaffalse로 설정하세요:

const api = new MyApi(this, 'MyApi', {
integrations: MyApi.defaultIntegrations(this).build(),
enableWaf: false,
});

REST API의 경우, 생성된 인프라는 기본적으로 액세스 로깅을 활성화하여 요청당 하나의 구조화된 JSON 라인을 전용 CloudWatch Logs 그룹에 작성합니다. 로그 그룹은 고객 관리형 KMS 키로 암호화되며 1년 동안 보관됩니다.

API Gateway는 계정 수준의 CloudWatch Logs 역할을 사용하여 액세스 로그를 작성합니다. 이 역할은 AWS::ApiGateway::Account 설정에 구성되며, 이는 리전당 계정당 싱글톤입니다 — 리전의 모든 REST API에 대해 하나의 역할만 존재합니다. 독립적으로 배포된 여러 스택에서 이를 안전하게 관리하기 위해, 생성된 인프라는:

  • 작동하는 역할이 이미 설정되어 있지 않은 경우에만 공유 CloudWatch Logs 역할을 생성하고 계정에 구성하므로, 배포가 다른 스택이 소유한 역할을 덮어쓰지 않습니다.
  • 해체 시 계정 설정을 그대로 두므로, 하나의 스택을 삭제해도 리전의 다른 REST API에 대한 로깅이 비활성화되지 않습니다.

계정 역할은 ApiGatewayAccount 구성 요소에 의해 관리되며, 이는 ApiGatewayAccount.ensure(scope)를 통해 해결되는 스택 범위 싱글톤입니다. 각 REST API의 스테이지는 이에 의존하며, 역할은 Lambda 기반 사용자 지정 리소스에 의해 구성됩니다.

액세스 로그 형식은 API가 확장하는 RestApi 구성 요소에 의해 설정됩니다. 이를 사용자 지정하려면 생성된 packages/common/constructs/src/app/apis/my-api.ts에서 deployOptionssuper에 전달하되, 구성 요소가 이미 설정한 tracingEnabled를 유지하세요:

packages/common/constructs/src/app/apis/my-api.ts
super(scope, id, {
apiName: 'MyApi',
// ...
deployOptions: {
tracingEnabled: true,
accessLogFormat: AccessLogFormat.clf(),
},
...props,
});

AccessLogFormataws-cdk-lib/aws-apigateway에서 가져옵니다. 설정하지 않은 항목은 구성 요소의 기본값(표준 필드가 포함된 JSON 형식)을 유지합니다.

REST/HTTP API CDK 구성은 각 작업에 대한 통합을 정의하기 위한 타입 안전 인터페이스를 제공하도록 구성되어 있습니다.

CDK 구성은 아래에 설명된 대로 완전한 타입 안전 통합 지원을 제공합니다.

정적 defaultIntegrations를 사용하여 각 작업에 대해 개별 AWS Lambda 함수를 정의하는 기본 패턴을 활용할 수 있습니다:

new MyApi(this, 'MyApi', {
integrations: MyApi.defaultIntegrations(this).build(),
});

API 구성의 integrations 속성을 통해 타입 안전 방식으로 기본 AWS Lambda 함수에 액세스할 수 있습니다. 예를 들어, API가 sayHello라는 작업을 정의하고 이 함수에 일부 권한을 추가해야 하는 경우 다음과 같이 할 수 있습니다:

const api = new MyApi(this, 'MyApi', {
integrations: MyApi.defaultIntegrations(this).build(),
});
// sayHello is typed to the operations defined in your API
api.integrations.sayHello.handler.addToRolePolicy(new PolicyStatement({
effect: Effect.ALLOW,
actions: [...],
resources: [...],
}));

API가 shared 패턴을 사용하는 경우, 공유 라우터 Lambda는 api.integrations.$router로 노출됩니다:

const api = new MyApi(this, 'MyApi', {
integrations: MyApi.defaultIntegrations(this).build(),
});
api.integrations.$router.handler.addEnvironment('LOG_LEVEL', 'DEBUG');

각 기본 통합에 대해 Lambda 함수를 생성할 때 사용되는 옵션을 사용자 정의하려면 withDefaultOptions 메서드를 사용할 수 있습니다. 예를 들어, 모든 Lambda 함수를 Vpc에 배치하려면:

const vpc = new Vpc(this, 'Vpc', ...);
new MyApi(this, 'MyApi', {
integrations: MyApi.defaultIntegrations(this)
.withDefaultOptions({
vpc,
})
.build(),
});

특정 작업에 대한 기본 통합을 생성하는 데 사용되는 옵션을 사용자 정의하려면(다른 작업에 영향을 주지 않고) withOperationOptions 메서드를 사용할 수 있습니다. 예를 들어, 하나의 작업에 대해서만 Lambda 함수 타임아웃을 늘리려면:

const api = new MyApi(this, 'MyApi', {
integrations: MyApi.defaultIntegrations(this)
.withOperationOptions({
sayHello: {
timeout: Duration.seconds(60),
},
})
.build(),
});
// The selected operations remain default integrations, so they're still typed accordingly:
api.integrations.sayHello.handler.addToRolePolicy(new PolicyStatement({ ... }));

지정한 옵션은 기본 통합 옵션(및 withDefaultOptions를 통해 설정된 모든 옵션)과 병합됩니다. withOverrides를 통해 교체한 작업에 대해서는 옵션을 지정할 수 없습니다. 이러한 작업은 더 이상 기본 통합을 사용하지 않기 때문입니다.

호출 순서에 관계없이 withOperationOptionswithOverrides 모두에서 동일한 작업을 대상으로 하는 경우 타입 오류가 발생합니다.

withOverrides 메서드를 사용하여 특정 작업에 대한 통합을 재정의할 수도 있습니다. 각 재정의는 HTTP 또는 REST API에 대한 적절한 CDK 통합 구성으로 타입이 지정된 integration 속성을 지정해야 합니다. withOverrides 메서드도 타입 안전합니다. 예를 들어, getDocumentation API를 일부 외부 웹사이트에서 호스팅하는 문서를 가리키도록 재정의하려면 다음과 같이 할 수 있습니다:

new MyApi(this, 'MyApi', {
integrations: MyApi.defaultIntegrations(this)
.withOverrides({
getDocumentation: {
integration: new HttpIntegration('https://example.com/documentation'),
},
})
.build(),
});

또한 재정의된 통합은 api.integrations.getDocumentation을 통해 액세스할 때 더 이상 handler 속성을 갖지 않습니다.

통합에 추가 속성을 추가할 수 있으며 이는 타입에 따라 적절하게 지정되어 다른 유형의 통합을 추상화하면서도 타입 안전을 유지할 수 있습니다. 예를 들어 REST API에 대한 S3 통합을 생성했고 나중에 특정 작업에 대한 버킷을 참조하려는 경우 다음과 같이 할 수 있습니다:

const storageBucket = new Bucket(this, 'Bucket', { ... });
const apiGatewayRole = new Role(this, 'ApiGatewayS3Role', {
assumedBy: new ServicePrincipal('apigateway.amazonaws.com'),
});
storageBucket.grantRead(apiGatewayRole);
const api = new MyApi(this, 'MyApi', {
integrations: MyApi.defaultIntegrations(this)
.withOverrides({
getFile: {
bucket: storageBucket,
integration: new AwsIntegration({
service: 's3',
integrationHttpMethod: 'GET',
path: `${storageBucket.bucketName}/{fileName}`,
options: {
credentialsRole: apiGatewayRole,
requestParameters: {
'integration.request.path.fileName': 'method.request.querystring.fileName',
},
integrationResponses: [{ statusCode: '200' }],
},
}),
options: {
requestParameters: {
'method.request.querystring.fileName': true,
},
methodResponses: [{
statusCode: '200',
}],
}
},
})
.build(),
});
// Later, perhaps in another file, you can access the bucket property we defined
// in a type-safe manner
api.integrations.getFile.bucket.grantRead(...);

통합에 options를 제공하여 인증자와 같은 특정 메서드 옵션을 재정의할 수도 있습니다. 예를 들어 getDocumentation 작업에 Cognito 인증을 사용하려면:

new MyApi(this, 'MyApi', {
integrations: MyApi.defaultIntegrations(this)
.withOverrides({
getDocumentation: {
integration: new HttpIntegration('https://example.com/documentation'),
options: {
authorizer: new CognitoUserPoolsAuthorizer(...) // for REST, or HttpUserPoolAuthorizer for an HTTP API
}
},
})
.build(),
});

원하는 경우 기본 통합을 사용하지 않고 각 작업에 대해 직접 통합을 제공할 수 있습니다. 이는 예를 들어 각 작업이 다른 유형의 통합을 사용해야 하거나 새 작업을 추가할 때 타입 오류를 받고 싶을 때 유용합니다:

new MyApi(this, 'MyApi', {
integrations: {
sayHello: {
integration: new LambdaIntegration(...),
},
getDocumentation: {
integration: new HttpIntegration(...),
},
},
});

생성된 CDK API 구성은 두 가지 통합 패턴을 지원합니다:

  • isolated는 작업당 하나의 Lambda 함수를 생성합니다. 이것이 생성된 API의 기본값입니다.
  • shared는 단일 기본 라우터 Lambda를 생성하고 특정 통합을 재정의하지 않는 한 모든 작업에 재사용합니다.

isolated는 작업별로 더 세밀한 권한과 구성을 제공합니다. shared는 선택적 재정의를 허용하면서 Lambda 및 API Gateway 통합 확산을 줄입니다.

예를 들어, pattern'shared'로 설정하면 통합당 하나가 아닌 단일 함수를 생성합니다:

packages/common/constructs/src/app/apis/my-api.ts
export class MyApi<...> extends ... {
public static defaultIntegrations = (scope: Construct) => {
...
return IntegrationBuilder.rest({
pattern: 'shared',
...
});
};
}

작업이 Smithy에 정의되어 있으므로 코드 생성을 사용하여 타입 안전한 통합을 위해 CDK 구성 요소에 메타데이터를 제공합니다.

generate:<ApiName>-metadata 타겟이 공통 구성 요소 project.json에 추가되어 이 코드 생성을 용이하게 하며, packages/common/constructs/src/generated/my-api/metadata.gen.ts와 같은 파일을 생성합니다. 이것은 빌드 시 생성되므로 버전 관리에서 무시됩니다.

auth = iam

IAM 인증을 선택한 경우 grantInvokeAccess 메서드를 사용하여 API에 대한 액세스를 부여할 수 있습니다:

api.grantInvokeAccess(myIdentityPool.authenticatedRole);

React 웹사이트에서 API를 호출하려면 Smithy 모델에서 타입 안전한 클라이언트 생성을 제공하는 connection 생성기를 사용할 수 있습니다.

connection 생성기를 사용하여 이 프로젝트를 워크스페이스의 다른 프로젝트와 통합하세요. 다음 연결에는 이 프로젝트가 포함됩니다:

Smithy
React to Smithy APIReact 웹사이트에서 Smithy API 호출
SmithyAmazon Aurora
Smithy API to Relational DatabaseSmithy API를 Aurora 관계형 데이터베이스에 연결
SmithyAmazon DynamoDB
Smithy API to TypeScript DynamoDBSmithy API를 DynamoDB 테이블에 연결