Skip to content
This repository has been archived by the owner on Mar 18, 2020. It is now read-only.

Latest commit

 

History

History
59 lines (45 loc) · 4.38 KB

2019-05-17-TIL.md

File metadata and controls

59 lines (45 loc) · 4.38 KB
layout title slug tags
post
2019-05-17-TIL
190517-TIL
TIL

슬랙 사다리 챗봇 만들기 - heroku와 rtm

내가 일주일에 한 번은 반드시 슬랙 채팅방에 있는 사람들과 함께 사다리를 탄다는 사실을 깨닫고, 사다리를 타주는 슬랙 봇을 만들고자 했다.

목표는 단순하다. 내가 "사다리 1 / 2 / 3" 처럼 메세지를 입력하면, 슬랙 봇이 채팅방에 있는 사람들 목록과 매칭시켜서 결과를 답해주는 것이다. "A: 3, B: 1, C: 2"하는 식으로 말이다. 처음에는 rtm으로 간단하게 해결할 수 있을 거라고 생각했다. 일단 유저의 메세지에 반응하게끔 코드를 간단하게 짜서 헤로쿠에서 배포하였다. 하지만 배포한 직후에만 작동을 하고, 잠시라도 메세지를 보내지 않으면 sleep mode가 되었는지 메세지를 보내도 아무런 반응이 없었다. 다른 사람들의 블로그를 많이 찾아보았는데, 다들 rtm을 멀쩡히 쓰는 것 같았는데 무엇이 문제인지 이해하기 힘들었다. 그러다 챗봇을 만들어본 적 있는 동아리 선배분이 해답을 알려주셨다. 헤로쿠의 free plan은 web dyno라는 가상머신을 제공하는데, 일정 시간동안 http 요청이 오지 않으면 sleep mode가 된다. sleep mode인 상태에서 http 요청을 받으면 잠에서 깨어나는 데 시간이 조금 걸리며, 깨어난 이후 정상적으로 응답을 하게 된다. (그래서 헤로쿠가 왜 응답 속도가 늦냐는 질문글을 많이 볼 수 있기도 하다.)

챗봇이 유저의 메세지를 잘 인식하고 반응할 수 있는지를 테스트하고자 했다. rtm api를 사용하고 있었고, "사다리"라는 메세지를 유저가 보내면 챗봇이 "사다리를 타자"라고 응답을 하게끔 코드를 짰다.

const rtm = new RTMClient(token);
// 중략 
rtm.on('message', async (event) => {
    if(!event.text.includes("사다리")) {
        return
    } else {
        const reply = await rtm.sendMessage("사다리를 타자", event.channel)
        console.log(reply)
    }

확인을 해보면 배포 후 "사다리"라고 메세지를 보냈을 때는 곧장 "사다리를 타자"라는 응답이 정상적으로 오지만, 몇 초 지난 다음 다시 "사다리"라고 보내면 아무런 반응을 하지 않았다. (예상보다 굉장히 빠르게) sleep mode에 빠진 것이다. 이후 아무리 "사다리"라고 메세지를 보내도 아무런 응답이 없었다. web dyno가 sleep mode에서 깨어나지 못했기 때문이다.

말장난같지만 유저가 "사다리"라는 메세지를 보냈을 때 rtm은 유저가 "사다리"라는 메세지를 보냈다는 것을 알게될 뿐, 그 이상 그 이하도 아니다. 내부 구조는 알 수 없고, 또 관심사도 아니지만 중요한 것은 web dyno에게 http 요청이 온 것이 아니라는 것이다. rtm이 어떤 이벤트가 발생했는지 인지하는 것과 web dyno에게 http 요청이 오는 것은 별개이다.

구글 클라우드 플랫폼이나 개인용 서버에 올리면 문제가 없었을 것이다. 그래도 heroku가 어떤 것인지 한번 써보고 싶었고, 딜레이가 약간 발생해도 전혀 상관없는 챗봇이어서 rtm이 아닌 express를 이용해서 챗봇을 완성했다.

app.use(bodyParser.urlencoded({extended: true}));
app.listen(80);
app.post('/', async (req, res) => {
    const data = req.body;
    const text = data.text;
    const channelId = data.channel_id;
    const membersData = await web.conversations.members({
        channel: channelId,
    });
    const color = text.split('/');
    // 중략 
})

슬래시 커맨드를 이용해서 유저가 "/사다리 빨간색 / 노란색 / 초록색" 같이 입력하면, 채널에 속한 사람들의 id를 이용해서 사다리를 타고 그 결과를 알려주는 식으로 만들고자 했다. 해당 슬래시 커맨드가 발생하면, 슬랙 쪽에서 내가 지정해놓은 url로 http 요청이 오고, 그 요청을 받아 원하는 행위를 하는 형태이다. 이 경우 http 요청을 받게 되므로 sleep mode에 빠졌어도 깨어날 수 있다.

간단한 명령어 문법

명령어 순서인자 / 옵션 인자 pm2 start index.js --> pm2가 start 한다 index.js를

옵션인자 --name zombie-server --> 옵션으로 좀비서버라는 이름을 쓰겠다는 것