Dynamodb + Lambda

주의할 점

이전에는 event, context, callback 을 사용했지만 세번째 인자 callback은 더이상 잘 사용되지 않는다고 한다. 현재는 status code를 포함한 response 구조를 가진 객체를 return 하면 된다.

Dynamodb로 작업하기

fetch data

데이터를 가져오는 방법은 두가지가 있다.

  1. scan : 전체 테이블 조회
  2. query : 조건부 테이블 조회

특정 속성을 사용해 검색하고 싶은 경우 query를 사용하게 된다. 이때 검색에 사용하고자 하는 속성은 Index로 설정되어있어야 사용이 가능하다.

✍🏻로직

1. DB에 저장된 데이터들의 UUID를 스캔한다.

const ddbScanData = await ddb.scan(scanParams).promise();
const scanParams = {
  TableName: "midibus-play-statistics",
  ProjectionExpression: "#id",
  ExpressionAttributeNames: {
    "#id": "uuid",
  },
};

function getUuid(data) {
  const uuidArr = {};
  data["Items"].forEach((e) => {
    let tempUuid = e["uuid"]["S"];
    if (!uuidArr[tempUuid]) uuidArr[tempUuid] = true;
  });
  return Object.keys(uuidArr);
}

id가 예약어이기 떄문에 ExpressionAttributeNames 로 예약어가 아닌 다른 변수명과 매핑시켰다. ProjectionExpression 은 조회할 항목을 고르는 설정이다. 여기서 설정한 항목들만 db에서 스캔해온다.

2. 조회한 UUID들의 play data 중 가장 최신의 timestamp를 가지는 데이터를 조회한다.

async function getLatesData(uuids) {
  const result = [];
  uuids.forEach(async (uuid) => {
    console.log("start query", uuid);
    try {
      const params = {
        TableName: "midibus-play-statistics",
        KeyConditionExpression: "#id = :v1",
        ExpressionAttributeValues: {
          ":v1": { S: uuid },
        },
        ExpressionAttributeNames: {
          "#id": "uuid",
        },
        Limit: 1,
        ScanIndexForward: false,
      };
      console.log(params);
      let latestData = await ddb.query(params).promise();
      console.log(latestData);
      result.push(latestData);
    } catch (err) {
      console.error(err);
    }
  });
  return result;
}

uuid가 Hash Key, timestamp 가 Range Key로 설정되어있다. timestamp가 sorting key이기 때문에 Limit를 1로 두고 ScanIndexForward 값을 false로 지정해 내림차순 정렬을 하도록 했다.

여기서 오류가 계속 발생했다. 결과값이 계속해서 빈 배열로 나왔다. 끝내 찾아낸 이유는 비동기 처리가 잘못 되었던 것이었다. 쿼리가 잘못 된 줄 알고 계속해서 쿼리문 API만 다시 작성했는데 uuid 하나 넣어서 실행시켜보니 동작했다!😅…

함수가 내가 생각한 대로 동작하지 않았던 이유는 forEach 내부의 익명 함수는 동기 함수가 아니기 때문이었다. 때문에 비동기적으로 return result 문이 먼저 동작하게 되어 빈 배열이 반환되고 프로그램이 종료하게 된다.