API Gateway, Lambda, DynamoDB 연결하기

읽기 전

  • 불필요한 코드나 잘못 작성된 내용에 대한 지적은 언제나 환영합니다. (예시 코드는 works on my machine 상태라 다르게 작동될 수 있습니다.)
  • Udemy강의(AWS Serverless APIs & Apps - A Complete Introduction)를 기반으로 작성되었습니다. 필자의 프로젝트 요구사항에 맞춰 일부 변형하였으니 자세한 이해를 원하신다면 결제해서 수강해보시길 권장드립니다. 좋은 강의라고 생각합니다. 항상 할인 중이니 저렴한 가격에 줍줍하세요
  • 외부 클라이언트에서 API를 호출하여 DynamoDB에 저장된 데이터를 조회하고 새로운 데이터를 삽입합니다. 삭제는 이전 포스팅과 동일하므로 생략합니다.

이번 글에서 할 일

AWS_Serverless_005_01

위 그림에 표시된 영역을 구현해보려 합니다. 이전 단계에서 모두 작업했던 내용으로 단순 검증 정도만 작성할 예정이니 다음 포스팅으로 넘어가도 됩니다.

API Gateway에서 DynamoDB 데이터 다루기

POST 메소드 호출

이전 포스팅에서 Lambda 콘솔의 테스트 이벤트를 구성한 뒤 실행하여 DynamoDB 테이블에 접근하였다. 항상 Lambda에서 요구하는 데이터에 대해 API Gateway가 제대로 받았는지 확인하는 과정을 유념해야 한다. 이는 모델을 생성, 적용하고 Request 데이터를 매핑하여 적용할 수 있다. 이전 포스팅에서 성공적으로 수행되고 있음을 확인하였다. API Gateway에서 입력된 Request 데이터를 DynamoDB에 저장하기 위해 임의로 고정했던 값들을 다시 event 객체에서 참조하도록 바꾸어주었다.

import json
import boto3
from random import randint

dynamodb = boto3.client('dynamodb')

def lambda_handler(event, context):
    response = dynamodb.put_item(
        TableName = 'basic-dynamo',
        Item = {
            'UserId' : {
                'S' : 'user_' + str(randint(1,999999)).zfill(6)
            },
            'prevScore' : {
                'N' : event['prevScore']
            },
            'prevRank' : {
                'N' : event['prevRank']
            },
            'currScore' : {
                'N' : event['currScore']
            },
            'currRank' : {
                'N' : event['currRank']
            }
        })

    return "stored data successfully"

Lambda에서 입력된 값에 대해 따로 String 처리를 하지 않으므로 이전 단계인 API Gateway에서 String으로 전달하게끔 Integration Request(통합 요청)의 매핑 템플릿을 수정하자. 우측 입력값을 참조하는 코드에 따옴표로 감싸주면 스트링으로 변환해준다.

AWS_Serverless_005_02

임의의 값을 Request body(요청 본문)에 입력하여 테스트를 수행한다.

AWS_Serverless_005_03

DynamoDB 테이블에서 데이터를 확인하면 성공적으로 저장되었음을 확인하였다.

AWS_Serverless_005_04

GET 메소드 호출

이전 GET 메소드를 호출할 시에는 경로 파라미터 여부에 따라 데이터를 조회하는 방식이었지만 'single' 값에 대해선 특정 데이터를 조회하는 코드를 작성했었다. 이번에는 쿼리 문자열에 값을 입력하여 특정 Id값을 갖는 레코드를 조회해보자. UserId 값을 기준으로 검색하려 하기에 경로 파라미터 이외에 쿼리 문자열을 입력해주자.

AWS_Serverless_005_05

Lambda 함수에 값을 제대로 전달하기 위해 Integration Request(통합 요청) 탭의 매핑 템플릿을 수정하자.

AWS_Serverless_005_06

이전에 정의했던 GET 메소드에 연결된 Lambda 함수(basic-get-data)를 수정한다. 경로 파라미터가 'single'일 경우 입력받은 값을 검색한다.

import json
import boto3

dynamodb = boto3.client('dynamodb')

def lambda_handler(event, context):
    type = event['type']
    UserId = event['UserId']
    done = False
    start_key = None
    items = []
    if type == 'all':
        while not done:
            if start_key:
                scan_kwargs['ExclusiveStartKey'] = start_key
            response = dynamodb.scan(
                TableName = 'basic-dynamo'
                )
            start_key = response.get('LastEvaluatedKey', None)
            done = start_key is None
        for item in response['Items']:
            items.append({
                'UserId': item['UserId']['S'],
                'prevScore': item['prevScore']['N'],
                'prevRank': item['prevRank']['N'],
                'currScore': item['currScore']['N'],
                'currRank': item['currRank']['N']
            })
        return items
    elif type == 'single':
        item = dynamodb.get_item(
            Key = {
                'UserId':{
                    'S': UserId
                }
            },
            TableName = 'basic-dynamo')['Item']
        return [{
            'UserId': item['UserId']['S'],
            'prevScore': item['prevScore']['N'],
            'prevRank': item['prevRank']['N'],
            'currScore': item['currScore']['N'],
            'currRank': item['currRank']['N']
        }]
    else:
        return "OOPS! Invalid Path Params"

이제 다시 API Gateway로 돌아와서 호출하면 성공적으로 조회됨을 확인할 수 있다.

AWS_Serverless_005_07

외부에서 호출된 API 기능 테스트

API Gateway에서 DynamoDB까지 성공적으로 연결되어 기능함을 확인하였으니 이제 외부에서 호출해보려 한다. API를 배포하고서 외부에서 연결을 생성한 뒤 Request를 전송하는 코드를 저번과 같이 작성하였다.

var conn = new XMLHttpRequest();
conn.open('POST','https://imdto253jj.execute-api.ap-northeast-2.amazonaws.com/dev/basic-api-res');
conn.onreadystatechange = function (event){
  console.log(event.target.response);
}
conn.setRequestHeader('Content-Type', 'application/json');
conn.send(JSON.stringify({prevScore: 3153, prevRank: 5, currScore: 5908, currRank: 10}));            

코드 실행 결과 응답이 정상적으로 출력되었다.

AWS_Serverless_005_08

DB 테이블을 조회하면 코드에 입력했던 값이 새롭게 삽입되었음을 확인할 수 있다.

AWS_Serverless_005_09

GET 메소드의 경우에도 경로 파라미터에 'all'을 입력했을 경우 테이블에 저장된 모든 값이 출력됨을 확인할 수 있다.

AWS_Serverless_005_10

경로 파라미터에 'single'을 입력했을 경우 쿼리 문자열을 추가하여 요청하였다. 콘솔 화면에 출력된 결과를 보면 정상적으로 기능함을 확인하였다

AWS_Serverless_005_11

DELETE 메소드를 호출함에 따라 삭제하고자 하는 UserId를 작성하여 요청하였다. 콘솔화면에 정상적으로 삭제되었다는 메시지를 확인할 수 있다.

AWS_Serverless_005_12

아래와 같이 방금 삭제를 요청했던 UserId 값을 갖는 레코드가 성공적으로 삭제되었다.

AWS_Serverless_005_13

+ Recent posts