자습서: Lambda 및 DynamoDB를 사용한 CRUD API 구축 - Amazon API Gateway

자습서: Lambda 및 DynamoDB를 사용한 CRUD API 구축

이 자습서에서는 DynamoDB 테이블에서 항목을 생성, 읽기, 업데이트 및 삭제하는 서버리스 API를 생성합니다. DynamoDB는 완전관리형 NoSQL 데이터베이스 서비스로서 원활한 확장성과 함께 빠르고 예측 가능한 성능을 제공합니다. 이 자습서를 완료하는 데 약 30분이 소요되며 AWS 프리 티어 내에서 이를 수행할 수 있습니다.

먼저 DynamoDB 콘솔을 사용하여 DynamoDB 테이블을 생성합니다. 그런 다음, AWS Lambda 콘솔을 사용하여 Lambda 함수를 생성합니다. 그런 다음 API Gateway 콘솔을 사용하여 HTTP API를 생성합니다. 마지막으로 API를 테스트합니다.

HTTP API를 호출하면 API Gateway는 요청을 Lambda 함수로 라우팅합니다. Lambda 함수는 DynamoDB와 상호 작용하고 API Gateway에 대한 응답을 반환합니다. 그러고 나면 API Gateway가 응답을 반환합니다.

이 튜토리얼에서 생성하는 HTTP API의 개요입니다.

이 연습을 완료하려면 AWS 계정과 콘솔 액세스 권한이 있는 AWS Identity and Access Management 사용자가 있어야 합니다. 자세한 내용은 API Gateway를 시작하기 위한 사전 조건 단원을 참조하세요.

이 자습서에서는 를 사용합니다AWS Management Console 이 API 및 모든 관련 리소스를 생성하는 AWS SAM 템플릿은 template.yaml 단원을 참조하세요.

1단계: DynamoDB 테이블 생성

DynamoDB 테이블을 사용하여 API에 대한 데이터를 저장합니다.

각 항목에는 테이블의 파티션 키로 사용하는 고유 ID가 있습니다.

DynamoDB 테이블을 생성하려면
  1. https://console.aws.amazon.com/dynamodb/에서 DynamoDB 콘솔을 엽니다.

  2. [Create table]을 선택합니다.

  3. 테이블 이름http-crud-tutorial-items을(를) 입력합니다.

  4. 파티션 키(Partition key)id를 입력합니다.

  5. 테이블 생성을 선택합니다.

2단계: Lambda 함수 생성

API의 백엔드에 Lambda 함수를 생성합니다. 이 Lambda 함수는 DynamoDB에서 항목을 생성, 읽기, 업데이트 및 삭제합니다. 이 함수는 API Gateway의 이벤트를 사용하여 DynamoDB와 상호 작용하는 방법을 결정합니다. 단순화를 위해 이 자습서에서는 단일 Lambda 함수를 사용합니다. 가장 좋은 방법은 각 경로에 대해 별도의 함수를 생성하는 것입니다.

Lambda 함수를 만들려면
  1. https://console.aws.amazon.com/lambda에서 Lambda 콘솔에 로그인합니다.

  2. 함수 생성을 선택합니다.

  3. [함수 이름(Function name)]에 http-crud-tutorial-function을 입력합니다.

  4. 런타임에서 지원되는 최신 Node.js 또는 Python 런타임을 선택합니다.

  5. 사용 권한에서 [기본 실행 역할 변경(Change default execution role)]을 선택합니다.

  6. AWS 정책 템플릿에서 새 역할 생성을 선택합니다.

  7. [역할 이름(Role name)]에 http-crud-tutorial-role을 입력합니다.

  8. 정책 템플릿에서 Simple microservice permissions을(를) 선택합니다. 이 정책은 Lambda 함수에 DynamoDB와 상호 작용할 수 있는 권한을 부여합니다.

    참고

    이 자습서에서는 단순화를 위해 관리형 정책을 사용합니다. 가장 좋은 방법은 필요한 최소 권한을 부여하는 자체 IAM 정책을 생성하는 것입니다.

  9. 함수 생성을 선택합니다.

  10. 콘솔의 코드 편집기에서 Lambda 함수를 열고 내용을 다음 코드로 바꿉니다. [배포(Deploy)]를 선택하여 함수를 업데이트합니다.

Node.js
import { DynamoDBClient } from "@aws-sdk/client-dynamodb"; import { DynamoDBDocumentClient, ScanCommand, PutCommand, GetCommand, DeleteCommand, } from "@aws-sdk/lib-dynamodb"; const client = new DynamoDBClient({}); const dynamo = DynamoDBDocumentClient.from(client); const tableName = "http-crud-tutorial-items"; export const handler = async (event, context) => { let body; let statusCode = 200; const headers = { "Content-Type": "application/json", }; try { switch (event.routeKey) { case "DELETE /items/{id}": await dynamo.send( new DeleteCommand({ TableName: tableName, Key: { id: event.pathParameters.id, }, }) ); body = `Deleted item ${event.pathParameters.id}`; break; case "GET /items/{id}": body = await dynamo.send( new GetCommand({ TableName: tableName, Key: { id: event.pathParameters.id, }, }) ); body = body.Item; break; case "GET /items": body = await dynamo.send( new ScanCommand({ TableName: tableName }) ); body = body.Items; break; case "PUT /items": let requestJSON = JSON.parse(event.body); await dynamo.send( new PutCommand({ TableName: tableName, Item: { id: requestJSON.id, price: requestJSON.price, name: requestJSON.name, }, }) ); body = `Put item ${requestJSON.id}`; break; default: throw new Error(`Unsupported route: "${event.routeKey}"`); } } catch (err) { statusCode = 400; body = err.message; } finally { body = JSON.stringify(body); } return { statusCode, body, headers, }; };
Python
import json import boto3 from decimal import Decimal client = boto3.client('dynamodb') dynamodb = boto3.resource("dynamodb") table = dynamodb.Table('http-crud-tutorial-items') tableName = 'http-crud-tutorial-items' def lambda_handler(event, context): print(event) body = {} statusCode = 200 headers = { "Content-Type": "application/json" } try: if event['routeKey'] == "DELETE /items/{id}": table.delete_item( Key={'id': event['pathParameters']['id']}) body = 'Deleted item ' + event['pathParameters']['id'] elif event['routeKey'] == "GET /items/{id}": body = table.get_item( Key={'id': event['pathParameters']['id']}) body = body["Item"] responseBody = [ {'price': float(body['price']), 'id': body['id'], 'name': body['name']}] body = responseBody elif event['routeKey'] == "GET /items": body = table.scan() body = body["Items"] print("ITEMS----") print(body) responseBody = [] for items in body: responseItems = [ {'price': float(items['price']), 'id': items['id'], 'name': items['name']}] responseBody.append(responseItems) body = responseBody elif event['routeKey'] == "PUT /items": requestJSON = json.loads(event['body']) table.put_item( Item={ 'id': requestJSON['id'], 'price': Decimal(str(requestJSON['price'])), 'name': requestJSON['name'] }) body = 'Put item ' + requestJSON['id'] except KeyError: statusCode = 400 body = 'Unsupported route: ' + event['routeKey'] body = json.dumps(body) res = { "statusCode": statusCode, "headers": { "Content-Type": "application/json" }, "body": body } return res

3단계: HTTP API 생성

HTTP API는 Lambda 함수에 대한 HTTP 엔드포인트를 제공합니다. 이 단계에서는 빈 API를 생성합니다. 다음 단계에서는 API와 Lambda 함수를 연결하기 위한 경로 및 통합을 구성합니다.

HTTP API 생성하기
  1. https://console.aws.amazon.com/apigateway에서 API Gateway 콘솔에 로그인합니다.

  2. [API 생성(Create API)]을 선택한 다음 HTTP API에 대해 [빌드(Build)]를 선택합니다.

  3. API 이름에서 http-crud-tutorial-api을(를) 입력합니다.

  4. [Next]를 선택합니다.

  5. 경로 구성에 대해 [다음(Next)]을 선택하여 경로 생성을 건너뜁니다. 나중에 루트를 생성합니다.

  6. API Gateway가 생성하는 단계를 검토한 후 [다음(Next)]을 선택합니다.

  7. Create를 선택합니다.

4단계: 경로 생성

경로는 수신 API 요청을 백엔드 리소스로 보내는 방법입니다. 경로는 HTTP 메서드와 리소스 경로(예: GET /items), 이렇게 두 부분으로 구성됩니다. 이 예제 API의 경우 네 개의 경로를 생성합니다.

  • GET /items/{id}

  • GET /items

  • PUT /items

  • DELETE /items/{id}

경로 생성
  1. https://console.aws.amazon.com/apigateway에서 API Gateway 콘솔에 로그인합니다.

  2. API를 선택합니다.

  3. Routes(라우팅)를 선택합니다.

  4. Create를 선택합니다.

  5. 메서드(Method)에서 GET을(를) 선택합니다.

  6. 경로에 /items/{id}을(를) 입력합니다. 경로 끝의 {id}은(는) 클라이언트가 요청을 할 때 API Gateway가 요청 경로에서 검색하는 경로 파라미터입니다.

  7. Create를 선택합니다.

  8. GET /items, DELETE /items/{id}PUT /items에 대해 4-7단계를 반복합니다.

API에 GET /items, GET /items/{id}, DELETE /items/{id} 및 PUT /items에 대한 경로가 있습니다.

5단계: 통합 생성

백엔드 리소스에 경로를 연결하는 통합을 생성합니다. 이 예제 API에 대해 모든 경로에 사용할 Lambda 통합을 하나 생성합니다.

통합 생성하기
  1. https://console.aws.amazon.com/apigateway에서 API Gateway 콘솔에 로그인합니다.

  2. API를 선택합니다.

  3. [통합(Integrations)]을 선택합니다.

  4. [통합 관리(Manage integrations)]를 선택한 다음 [생성(Create)]을 선택합니다.

  5. [경로에 이 통합 연결(Attach this integration to a route)]을 건너뜁니다. 이후 단계에서 이 작업을 완료합니다.

  6. 통합 유형에서 Lambda 함수(Lambda Function)를 선택합니다.

  7. Lambda 함수에서 http-crud-tutorial-function을(를) 입력합니다.

  8. Create를 선택합니다.

6단계: 경로에 통합 연결

이 예제 API의 경우 모든 경로에 대해 Lambda 통합을 사용합니다. 모든 API의 경로에 통합을 연결한 후 클라이언트가 경로를 호출하면 Lambda 함수가 호출됩니다.

경로에 통합 연결하기
  1. https://console.aws.amazon.com/apigateway에서 API Gateway 콘솔에 로그인합니다.

  2. API를 선택합니다.

  3. [통합(Integrations)]을 선택합니다.

  4. 경로를 선택합니다.

  5. 기존 통합 선택에서 http-crud-tutorial-function을(를) 선택합니다.

  6. [통합 연결(Attach integration)]을 선택합니다.

  7. 모든 경로에 대해 4-6단계를 반복합니다.

모든 경로가 AWS Lambda 통합이 연결되어 있음을 보여줍니다.

콘솔이 모든 경로에서 AWS Lambda를 표시하여 통합이 연결되었음을 나타냅니다.

이제 HTTP API에 경로 및 통합이 연결되었으므로 API를 테스트할 수 있습니다.

7단계: API 테스트

API가 작동하는지 확인하려면 curl을 사용합니다.

API를 호출할 URL 가져오기
  1. https://console.aws.amazon.com/apigateway에서 API Gateway 콘솔에 로그인합니다.

  2. API를 선택합니다.

  3. API의 호출 URL을 기록해 둡니다. 세부 정보 페이지의 [호출 URL(Invoke URL)] 아래에 나타납니다.

    API를 생성하면 콘솔에 API의 호출 URL이 표시됩니다.
  4. API의 호출 URL을 복사합니다.

    전체 URL은 https://abcdef123.execute-api.us-west-2.amazonaws.com처럼 보입니다.

항목 생성 또는 업데이트하기
  • 다음 명령을 사용하여 항목을 생성하거나 업데이트합니다. 명령에는 항목의 ID, 가격 및 이름이 포함된 요청 본문이 포함됩니다.

    curl -X "PUT" -H "Content-Type: application/json" -d "{\"id\": \"123\", \"price\": 12345, \"name\": \"myitem\"}" https://abcdef123.execute-api.us-west-2.amazonaws.com/items
모든 항목 가져오기
  • 다음 명령을 사용하여 모든 항목을 나열합니다.

    curl https://abcdef123.execute-api.us-west-2.amazonaws.com/items
항목 가져오기
  • 다음 명령을 사용하여 ID별로 항목을 가져옵니다.

    curl https://abcdef123.execute-api.us-west-2.amazonaws.com/items/123
항목 삭제 방법
  1. 다음 명령을 사용하여 항목을 삭제합니다.

    curl -X "DELETE" https://abcdef123.execute-api.us-west-2.amazonaws.com/items/123
  2. 항목이 삭제되었는지 확인하려면 모든 항목을 가져옵니다.

    curl https://abcdef123.execute-api.us-west-2.amazonaws.com/items

8단계: 정리

불필요한 비용을 방지하려면 이 시작하기 연습의 일부로 생성한 리소스를 삭제하세요. 다음 단계에서는 HTTP API, Lambda 함수 및 관련 리소스를 삭제합니다.

DynamoDB 테이블 삭제
  1. https://console.aws.amazon.com/dynamodb/에서 DynamoDB 콘솔을 엽니다.

  2. 테이블을 선택합니다.

  3. [Delete Table]을 선택합니다.

  4. 선택을 확인하고 [삭제(Delete)]를 선택합니다.

HTTP API 삭제하기
  1. https://console.aws.amazon.com/apigateway에서 API Gateway 콘솔에 로그인합니다.

  2. API 페이지에서 API를 선택합니다. [ Actions]를 선택한 후 [Delete]를 선택합니다.

  3. 삭제를 선택합니다.

Lambda 함수 삭제하기
  1. https://console.aws.amazon.com/lambda에서 Lambda 콘솔에 로그인합니다.

  2. 함수 페이지에서 함수를 선택합니다. [ Actions]를 선택한 후 [Delete]를 선택합니다.

  3. 삭제를 선택합니다.

Lambda 함수의 로그 그룹 삭제하기
  1. Amazon CloudWatch 콘솔에서 로그 그룹 페이지를 엽니다.

  2. 로그 그룹 페이지에서 함수의 로그 그룹(/aws/lambda/http-crud-tutorial-function)을 선택합니다. 작업을 선택한 다음 로그 그룹 삭제를 선택합니다.

  3. 삭제를 선택합니다.

Lambda 함수의 실행 역할 삭제하기
  1. AWS Identity and Access Management 콘솔에서 역할 페이지를 엽니다.

  2. 함수의 역할(예: http-crud-tutorial-role)을 선택합니다.

  3. 역할 삭제를 선택합니다.

  4. 예, 삭제를 선택합니다.

다음 단계: AWS SAM 또는 AWS CloudFormation을 통한 자동화

AWS CloudFormation 또는 AWS SAM을 사용하여 AWS 리소스의 생성 및 정리를 자동화할 수 있습니다. 이 자습서의 AWS SAM 템플릿 예는 template.yaml 단원을 참조하세요.

예제 AWS CloudFormation 템플릿에 대해서는 예제 AWS CloudFormation 템플릿을 참조하세요.