이번 글에서는 아주 아주 간단한 슬랙봇을 만들어 보도록 하겠습니다.
봇(bot)이란? 봇은 인간이 하는 행동을 흉내내도록 만들어진 프로그램을 의미합니다. 예를 들어, 검색엔진의 웹 크롤러는 웹 사이트 정보를 자동으로 읽어들여 저장하는 프로그램이며, 이외에도 인터넷 채팅에서 자동 응답을 하도록 만든 채터봇 프로그램 등이 있습니다. (출처: 위키백과) 슬랙봇은 업무용 메신저인 슬랙(Slack)에서 위와 같은 역할을 할 수 있는 봇을 말합니다.
이번에 만들어 볼 봇은, 제가 하는 말을 그대로 두 번 따라 하는 앵무새 봇입니다.
내 말만 따라하는 봇을 워따 써!? 라고 생각하실 수 있겠지만, 내가 하는 말을 두 번 따라 하려면 세 가지 기능이 가능해야 합니다.
첫째, 내가 하는 말을 입력받을 수 있다.
둘째, 입력받은 말을 가공할 수 있다.
셋째, 가공한 말을 다시 나에게 출력할 수 있다.
이 세 가지 조건을 처리할 수 있다는 것은, 응용을 통해 다양한 봇을 만들 수 있는 기반이 될 수 있다는 뜻입니다.
자, 그럼 이제부터 봇을 직접 만들어 보도록 하겠습니다.
시작하기에 앞서
앞서, 말한 앵무새 봇은 일종의 챗봇이라고 할 수 있습니다. 메신저 상에서 사람을 대신해 특수한 기능을 수행하는 로봇의 일종이죠.
그리고 이러한 챗봇을 만들기 위해서는 최소 아래와 같은 조건이 필요합니다.
웹프로그래밍 언어(PHP, JSP, ASP)를 다루거나, 타 언어로 웹 서버를 구현 할 수 있다.
웹기반 지식과 HTTP 지식
데이터의 입력과 출력에 사용될 JSON 포맷에 대한 지식
위 세 가지 조건을 모두 다 충족하지 못하셔도 일단 따라하기만 하면 만들 수 있도록 최대한 쉽게 작성해 보도록 하겠습니다.
하지만, 앞으로 다양한 봇을 만들어 보고 싶다면 언급된 기술들에 대해서 천천히 공부해 보시기 바랍니다.
웹서버 구현하기
챗봇을 만든다는 것은 사용자가 입력한 채팅 메시지를 분석 및 가공하고 이를 다시 사용자에게 출력할 수 있는 프로그램이 필요하다는 뜻입니다. 따라서 우리는 24시간 동작하며, 사용자의 요청(메시지)를 받아 처리할 수 있는 서버를 구현해야 합니다.
조금 더 엄밀히 말하자면, 슬랙봇을 만들기 위해서는 웹서버를 구현해야 합니다. 왜냐하면, 슬랙이 지원하는 모든 API가 웹기반이기 때문입니다. 다른 대부분의 서비스도 웹기반의 API를 제공합니다.
웹서버를 만들 수 있는 방법은 매우 많지만, 이번 글에서는 요즘 핫하고 힙하다는 개발언어인 파이썬(Python)을 통해서 구현해 볼까 합니다. 웹기반이라는 자체가 표준을 통해 구현한다는 뜻이므로, 내용만 이해한다면 다른 언어로도 충분히 구현하실 수 있습니다.
일단 파이썬과 코딩을 도와줄 IDE인 파이참(PyCharm)을 다음의 링크를 참고하여 설치하시기 바랍니다.(파이썬은 3.6.x 버전을 사용하며, 파이참 커뮤니티 버전은 무료입니다.)
파이썬으로 웹서버를 처음부터 직접 구현할 수도 있지만, 인간은 도구를 쓰는 존재이므로, 이미 만들어져 있는 도구(라이브러리)를 가져다 쓰기로 하겠습니다.
파이썬의 대표적인 웹프레임워크로는 장고(Django)와 플라스크(Flask)가 있으며, 이번 웹서버를 만들어줄 도구는 플라스크를 사용하도록 하겠습니다. 나중에 기회가 되신다면 장고로 서버를 한번 구현해 보시기 바랍니다.
파이썬과 파이참의 설치가 완료 되었다면, pip 명령어를 통해 플라스크를 설치해보도록 하겠습니다. 아래의 명령어를 콘솔(윈도우) 또는 터미널(맥)에 입력해 주세요.
$ sudo pip install Flask # 윈도우 사용자라면 sudo는 입력하지 않아도 됩니다.
플라스크의 설치가 완료된 후, 파이참을 실행합니다.
파이참을 처음 설치하신 분은 프로젝트를 생성하여야 하는데, 원하시는 프로젝트명으로 프로젝트를 하나 만듭니다. 저는 그냥 기본값(untitled)으로 하였습니다.
해당 프로젝트 밑에 slack_server.py 파일을 하나 생성하고 다음의 코드를 붙여넣기 합니다.
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run(host=’0.0.0.0’, port=5000)
“Hello World!”를 보셨나요? 수고하셨습니다. 방금 웹서버 하나를 만들었습니다!
슬랙 웹훅 이해하기
자! 이제 웹서버도 준비 되었겠다, 슬랙에서 데이터를 넘겨받고 이를 가공해서 다시 슬랙으로 돌려 보내주면 우리의 앵무새 봇이 완성됩니다!
슬랙은 특정 이벤트가 발생하면 해당 이벤트를 나에게 넘겨 주거나, 또는 나의 웹서버에서 발생한 이벤트를 슬랙으로 전달하는 다양한 방법을 제공합니다. 이러한 다양한 방법 중, 우리는 가장 쉽고 간단한 방법인 아웃고잉 웹훅(Outgoing Webhook)을 사용할 것입니다.
아웃고잉 웹훅은 [슬랙] -> [사용자의 웹서버]로 데이터를 전달하는 역할을 합니다.
그럼 이제부터 아웃고잉 웹훅을 만들어 보도록 하겠습니다. 먼저, 아래의 주소로 접속해 주시기 바랍니다.
https://{your-team-url}.slack.com/apps/manage/custom-integrations
{your-team-url}은 내가 봇을 붙이고 싶은 채널을 가진 team으로 명시하시기 바랍니다.
위와 같은 화면이 보이셨나요? 그렇다면 화면의 “Outgoing WebHooks”를 클릭해 주세요.
그리고 “Add Configuration”과 “Add Outgoing WebHooks integration” 버튼을 클릭 합니다.
마지막으로 최종 설정 화면이 나타나게 되는데, 이 화면에서 우리가 설정해야 할 값은 아래와 같습니다.
Channel
어떤 채널에서 발생하는 메시지를 수신할 것인가?
전체(Any) 또는 하나의 채널만 지정할 수 있습니다.
Trigger Word(s)
어떤 단어로 시작하는 메시지만 수신할 것인가?
Channel을 Any로 선택하셨다면 필수사항 입니다. 여러 단어를 콤마로 구분하여 등록할 수 있습니다.
URL(s)
선택한 Channel에서 메시지가 발생하면 어느 URL로 해당 메시지를 전달해 줄 것인가?
URL을 라인으로 구분해서 여러 개 등록할 수 있습니다.
앞서 우리가 구현한 웹서버 주소를 입력하면 됩니다.
(자세한 내용은 아래에서 설명하겠습니다)
Customized Name
봇 이름
Customize Icon
봇 아이콘
저는 iconfinder.com에서 앵무새 아이콘을 하나 찾아서 적용해 보았습니다.
마지막으로 “Save Settings” 클릭!
웹서버 더 자세히 구현하기
저는 앞서 만든 웹서버를 자체 서버에 올려두었습니다.
자체 서버의 아이피 주소는 192.168.0.8 인데요. 이 주소로 슬랙은 데이터를 넘겨줄 수 없습니다. 왜냐!? 내부에서만 사용되는 사설 아이피이기 때문이죠. 그래서 공유기를 찾아서 공유기에 할당된 공인 아이피를 확인하고 포트포워딩을 설정하였습니다.
내가 쓰는 공유기가 iptime 이라면 여기를 참고하시기 바랍니다.
공유기에서 확인한 공인 아이피 주소: 1.215.xxx.70
자체 서버 아이피 주소: 192.168.0.8
웹서버가 돌아가는 포트 번호: 5000번
1.215.xxx.70:5000 -> 192.168.0.8:5000 으로 포트포워딩 하였습니다.
이렇게 설정하고 나면 1.215.xxx.70에 5000번 포트로 들어오는 데이터는 내부 아이피 192.168.0.8번의 5000번 포트로 전송되게 됩니다.
위와 같은 설정은 일반적으로 카페24나 AWS에서 서버를 운영할 경우 필요없는 설정입니다. 왜냐하면 각 서버에 바로 공인 아이피가 할당되기 때문입니다.
자, 그럼 위에서 아웃고잉 웹훅을 설정할때 URL(s) 기억나시나요?
해당 칸에 공인아이피 + 웹서버 포트번호(http://1.215.xxx.70:5000)를 적어주도록 합시다.
이제 슬랙으로부터 내가 지정한 채널에서 메시지가 발생 되었을 경우, 해당 메시지를 받을 준비가 완료되었습니다.
슬랙은 채널에서 메시지가 발생하면 해당 이벤트를 나의 웹서버에 POST 메소드로 전송 해줍니다. 따라서 우리의 웹서버도 POST 메소드를 수신할 수 있도록 변경해줘야 합니다.
아래와 같이 slack_server.py 코드를 수정합니다.
from flask import Flask, request
app = Flask(__name__)
@app.route("/", methods=['GET', 'POST'])
def hello():
print(request.form['text'])
return "Hello World!"
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000)
코드를 보시면 @app.route("/", methods=[‘GET’, ‘POST’])가 추가되었습니다.
GET 그리고 POST메소드를 http://서버주소:5000/ 경로에 허용하겠다는 뜻입니다.
그리고 request.form[‘text’]라는 녀석이 등장했는데요. 슬랙에서는 데이터를 다음과 같은 형태로 넘겨줍니다.
token=Eqn4cHo1NM44rAvMQxK26pgH&team_id=T0433FX78&team_domain=slowalk&
service_id=165336103011&channel_id=C3FJCN6CS&channel_name=test&
timestamp=1491540739.372491&user_id=U1D5UGLEB&user_name=hakjin&text=hello
이중 우리가 필요한 데이터는 text 값(사용자가 입력한 채팅 메시지)이고, 이를 flask의 request.form을 이용해서 추출하고 화면에 출력해 본 것입니다.
이제 고지가 눈앞에 보입니다. 이제 text값을 복사해서 두번 반복되게 만들고 이를 슬랙으로 보내면 앵무새봇이 완성되겠습니다.
그럼, 슬랙으로 데이터는 어떻게 보낼까요?
제가 선택한 채널에서 메시지가 발생하면 슬랙은 저희 서버로 해당 이벤트를 POST 메소드를 사용해 요청합니다. 그리고 모든 HTTP 요청에는 적당한 응답을 주어야 합니다. 이 응답값을 특정한 포맷으로 맞춰서 주면 선택한 채널로 메시지가 표시되게 됩니다. (이것은 아웃고잉 웹훅을 사용했을 경우 입니다.)
여기서 말한 특정한 포맷은 아웃고잉 웹훅 설정화면에 잘 나타나 있는데요. 아래와 같은 JSON 형태의 값 입니다.
{
"text" : "안녕하세요?"
}
위와 같은 포맷으로 응답까지 수행하는 slack_server.py 서버 코드는 다음과 같습니다.
from flask import Flask, request, Response
app = Flask(__name__)
@app.route("/", methods=['GET', 'POST'])
def hello():
if request.form['user_id'] != 'USLACKBOT':
text = '{{"text":"{} {}"}}'.format(request.form['text'], request.form['text'])
resp = Response(response=text, status=200, mimetype="application/json")
return resp
else:
return "ok"
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000)
일단 코드에 if 문이 추가되었는데요. user_id가 USLACKBOT이 아닐때만 응답하도록 코드를 수정했습니다. 이유가 궁금하신 분은 if문을 제거하고 돌려보세요. 그리고 Flask의 Response를 사용해서 JSON 포맷으로 응답하도록 수정되었습니다.
마치며
여기까지 앵무새봇을 아주 간단하게 만들어 보았습니다. 앵무새봇은 슬랙의 아웃고잉 웹훅으로만 구현되었습니다. 따라서 다른 여러 채널에 적용하기에는 범용성이 떨어지는 점과 사람이 먼저 말을 해야 반응을 보이는 단점이 있습니다. 여러분은 이러한 단점을 보완하기 위해 슬랙에서 제공하는 다양한 API를 활용해서 봇을 생성해 보시기 바랍니다.
더 읽기
'Technology' 카테고리의 다른 글
‘서울정책아카이브’를 통해 알아보는 아카이브 개발 사례 (0) | 2017.10.31 |
---|---|
독점 콘텐츠로 살아있는 뉴스레터 보내기 (2) | 2017.10.24 |
오늘 배워 바로 쓰는 CSS 애니메이션 프로토타이핑 (0) | 2017.09.08 |
성장하는 서비스의 DB 성능 개선, 어떻게 할까? (1) | 2017.07.26 |
헷갈리는 UI, 스티비는 이렇게 씁니다 (0) | 2017.04.07 |
레드오션 O2O시장에서 살아남는 스타트업의 전략 (0) | 2017.03.31 |
새로운 개발 언어, 어떤 걸 배울까? (0) | 2017.03.27 |
슬로워크 웹기획자의 GAIQ 정복기 (1) | 2017.03.23 |