API Gateway + Lambda + DynamoDB를 사용하여 서버 없는 API 만들기

Serverless Frammework 콤보 API Gateway와 람바다, 다이나모DB를 활용한 API 제작 방법을 소개한다.

전제 조건


Serverless Framework가 설치되어 AWS의 계정이 설정된 전제로 진행됩니다.
운영 환경의 Serverless Framework 버전은 2.29.0이고 Lambda가 사용하는 언어는 Pythn 3.8이다.

생성할 API


간단한 ToDo 목록 API를 생성합니다.생성할 API는 다음과 같은 네 가지입니다.
POST   /todo          : 新規ToDoリスト作成
GET    /todo/{todoId} : ToDoの取得
PUT    /todo/{todoId} : ToDoの更新
DELETE /todo/{todoId} : ToDoの削除

DynamoDB 테이블 만들기


먼저 ToDo 목록을 관리하는 DB를 만듭니다.
serverless.ymlresources에 클라우드 포메이션 형식으로 기록되어 다이나마이트 DB의 자원을 만들 수 있습니다.
이번에는 아래에 기재된ToDoTable 탁자를 제작한다.DynamoDB의 테이블에 주 키가 있어야 하기 때문에 주 키에 todo_id 이 키를 지정했습니다.
serverless.yml
resources:
  Resources:
    todoTable:
      Type: AWS::DynamoDB::Table
      Properties:
        TableName: ToDoTable
        AttributeDefinitions:
          - AttributeName: todo_id
            AttributeType: S
        KeySchema:
          - AttributeName: todo_id
            KeyType: HASH
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1
AWS의 무료 프레임으로 시도하고 싶어 사전 설정 모드를 설정했다.주문형ProvisionedThroughput을 주문형BillingMode: PAY_PER_REQUEST으로 변경하려면 주문형으로 제작한다.설정 상세 정보는 AWS용 브로셔 등을 참조하세요.
API의 트래픽 제한을 하지 않을 때 다이나모DB가 공급 모드에서 실행될 경우 다이나모DB의 용량으로 인해 API 오류가 발생할 수 있습니다.따라서 자동 비례화로 수요에 따라 활용하는 것이 더욱 수월해진다.
그러나 주문형 모드에서는 자동으로 축척되고, 반대로 디도스와 같은 접근이 있어도 정상적으로 작동하는 경우 예상을 뛰어넘는 사용료가 발생한다.어쨌든 API의 액세스 제한 등을 잘 수행해 주십시오.

DynamoDB에 대한 액세스 권한 부여


제작ToDoTable돼 람다에서 방문해 미리 접근 권한을 부여했기 때문이다.
다음은 서버less입니다.yml에 추가하면 제작된 람다에 IAM Policy가 부여된다.그나저나 예전에는 provider.iam.role.statements였으나 지금은 Deprecation입니다.
serverless.yml
provider:
  # name, runtimeなどの記述は省略
  iam:
    role:
      statements:
        - Effect: "Allow"
          Action:
            - dynamodb:GetItem
            - dynamodb:PutItem
            - dynamodb:UpdateItem
            - dynamodb:DeleteItem
          Resource: "arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/ToDoTable"
DynamoDB 관련 설정이 완료되면 방문provider.iamRoleStatements API를 제작한다.

ToDo 등록 API 작성


먼저 ToDo를 등록하기 위해 POST 메소드의 API를 만듭니다.
파이썬의 코드는 다음과 같지만 오류 처리 등은 생략되었으니 이 전제에서 보십시오.
todo.py
import json
import random
import string

import boto3

dynamodb = boto3.resource("dynamodb")
table = dynamodb.Table("ToDoTable")

def post_todo(event, context):
    body = json.loads(event.get("body"))
    todo = body.get("todo")
    todo_id = "".join(random.choices(string.ascii_letters + string.digits, k=12))
    item = {"todo_id": todo_id, "todo": todo}
    table.put_item(Item=item)
    response = {"statusCode": 200, "body": json.dumps(item)}
    return response
API의 요청은 JSON의 요청으로 가정하므로ToDoTable dictbody로 변환합니다.json.loads 키의 데이터를 ToDo 데이터로 처리합니다.
보토 3todo 방법으로 다이나모DB에 ToDo를 등록했다.등록 시 주 키워드put_item가 필수적이기 때문에 알파벳 숫자의 무작위 값을 자동으로 생성하고 설정합니다.
serverless.ymltodo_id에 추가된 내용은 다음과 같다.
serverless.yml
functions:
  postTodo:
    handler: todo.post_todo
    events:
      - httpApi:
          path: /todo
          method: post
functionspath,/todomethod,경로로/todo를 만드는 POST 방법을 뜻합니다.
이거 디자인할게요.
$ sls deploy

post를 실행하여 API 작업 확인


디버그 후 API를 실행해 보십시오.POST /todo에 JSON을 추가하여 POST에서 팟캐스트합니다.
또한 헤더에 body를 설정하지 않으면 Content-Type: application/json를 JSON으로 처리하지 않으므로 주의하십시오.
요청
$ curl -XPOST -H "Content-Type: application/json" 'https://<yourapigatewayid>.execute-api.ap-northeast-1.amazonaws.com/todo' -d '{"todo":"コーヒーを買う"}' | jq .
{
  "todo_id": "iAx50hjXLiFB",
  "todo": "コーヒーを買う"
}
body은 그것이 정상적으로 등록되었기 때문{"todo":"コーヒーを買う"}과 함께 응답하여 돌아왔습니다.
그런 다음 데이터에 액세스하기 위한 GET/PUT/DELETE 메서드의 API를 생성합니다.

GET/PUT/DELETE 방법의 API 제작


GET/PUT/DELETE 메서드로 API를 만들 때 서버less입니다.다음은 yml입니다.
serverless.yml
functions:
  getTodo:
    handler: todo.get_todo
    events:
      - httpApi:
          path: /todo/{todoId}
          method: get
  putTodo:
    handler: todo.put_todo
    events:
      - httpApi:
          path: /todo/{todoId}
          method: put
  deleteTodo:
    handler: todo.delete_todo
    events:
      - httpApi:
          path: /todo/{todoId}
          method: delete
POST 때와 다른 점은 경로 매개변수todo_id가 포함되어 있다는 점입니다.GET/PUT/DELETE에 관해서는 특정 ToDo에 대한 작업이기 때문에 설정{todoId}했습니다.
또한 여기에 지정된 중괄호 안의 변수는 람다{todoId}에 전달되는 event에 포함됩니다.
다음은 파이썬 코드를 기록합니다.
todo.py
def get_todo(event, context):
    todo_id = event["pathParameters"]["todoId"]
    res = table.get_item(Key={"todo_id": todo_id})
    item = res.get("Item")
    response = {"statusCode": 200, "body": json.dumps(item)}
    return response

def put_todo(event, context):
    todo_id = event["pathParameters"]["todoId"]
    body = json.loads(event.get("body"))
    todo = body.get("todo")
    item = {"todo_id": todo_id, "todo": todo}
    table.update_item(
        Key={"todo_id": todo_id},
        UpdateExpression="set todo=:todo",
        ExpressionAttributeValues={":todo": todo},
    )
    response = {"statusCode": 200, "body": json.dumps(item)}
    return response

def delete_todo(event, context):
    todo_id = event["pathParameters"]["todoId"]
    table.delete_item(Key={"todo_id": todo_id})
    response = {"statusCode": 200, "body": json.dumps({"todo_id": todo_id})}
    return response
경로 파라미터는 pathParametersevent에 포함되어 있으며, pathParameters라면 event["pathParameters"]["todoId"]를 얻을 수 있습니다.
POST에서는 DynamoDB에 데이터를 새로 만들기 위해todoId 방법을 사용했습니다.GET/PUT/DELETE는 각각 put_item, get_item, update_item를 사용한다.
각 방법의 사용 방법은 AWS 문서 등을 참조하십시오.
또한 이러한 DynamoDB 작업에 사용되는 방법을 실행하려면 권한이 필요합니다.그래서 첫 번째 서버less.ymldelete_item에 IAM 폴리시가 추가됐다.
그러면 만들어진 API를 디버깅합니다.
$ sls deploy

제작된 GET/PUT/DELETE 메서드의 API 확인


생성된 GET/PUT/DELETE 메서드의 API를 실행합니다.

provider.iam.role.statements의 실행


GET 메서드의 실행은 다음과 같습니다.DynamoDB에서 객체의 ToDo를 가져올 수 있습니다.
$ curl -XGET 'https://<yourapigatewayid>.execute-api.ap-northeast-1.amazonaws.com/todo/iAx50hjXLiFB' | jq .
{
  "todo_id": "iAx50hjXLiFB",
  "todo": "コーヒーを買う"
}

GET/todo/{todoId}의 실행


PUT 메서드의 실행은 다음과 같습니다.
$ curl -XPUT -H "Content-Type: application/json" 'https://<yourapigatewayid>.execute-api.ap-northeast-1.amazonaws.com/todo/iAx50hjXLiFB' -d '{"todo":"牛乳を買う"}' | jq .
{
  "todo_id": "iAx50hjXLiFB",
  "todo": "牛乳を買う"
}
PUT 메서드 실행 후 GET 메서드를 실행하더라도 객체의 업데이트를 확인할 수 있습니다.
$ curl -XGET 'https://<yourapigatewayid>.execute-api.ap-northeast-1.amazonaws.com/todo/iAx50hjXLiFB' | jq .
{
  "todo_id": "iAx50hjXLiFB",
  "todo": "牛乳を買う"
}

PUT/todo/{todoId}의 실행


DELETE 메서드의 실행은 다음과 같습니다.
$ curl -XDELETE 'https://<yourapigatewayid>.execute-api.ap-northeast-1.amazonaws.com/todo/iAx50hjXLiFB' | jq .
{
  "todo_id": "iAx50hjXLiFB"
}
DELETE 메서드가 실행된 후 GET 메서드를 실행하면 객체가 존재하지 않으므로 삭제를 확인할 수 있습니다.
$ curl -XGET 'https://<yourapigatewayid>.execute-api.ap-northeast-1.amazonaws.com/todo/iAx50hjXLiFB' | jq .
null


이번에 사용한 코드는 아래 Giithub 창고에 업로드되었습니다. 모든 코드를 확인하고 싶은 분들은 저쪽(v3.0 라벨은 이번 코드)을 보세요.
https://github.com/ombran/serverless-sample/tree/v3.0

좋은 웹페이지 즐겨찾기