앞선 실습을 통해 노션 데이터베이스에 새 페이지를 notion API를 이용해 추가하는 방법에 대해 알아보았습니다. 이번 시간에서는 AWS Lambda로 해당 코드를 실행시켜 서버리스 환경에서 notion API를 실행시키는 실습을 진행하겠습니다.
진행에 앞서 AWS 계정과 AWS Lambda, eventBridge 서비스에 대한 사전 지식이 필요합니다.
먼저 Lambda 함수를 생성해줍시다. 런타임은 nodeJS 14버전으로 진행합니다. 실행 역할은 Lambda용 IAM Role을 생성하셨던 분들은 그대로 진행하시면 되고, 그게 아니라면 기존 Lambda 권한을 가진 새 역할을 생성해도 무방합니다. 다만 저는 AWS DynamoDB에서 쿼리 작업을 진행할 예정이기에 Lambda와 DynamoDB에 관한 권한이 허용되어있는 역할을 사용했습니다.
그다음은 환경변수를 먼저 설정해 줄 차례입니다. 앞서 진행한 실습에서 export문으로 DATABASE_ID 등을 설정해 둔 것을 기억하실 겁니다. Lambda 환경의 변수로 NOTION_DATABASE_ID, NOTION_KEY를 넣어줍시다. 어떤 값인지 기억이 안나 시는 분들은 실습 (1), (2)를 참고해서 진행해 주시길 바랍니다.
이제 Lambda가 동작할 로직을 작성해 줄 차례입니다. 하지만 우리의 코드는 패키지가 하나 필요합니다. notion-example 이라는 이름의 모듈이죠. Lambda에 패키지를 올리는 방법은 크게 세 가지입니다.
1. node_modules 디렉토리와 index.js , package.json을 모두 zip으로 압축해 Lambda에 올린다.
2. node_modules 디렉토리를 zip 해 Layer로 Lambda에 올리고, index.js 파일은 코드만 복사하여 붙여 넣는다.
3. docker로 구성해 ECR에 올린 후, image형식으로 Lambda에 올린다.
이번 실습에는 1번 방법으로 진행합니다. 곧 나올 CommonJS와 ES6 방식에 대한 설명을 위함입니다.
이전 실습에서 진행한 notion-example 디렉토리 전체를 zip으로 압축하고, 코드 소스에 [에서 업로드] - [.zip 파일]로 해당 압축파일을 올리면 성공적으로 옮겨집니다.
그다음 Lambda가 실행될 런타임 설정에서 핸들러를 변경해줘야 합니다. 핸들러 명은 본인이 작업하고 압축했던 디렉터리의 이름이 됩니다. 저의 디렉토리 이름은 'notion-example'이었기에 notion-example/index.handler로 변경한 모습입니다.
그다음 index.js를 조금 바꿔줘야 합니다. 이전 실습에서 진행할 때는 import ~ from ~ 문법, 즉 ES module 형식으로 모듈을 사용했습니다. 하지만 Lambda에서는 ES module이 지원이 아직은 되지 않아 오류가 납니다. 따라서 CommonJS 방식으로 구문을 바꿔줍시다.
const {Client} = require("./node_modules/@notionhq/client")
const notion = new Client({ auth: process.env.NOTION_KEY })
const databaseId = process.env.NOTION_DATABASE_ID
exports.handler = async (event) => {
try {
const response = await notion.pages.create({
parent: { database_id: databaseId },
icon: {
type: "emoji",
emoji: "📊"
},
properties: {
"제목": {
title: [
{
text: {
content: '오늘의 유저 리포트',
},
},
],
},
"Total User": {
number: 100,
},
"Today User": {
number: 100,
},
"Date": {
"date": {
"start": "2022-06-06"
}
}
},
})
console.log(response)
console.log("Success! Entry added.")
} catch (error) {
console.error(error.body)
}
}
추가로 module 형식이 아니니 package.json 도 다음과 같이 변경해 주어야 합니다.
{
"name": "notion-example",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"@notionhq/client": "^1.0.1"
}
}
이대로 실행시키면 잘 추가가 되는 모습을 볼 수 있습니다.
이제 Lambda로 Notion API를 활용을 할 수 있는 초석은 모두 닦았습니다. 여러 가지 개발자 생산성을 향상하기 위한 많은 자동화 작업을 할 수 있습니다. 예를 들어, Lambda로 크롤링을 할 수 있으니, 특정 사이트에서 크롤링 한 값들을 notion에 자동으로 업로드하는 작업도 가능하겠죠? 이와 같이 할 수 있는 작업들은 무궁무진하지만 간단하게 EventBridge로 트리거 시켜 매 정각마다 DynamoDB로부터 전체 유저 수와 오늘의 유저 수를 쿼리 하고, 자동으로 날짜별로 노션 데이터베이스에 업로드하는 과정을 설명드리겠습니다.
먼저 AWS EventBridge 서비스에 들어가 새 규칙을 만들어 봅시다. 매 정각마다 실행될 규칙을 만들 겁니다.
규칙 유형을 일정으로, 패턴에 대한 Cron 식을 (0 15 * * ? *) 다음과 같이 설정해 주면, 매 정각마다 실행되는 규칙을 만들 수 있습니다. 캡처된 화면은 GMT로, 현지 시각대로 보면 한국 시간 기준 정각임을 알 수 있습니다.
다음으로 넘어가서 Lambda-함수를 연결시키고 다시 Lambda 서비스 화면으로 돌아오면 트리거에 EventBridge가 추가된 모습을 볼 수 있습니다.
이제 코드를 수정하면 끝입니다. DynamoDB로부터 쿼리를 날려 그 결과를 notion에 올리는 과정입니다. DynamoDB관련 로직은 주의 깊게 보지 않으셔도 됩니다.
const {Client} = require("./node_modules/@notionhq/client")
const notion = new Client({ auth: process.env.NOTION_KEY })
const databaseId = process.env.NOTION_DATABASE_ID
let AWS = require("aws-sdk")
let documentClient = new AWS.DynamoDB.DocumentClient({
apiVersion: "2012-08-10",
})
exports.handler = async (event) => {
try {
let user_params = {
TableName: "User",
}
const user_query = await documentClient.scan(user_params).promise();
let nowDate = Date.now();
nowDate -= 43200 * 1000; // 60 seconds * 60 minutes = 1 hours * 12 = 1 days
let date = new Date(nowDate);
console.log("date = " + date);
var read_params = {
FilterExpression: "#timestamp > :timestamp",
ExpressionAttributeNames: {
"#timestamp": "timestamp",
},
ExpressionAttributeValues: {
":timestamp": nowDate,
},
TableName: "User_read",
}
const read_query = await documentClient.scan(read_params).promise();
const today = new Date();
const yyyy = today.getFullYear();
let mm = today.getMonth() + 1; // Months start at 0!
let dd = today.getDate();
if (dd < 10) dd = '0' + dd;
if (mm < 10) mm = '0' + mm;
let today_date = yyyy + '-' + mm + '-' + dd;
let today_date_mmdd = mm + '-' + dd;
const response = await notion.pages.create({
parent: { database_id: databaseId },
icon: {
type: "emoji",
emoji: "📊"
},
properties: {
"Title": {
title: [
{
text: {
content: today_date_mmdd + '오늘 유저 리포트',
},
},
],
},
"Total User": {
number: Number(user_query.Count),
},
"Today User": {
number: Number(read_query.Count),
},
"Date": {
"date": {
"start": today_date
}
}
},
})
console.log(response)
console.log("Success! Entry added.")
return {
statusCode: 200,
body: JSON.stringify('Notion Uploaded!'),
};
} catch (error) {
return {
statusCode: 500,
body: JSON.stringify('Notion Upload Fail...'),
};
}
};
이를 활용해 간단한 내부지표의 시각화에 사용 중인 모습입니다.
Notion에 올릴 용으로는 Lambda로 이 작업을 다 해줘야 하지만, 만약에 Slack으로 ChatOps를 하고 싶다, 하면 AWS Chatbot 서비스가 더 좋은 선택지일 것입니다. 그래프 형태의 시각화까지 간단하게 구성을 할 수 있도록 지원을 해주니까요.
다만 Notion으로 docs를 정리해야 할 작업도 분명 있을 것이고, 그 일이 반복적이고 자동화가 가능할 작업이다 하면 다음과 같이 Lambda를 작성해 두기만 하면 좋은 업무 효율성을 가져갈 것입니다.
'🐳AWS' 카테고리의 다른 글
AWS 엔지니어들은 Lambda를 어떻게 구현했을까 (1) : Firecracker 제작기 (7) | 2022.11.10 |
---|---|
[AWS] Lambda위에 자체 환경(Ubuntu)의 docker 컨테이너 올리기 (0) | 2021.11.23 |
[AWS] Step Function으로 Lambda 워크플로 자동화하기 (0) | 2021.09.08 |
[AWS] lambda에서 chrome-selenium 크롤링 환경 설정하기 (2) | 2021.08.26 |
[AWS][테라폼] 🐬 테라폼으로 AWS EC2 인스턴스 생성,삭제하기 (0) | 2021.06.19 |