Elixir 실험실: 채팅 프로그램

Tags
Published
Author
Elixir 로 할 수 있는 재밌는 것이 뭐가 있을까 하다가 간단한 채팅 프로그램을 구현했다.
Elixir 를 잘 사용하면 Node (erlang VM) 간 통신이 가능하다. 이를 이용한 채팅 프로그램이다.

Server

defmodule Chat.Server do @name :chat_server def start do pid = spawn(__MODULE__, :listen, [[]]) :global.register_name(@name, pid) pid end def join(client_pid) do send(:global.whereis_name(@name), {:join, client_pid}) end def send_message(client_pid, message) do send(:global.whereis_name(@name), {:message, %{pid: client_pid, message: message}}) end def listen(clients) do receive do {:join, pid} -> Enum.each(clients, fn client -> send(client, {:join, pid}) end) listen([pid | clients]) {:message, %{pid: pid, message: message}} -> Enum.each(clients, fn client -> send(client, {:message, %{sender: pid, message: message}}) end) listen(clients) end end end

Client

defmodule Chat.Client do def start() do pid = spawn(__MODULE__, :listen, []) Chat.Server.join(pid) pid end def listen do receive do {:join, pid} -> IO.puts("#{inspect(pid)} has joined the chat.") listen() {:message, %{sender: sender, message: message}} -> IO.puts("[#{inspect(sender)}] #{message}") listen() end end def send_message(message) do Chat.Server.send_message(self(), message) end end
 
코드는 단순하다.
Chat.Server.start 는 채팅 서버 Process 를 생성한다. 생성된 채팅 서버 프로세스는 loop 를 돌면서 :join 혹은 :message 라는 타입의 메세지가 들어올 때 까지 대기한다.
Chat.Client.start 는 채팅 클라이언트 Process 를 생성한다. 생성된 클라이언트 프로세스는 loop 를 돌면서 동일하게 :join, :message 라는 타입의 메세지를 받기위해 대기한다.
 
mix.exs 가 있는 프로젝트에 위 파일을 추가해두면 실행은 아래와 같이 가능하다.
iex --sname one -S mix Chat.Server.start Chat.Client.start
다른 터미널에서 아래와 같이 한다.
iex --sname two -S mix Node.connect :"one@${local-machine-name}" Chat.Client.start
 
두번째 터미널에서 Chat.Client.start 시 첫번째 terminal 에서 join 메세지를 확인할 수 있다.
이후 각 터미널에서 아래와 같이 입력하면 서로 채팅이 가능하다.
Chat.Client.send_message("some message")
 
아래처럼 정상 실행되는 모습을 확인할 수 있다.
notion image
 
엘릭서를 좀 오래 놓고있어서 복습 겸 간단하게 구현했는데, 다른 언어라면 언어만으로 해결하기 어려운 것을 몇줄 안되는 코드로 구현가능해서 좋았다.