AWS 서비스를 사용하여 CRUD API 생성하기

이번 글에서는 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 정책을 생성하는 것을 권유 드립니다.


[참고자료]

Leave a Comment