이번 글에서는 DynamoDB 테이블에서 항목을 생성, 읽기, 업데이트 및 삭제하는 CRUD API를 생성합니다. API는 서버리스로 실행되므로 기본 인프라를 관리하지 않아도 되고 자동으로 확장됩니다.
실습 순서는 아래와 같이 진행됩니다.
[실습 순서]
1. DynamoDB 테이블 생성
2. Lambda 함수 생성
3. HTTP API 게이트웨이 생성
4. AWS Cloud9 IDE 생성
5. API Test
[1. DynamoDB 테이블 생성]
DynamoDB를 통해 원하는 양의 데이터를 저장 및 검색하고 어느 수준의 요청 트래픽도 처리할 수 있는 데이터베이스 테이블을 생성할 수 있습니다. 다운타임 또는 성능 저하 없이 테이블의 처리 능력을 확장 또는 축소할 수 있습니다.
Amazon DynamoDB 테이블을 사용하여 API용 데이터를 저장합니다. 각 항목에는 파티션 키로 사용하는 고유 ID가 있습니다. DynamoDB 콘솔로 이동하여 DynamoDB 테이블을 아래와 같이 생성합니다.
– Table name: http-crud-tutorial-items
– Primary key: id
[2. 람다 함수 생성]
Lambda는 서버를 프로비저닝하거나 관리하지 않고도 코드를 실행할 수 있게 해주는 컴퓨팅 서비스입니다. Lambda는 필요할 때만 코드를 실행하고 하루에 몇 번의 요청에서 초당 수천 개의 요청으로 자동으로 확장됩니다. API의 백엔드에 대한 Lambda 함수를 생성합니다.
이번 실습에서 생성하는 Lambda 함수는 DynamoDB에서 항목을 생성, 읽기, 업데이트 및 삭제 (CRUD)합니다. 함수는 API Gateway의 이벤트를 사용합니다.
Lambda에서 새 함수를 아래와 같이 생성합니다.
– Function name: http-crud-tutorial-function
– Runtime: Node.js 14.x
– Execution role: Create a new role from AWS Policy templates
– Role name: http-crud-tutorial-role
– Policy templates: Simple microservice permissions (DynamoDB와 상호 작용할 수 있는 권한을 Lambda 함수에 부여하는 정책입니다.)
함수를 생성하고 Console의 코드 소스 편집기에서 index.js를 열고 내용을 아래와 같이 수정합니다.
const AWS = require("aws-sdk"); const dynamo = new AWS.DynamoDB.DocumentClient(); exports.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 .delete({ TableName: "http-crud-tutorial-items", Key: { id: event.pathParameters.id } }) .promise(); body = `Deleted item ${event.pathParameters.id}`; break; case "GET /items/{id}": body = await dynamo .get({ TableName: "http-crud-tutorial-items", Key: { id: event.pathParameters.id } }) .promise(); break; case "GET /items": body = await dynamo.scan({ TableName: "http-crud-tutorial-items" }).promise(); break; case "PUT /items": let requestJSON = JSON.parse(event.body); await dynamo .put({ TableName: "http-crud-tutorial-items", Item: { id: requestJSON.id, price: requestJSON.price, name: requestJSON.name } }) .promise(); 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 }; };
Deploy 버튼을 클릭하여 함수를 업데이트합니다.
[3. HTTP API 생성]
Amazon API Gateway는 개발자가 모든 규모에서 API를 쉽게 게시, 유지 관리, 모니터링, 보호 및 운영할 수 있도록 하는 완전 관리형 서비스입니다. API Gateway를 사용하면 HTTP API 또는 REST API를 사용하여 RESTful API를 생성할 수 있습니다.
HTTP API를 사용하면 REST API보다 대기 시간이 짧고 비용이 저렴한 RESTful API를 생성할 수 있습니다. HTTP API를 사용하여 AWS Lambda 함수 또는 공개적으로 라우팅 가능한 HTTP 엔드포인트에 요청을 보낼 수 있습니다.
HTTP API는 Lambda 함수에 대한 HTTP 엔드포인트를 제공합니다. 이번 단계에는 빈 API를 만듭니다. 다음 단계에서는 API와 Lambda 함수를 연결하도록 경로 및 통합을 구성합니다.API를 생성하고 HTTP API의 경우 빌드를 선택합니다.
API 이름에 http-crud-tutorial-api 를 입력합니다. 경로 생성은 나중에 하고 건너뜁니다. API Gateway가 ($default)를 생성했는지 확인하고 Next를 누르고 생성합니다.
[3.1 HTTP API 게이트웨이 Routes 생성하기]
경로 백엔드 리소스에 들어오는 API 요청을 보내는 방법입니다. 경로는 HTTP 메서드와 리소스 경로의 두 부분으로 구성되고 4개의 경로를 생성합니다.
– GET /items/{id}
– GET /items
– PUT /items
– DELETE /items/{id}
AWS API Gateway에서 http-crud-tutorial-api 를 선택하고 왼쪽 패널에서 Routes를 선택 후 생성합니다.
Method는 DELET를 선택하고 경로에 /items/{id}를 입력합니다. 경로 끝의 {id}는 클라이언트가 요청할 때 API Gateway가 요청 경로에서 검색하는 경로 매개변수입니다. 이와 같은 방법으로 GET, DELETE, PUT에 대한 4개의 경로를 생성합니다.
모든 경로가 제대로 생성되었는지 확인합니다.
[3.2 HTTP API 게이트웨이 통합 생성하기]
통합 생성 백엔드 리소스에 경로를 연결합니다. 이후 단계에서 통합을 경로에 연결합니다. 이 예제 API의 경우 모든 경로에 사용하는 하나의 Lambda 통합을 생성합니다.
API Gateway에서 http-crud-tutorial-api 를 선택하고 왼쪽 패널에서 Integrations를 선택한 후 생성합니다.
경로에 통합을 연결하지 않고 건너뜁니다. Integration type에 Lambda function을 선택하고 http-crud-tutorial-function을 Lambda function으로 입력합니다.
[3.3 HTTP API 게이트웨이 경로에 통합 연결하기]
DynamoDB에 대한 HTTP API
모든 API 경로에 통합을 연결한 후 클라이언트가 경로를 호출할 때 Lambda 함수가 호출됩니다.
API Gateway에서 http-crud-tutorial-api를 선택하고 왼쪽 패널에서 Integrations를 선택합니다. 아래에서 http-crud-tutorial-function을 선택합니다.
Attach integration을 선택하고 모든 경로에 대해서 이 작업을 반복합니다. AWS Lambda 통합이 연결되었다는 것을 확인할 수 있습니다.
이제 경로 및 통합이 포함된 HTTP API가 있으므로 API를 테스트할 수 있습니다.
[4. AWS Cloud9 생성하기]
AWS Cloud9은 통합 개발 환경 또는 IDE입니다.
AWS Cloud9 IDE는 여러 프로그래밍 언어와 런타임 디버거 및 기본 제공 터미널을 갖춘 강력한 코드 편집 환경을 제공합니다. 소프트웨어를 코딩, 빌드, 실행, 테스트 및 디버깅하기 위한 도구 모음을 갖추고 있으며 클라우드에 소프트웨어를 릴리스하는 데에도 도움이 됩니다.
AWS Cloud9 콘솔에서 Create environment 버튼을 클릭합니다. Cloud9의 인스턴스 옵션을 다음과 같이 구성합니다.
– Environment type: create a new EC2 instance for environment (direct access)
– Instance type: t2.mirco- Platform: Amzaon Linux2
API 테스트를 위한 터미널을 준비합니다.
[5. API Test]
Curl 명령어를 사용하여 API가 작동하는지 확인하겠습니다. API를 호출할 URL를 가져오기 위해서 API Gateway로 이동하고 URL을 기록해 둡니다.
다음 명령어는 Cloud9 터미널에서 진행합니다.
# 이전 단계에서 생성한 Invoke URL을 사용 export INVOKE_URL="https://abcdef123.execute-api.eu-west-1.amazonaws.com"
아래 명령어를 사용하여 DynamoDB 테이블에 데이터를 입력하고, 가져오고 삭제하는 테스트를 진행하겠습니다. DynamoDB 콘솔로 이동하여 직접 테이블 항목을 확인해보세요.
# PUT curl -X "PUT" -H "Content-Type: application/json" -d "{ \"id\": \"abcdef234\", \"price\": 12345, \"name\": \"myitem\" }" $INVOKE_URL/items # GET curl -s $INVOKE_URL/items | js-beautify # GET curl -s $INVOKE_URL/items/abcdef234 | js-beautify # DELETE curl -X "DELETE" $INVOKE_URL/items/abcdef234
[마무리]
DynamoDB, API Gateway, Lambda, Cloud9을 이용하여 CRUD를 만들어봤습니다. 이번 글에서는 간단하게 단일 Lambda 함수를 사용하였지만, Best Practice로는 각 경로에 대해 별도의 기능을 만들어야 합니다. 또한 Lambda 함수에서 관리형 정책을 사용했지만 최소 권한을 부여하여 IAM 정책을 생성하는 것을 권유 드립니다.
[참고자료]