현재 개발하고 있는 슬랙봇을 Serverless로 배포하기 위해 Aws Lambda를 사용하였습니다. 현 Serverless 프레임워크를 사용하여 Lambda까지 만든 상황입니다.
문제는 slash commands의 [ /제출 ] 명령어가 제대로 실행되지 않았습니다. 이 문제를 해결하기 위해 Lambda안에 기본적으로 내장되어 있는 Cloud Watch의 log를 살펴보았습니다.
Log를 보아하니 awsLambdaReceiver는 실행이 되는 상황입니다. 즉 Slack Event는 제대로 처리되지만 그에 대응되는 Slack handler가 Lambda에 등록되지 않았기 때문에 발생한 문제였습니다.
현재 코드를 보면, app.ts에서 2개의 handler를 Lambda에 등록시키는 코드입니다.
[app.ts]
import {submitNotionCommandHandler} from './server/notion/blog/handler/submitNotionCommandHandler';
import {uploadNotionBlogViewHandler} from './server/notion/blog/handler/uploadNotionBlogViewHandler';
import { notion } from './server/utils/appModule/notion/notion';
import { app } from './server/utils/appModule/slack/slack';
submitNotionCommandHandler(app);
uploadNotionBlogViewHandler(app,notion);
handler.ts는 Lambda함수에 등록된 handler들을 Slack과 연결이 되며, Slack에서 발생하는 모든 event들을 등록된 handler에게 전달합니다.
[handler.ts]
import { AwsCallback, AwsEvent, AwsResponse } from "@slack/bolt/dist/receivers/AwsLambdaReceiver";
import { awsLambdaReceiver } from "../../appModule/lambdaReciver/awsLambdaReceiver";
export const handler = async(
event: AwsEvent,
context: any,
callback: AwsCallback
): Promise<AwsResponse> => {
const slackHandler = await awsLambdaReceiver.start();
console.log('awsLambdaReceiver 실행');
return slackHandler(event, context, callback);
}
handler가 트리거 되기 위해서는 먼저 Lambda에 해당 handler를 등록해야 하는 데, 위의 코드처럼 작성하면 먼저 Lambda함수에 등록된 handler들을 Slack에 등록합니다.
하지만 Lambda에는 어떤 handler도 등록되어 있지 않습니다. 왜냐하면 실행순서는 handler.ts부터 실행되기 때문입니다.
즉, awsLambdaReceiver.start()이 실행되기 전에 먼저 handler를 Lambda에 등록해야 합니다.
awsLambdaReceiver.start()가 실행되기 전에 먼저 handler를 Lambda에 등록시킵니다.
import { AwsCallback, AwsEvent, AwsResponse } from "@slack/bolt/dist/receivers/AwsLambdaReceiver";
import { awsLambdaReceiver } from "../../appModule/lambdaReciver/awsLambdaReceiver";
import { submitNotionCommandHandler } from "../../../notion/blog/handler/submitNotionCommandHandler";
import { uploadNotionBlogViewHandler } from "../../../notion/blog/handler/uploadNotionBlogViewHandler";
import { app } from "../../appModule/slack/slack";
import { notion } from "../../appModule/notion/notion";
export const handler = async(
event: AwsEvent,
context: any,
callback: AwsCallback
): Promise<AwsResponse> => {
submitNotionCommandHandler(app); //추가
uploadNotionBlogViewHandler(app, notion); //추가
const slackHandler = await awsLambdaReceiver.start();
console.log('awsLambdaReceiver 실행');
return slackHandler(event, context, callback);
}
순서를 바꾸니 정상적으로 handler가 트리거 되는 것을 확인할 수 있습니다.
어떤 프로그램이던간에 초기화의 순서는 정말 중요한 것 같습니다😂 handler의 초기화 순서를 다시 한 번 정리해 봅시다.
1) Slack handler를 Lambda에 등록시킵니다.
2) 등록된 handler들은 해당 Lambda함수의 메모리에 올라갑니다.(쉽게 정의하자면 handler들의 코드가 등록됩니다)
3) awsLambdaReceiver.start()
를 호출하여 Slack과 연결하며, Slack으로부터 event를 받을 준비를 합니다.
4) Slack event가 발생할 때 Lambda 함수는 이미 등록된 handler를 사용하여 해당 event를 처리합니다.
→ 부과적으로 더 설명하자면 사용자가 Slack에서 발생시킨 event들은 API Gateway를 통해 Lambda 함수로 라우팅되며 Lambda 함수 내에서 적절한 handler가 해당 event를 처리합니다.