#elixirlang 언어로 만든 #slack 봇을 #heroku 서비스에 배포하기
다음 사이드 프로젝트는 slack 봇(bot)이다. 관리 시간을 줄일 아이디어가 떠올랐다. 언어는 요즘 쓰고 있는 elixir 언어로 결정했다. 처음부터 만들어야 하는 거 아니야? 노노. 이쪽 생태계를 무시하면 안 된다. 1986년에 발표된 32살 erlang 언어가 뒤를 든든하게 받쳐주고 있다. 엔간한 건 다 있다. elixir에 없으면 erlang 라이브러리를 찾으면 된다.
ping 슬랙 봇
elixir 설치부터 한다.
$ mix new ping --sup
프로젝트 생성
# mix.exs
defp deps do
[
{:slack, "~> 0.13.0"}
]
end
elixir로 만든 slack RTM(Real Time Messaging) API 클라이언트 라이브러리가 있다. 디펜던시(dependency)에 slack 라이브러리를 추가한다.
defmodule Ping.Slack do
use Slack
def start_link(args) do
Slack.Bot.start_link(Ping.Slack, args, Application.get_env(:ping, :slack_token))
end
def child_spec(opts) do
%{
id: __MODULE__,
start: {__MODULE__, :start_link, [opts]},
type: :worker,
restart: :permanent,
shutdown: 500
}
end
def handle_event(message = %{type: "message"}, slack, state) do
if message.text == "ping" do
send_message("pong", message.channel, slack)
end
{:ok, state}
end
def handle_event(_, _, state), do: {:ok, state}
end
lib/ping/slack.ex
파일을 생성한다. handle_event
콜백 함수를 구현하면 된다. 봇이 있는 채널 메시지나 DM(direct message)을 어떻게 처리할지 결정한다. 여기선 ping 메시지를 검사해 pong 메시지를 채널에 쓰게 했다. 크래시가 나면 종료 조건 없이 재시작하게 child_spec 함수를 구현했다. 구현 위치는 supervisor tree를 어떻게 구성하느냐에 따라 다르다. 여기선 별 생각 없이 구성했다.
defmodule Ping.Application do
@moduledoc false
use Application
def start(_type, _args) do
children = [{Ping.Slack, []}]
opts = [strategy: :one_for_one, name: Ping.Supervisor]
Supervisor.start_link(children, opts)
end
end
lib/ping/application.ex
파일을 수정한다. 위에서 만든 Ping.Slack
모듈을 자식으로 가진 supervisor를 시작한다. supervisor는 재시작을 담당한다.
use Mix.Config
config :ping,
slack_token: ""
config/config.exs 파일에 추가한다. 이제 slack_token 발급받아야 한다.
slack apps 페이지에서 앱을 만든 후 OAuth & Permissions > Bot User OAuth Access Token 문자열을 복사한다. 다시 config.exs 파일로 돌아와 slack_token에 붙여넣는다.
slack app 허가 권한은 workspace owner에게 있다. 적용하고 싶은 workspace의 owner가 아니라면 테스트용 workspace를 만드는 걸 추천.
$ mix run --no-halt
mix.exs 파일이 있는 ping 프로젝트 루트 디렉터리에서 실행하면 ping 봇이 짠하고 나타난다.
heroku로 배포
다음 사이드 프로젝트는 slack 봇이다. 사용 언어는 elixir. heroku는 정식 지원이 아니라 custom buildpack을 써야해서 망설여짐. 뭔가 다른 귀찮은 게 기다리고 있을까봐. Gigalixir는 #elixir 전용 호스팅이라니 한번 써보려. https://t.co/favMox04G3
— 오종빈(Jongbin Oh) (@ohyecloudy) May 28, 2018
gigalixir는 elixir 언어 웹프레임워크인 phoenix만 지원한다. 그래서 heroku로 왔다. @book_quote_bot, @bquote_bot 트위터봇 세팅하고 처내버려 두다가 정말 오랜만에 들어왔다.
heroku에서 앱을 만들고 안내대로 쭉쭉 따라가면 된다.
$ heroku buildpacks:add "https://github.com/HashNuke/heroku-buildpack-elixir.git"
Buildpack added. Next release on ping-slack-bot will use https://github.com/HashNuke/heroku-buildpack-elixir.git.
Run git push heroku master to create a new release using this buildpack.
공식 지원 언어가 아니라 빌드팩(buildpack)을 설정해줘야 한다. 다행히 elixir 빌드팩이 있다.
$ git push heroku master
...
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Elixir app detected
remote: -----> Checking Erlang and Elixir versions
remote: WARNING: elixir_buildpack.config wasn't found in the app
remote: Using default config from Elixir buildpack
remote: Will use the following versions:
remote: * Stack heroku-16
remote: * Erlang 20.1
remote: * Elixir 1.5.0
remote: -----> Will export the following config vars:
remote: * MIX_ENV=prod
remote: -----> Using cached Erlang 20.1
remote: -----> Installing Erlang 20.1
remote:
remote: -----> Using cached Elixir v1.5.0
remote: -----> Installing Elixir v1.5.0
...
remote: -----> Compiling
remote: Compiling 3 files (.ex)
remote: Generated pong app
remote: -----> Creating .profile.d with env vars
remote: -----> Writing export for multi-buildpack support
remote: -----> Discovering process types
remote: Procfile declares types -> (none)
remote: Default types for buildpack -> web
remote:
remote: -----> Compressing...
remote: Done: 61.9M
remote: -----> Launching...
remote: Released v5
remote: https://pong-slack-bot.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/pong-slack-bot.git
6bce8f3..b0f3b69 master -> master
push만 하면 컴파일부터 배포까지 알아서 싹 해준다. 이 맛에 PaaS(Platform as a Service) 쓰는 거제~
참고
- Erlang (programming language) - en.wikipedia.org(archive)
- The Elixir programming language - elixir-lang.org(archive)
- Tags - ohyecloudy.com(archive)
- Getting started writing a Slack bot with Elixir - by Mike Wagg - Carwow Produ…(archive)
- Phoenix Framework - phoenixframework.org(archive)
- Deploying Elixir with Heroku - ElixirCasts - elixircasts.io(archive)
- Slack API: Applications - Slack - api.slack.com(archive)
- Cloud Application Platform - Heroku - heroku.com(archive)
- Slack is your productivity platform - Slack - slack.com(archive)
- Platform as a service - en.wikipedia.org(archive)
- BlakeWilliams/Elixir-Slack - github.com(archive)
- Elixir’s Platform as a Service - Gigalixir - gigalixir.com(archive)