@eeyees - 인쇄기기 업계의 기린아, TAFKA_HoliK라는 닉을 사용하기도 한다. 일본에서 일하다가 올해 한국 후지 제록스로 이직하였다.
우리는 지난 기사에서 카탈리스트, 댄서와 같은 웹 프레임워크를 볼 수 있었습니다. 제가 소개시켜 드릴 것은 Mojolicious라는 웹 프레임워크입니다.
Mojolicious는 실시간 웹 프레임워크를 표방하고 있습니다. 그 외에도 멋진 특징들이 많이 있습니다. 공식 사이트에서는 아래와 같이 소개하고 있습니다.
오늘은 가볍게 Mojolicious를 이용해 Websocket으로 비동기 채팅하는 소스 코드를 살펴봅시다.
리눅스라면 다음과 같은 명령으로 간단하게 설치할 수 있습니다.
$ sudo sh -c "curl -L cpanmin.us | perl - Mojolicious"
cpan이 설정되어 있다면 아래와 같이 설치합니다.
$ cpan Mojolicious
Mojolicious가 설치되면 mojo라는 명령행 도구가 생성됩니다. Mojolicious::Lite를 기반으로 한 간단한 웹 어플리케이션 뼈대를 만들기 위해서는 아래와 같이 입력할 것입니다.
$ mojo generate lite_app
오늘은 간소화 버전이 아닌 정식 웹 어플리케이션을 만들어 봅시다.
따라서 lite_app
대신 app
타입으로 지정합니다.
어플리케이션의 이름은 Chat로 지어주었습니다.
$ mojo generate app Chat [mkdir] /home/holik/tmp/chat/script [write] /home/holik/tmp/chat/script/chat [chmod] chat/script/chat 744 [mkdir] /home/holik/tmp/chat/lib [write] /home/holik/tmp/chat/lib/Chat.pm [mkdir] /home/holik/tmp/chat/lib/Chat [write] /home/holik/tmp/chat/lib/Chat/Example.pm [mkdir] /home/holik/tmp/chat/t [write] /home/holik/tmp/chat/t/basic.t [mkdir] /home/holik/tmp/chat/log [mkdir] /home/holik/tmp/chat/public [write] /home/holik/tmp/chat/public/index.html [mkdir] /home/holik/tmp/chat/templates/layouts [write] /home/holik/tmp/chat/templates/layouts/default.html.ep [mkdir] /home/holik/tmp/chat/templates/example [write] /home/holik/tmp/chat/templates/example/welcome.html.ep
생성된 chat 디렉터리에 들어가 내부 구성을 살펴봅시다.
~/tmp$ cd chat ~/tmp/chat$ tree . ├── lib │ ├── Chat │ │ └── Example.pm │ └── Chat.pm ├── log ├── public │ └── index.html ├── script │ └── chat ├── t │ └── basic.t └── templates ├── example │ └── welcome.html.ep └── layouts └── default.html.ep 9 directories, 7 files
lib
아래에 있는 부분이 서버의 컨트롤러 부분이겠군요.
log
디렉터리에는 로그를 남길 것입니다.
public
에는 공통적으로 쓰이는 정적 파일이 올라갈 것입니다. 여기서는 html 페이지를 보관하고 있네요.
script
에는 구동 스크립트가 들어 있습니다.
t
디렉터리에는 테스트 묶음이 들어갈 것입니다.
templates
부분은 서버의 뷰 부분을 담당하고 있는 친구들인가 보군요.
간단하게 웹 서비스를 한번 실행해 봅시다.
아래와 같이 script
디렉터리에 들어있는 chat
스크립트를 morbo
명령을 통해 실행합니다.
~/tmp/chat$ morbo script/chat Server available at http://127.0.0.1:3000.
이제 웹 브라우저에서 http://127.0.0.1:3000/welcome에 접근해 봅시다.
그림 1. 생성된 뼈대를 구동해 열어본 웹 페이지
잘 나오네요. 그럼 이제부터 채팅 프로그램을 만들어 봅시다. :)
lib/Chat.pm
파일에 chat라는 라우트를 추가해 봅시다.
파일을 열면 아까 열어본 /welcome
도 여기에 정의되어 있습니다.
package Chat; use Mojo::Base 'Mojolicious'; # This method will run once at server start sub startup { my $self = shift; # Routes my $r = $self->routes; # Normal route to controller $r->route('/welcome')->to('example#welcome'); } 1;
/welcome
라우트를 등록하는 줄 하단에 /chat
도 같은 형태로 추가합니다.
$r->route('/chat')->to('ChatControl#chatAction');
to
에 전달하는 ChatControl#chatAction
은 "ChatControl
이라는
컨트롤러에 chatAction
이라는 액션을 수행해 주세요."라고 말하는 것과 같습니다.
같은 방식으로 웹소켓을 위한 라우트도 추가합니다.
$r->websocket('/chatWS')->to('ChatControl#wsAction');
Chat.pm
에 등록해 준 컨트롤러 부분을 구현해봅시다.
lib/Chat/ChatControl.pm
파일을 만들고 chatAction 함수와 wsAction 함수를 만듭니다.
package Chat::ChatControl; use Mojo::Base 'Mojolicious::Controller'; our $clients = {}; sub chatAction { my $self = shift; $self->render( message => 'Chatting Example' ); } sub wsAction { my $self = shift; my $clntID = sprintf "%s" , $self->tx; $clients->{$clntID} = $self->tx; for my $id (keys %$clients) { $clients->{$id}->send_message("Client Connected!"); } say "Client Connected!"; $self->on( finish => sub { my $self = shift; my $id = sprintf "%s" , $self->tx; delete $clients->{$id}; say "Client is Disconnected!"; } ); $self->on( message => sub { my ($self, $message) = @_; for my $id (keys %$clients) { $clients->{$id}->send_message($message); } } ); } 1;
chatAction
은 채팅 웹페이지 위에 표기할 메시지를 전달해
단순히 템플렛을 랜더링합니다.
wsAction
은 웹 소켓으로 통신하는 로직을 작성했습니다.
먼저, $self->tx
를 통해 현재 요청에 대한 트랙잭션 객체(Mojo::Transaction)를 얻습니다.
이 경우 웹 소켓 트랙잭션 객체(Mojo::Transaction::WebSocket)가 될 것입니다.
요청받은 모든 트랜잭션은 단순히 패키지 해시에 보관합니다.
$self->on
을 통해 현재 요청에 대한 트랜잭션에 이벤트 콜백을 등록합니다.
특히 웹 소켓을 통해 메시지가 도착하면 message
이벤트가 수행됩니다.
그러면 보관했던 모든 트랜잭션, 즉 요청했던 모든 클라이언트에게 메시지를 전달합니다.
wsAction
의 행동을 위의 두 줄로 요약하면 아래와 같습니다.
이제 뷰 부분을 만들어 보겠습니다.
templeates
디렉터리로 이동한 후 ChatControl
디렉터리를
만들고 그 안에 chatAction.html.ep
파일을 만듭니다.
$ mkdir ChatControl $ cd ChatControl $ vim chatAction.html.ep
그리고 다음과 같이 작성해 봅시다.
%layout 'chatLayout'; %title 'Chatting'; <h1> <%= $message %> </h1> <div id="chatWindow"> </div> <form> <input type="text" id="sendMes"> <input type="submit" id="sendBtn" value="Send"> </form>
채팅을 보일 창 한 개와 채팅을 입력할 부분과 보낼 버튼을 추가 했습니다.
이제 레이아웃을 작성해 볼까요? 이번에는 templates/layouts
디렉터리에
chatAction.html.ep
에서 사용한 레이아웃 파일을 만듭니다.
$ cd .. $ cd .. $ cd templates/layouts $ vim chatLayout.html.ep
이번에는 아래와 같이 작성합니다.
<!DOCTYPE html> <html> <head> <title><%= title %></title> <style type"text/css"> #chatWindow { width : 500px; height : 400px; overFlow : auto; border : 1px solid #000; } </style> <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.min.js"> </script> <script type="text/javascript"> var ws; $(document).ready(function() { $('#sendBtn').click(sendMessage); $('#sendBtn').keyup(function(ev) { if( ev.keycode == 13) { sendMessage(); } }); $('#disconnBtn').click(disconn); $('form').submit(function(ev) { ev.preventDefault(); }); if (!("WebSocket" in window)) { alert("do not Supprot WebSocket!!"); } else { ws = new WebSocket('ws://localhost:3000/chatWS'); ws.onopen = function() { } ws.onmessage = function(ev) { appendChat(ev.data); } ws.onclose = function() { appendChat("Connection Closed!"); } } function sendMessage() { ws.send($('#sendMes').val()); $('#sendMes').val(""); } function appendChat(mes) { $('#chatWindow').append(mes+"<br>"); } function disconn() { ws.close(); } }); </script> </head> <body> <%= content %> </body> </html>
간단한 자바스크립트 코드를 이용해 웹 소켓의 메시지를 송수신합니다.
브라우저가 웹 소켓을 지원하지 않는지 검사한 뒤, 서버와 접속을 수행합니다.
웹 소켓을 통해 메시지를 받으면 onmessage
에 등록한 함수가 호출되어 메시지를 출력합니다.
메시지를 보낼 때에는 ws.send(...)
와 같이 웹 소켓을 통해 전달하고 있습니다.
클라이언트에서 메시지를 보낸 이후 페이지를 다시 불러들이는 것을 막기 위해
preventDefault()
를 걸었습니다.
그럼 작성한 소스 코드를 실행해봅시다.
$ morbo script/chat
그림 2. 완성된 서비스
잘 되네요 :)
간단하게 Mojolicious를 웹 프레임워크를 사용해서 HTML5에 포함되는 WebSocket을 이용한 비동기 채팅 웹 서비스를 만들어 보았습니다. 한국에는 아직도 펄하면 단순히 문자열 처리만을 위한 언어라거나 시스템 엔지니어만 다루는 언어로만 알려져 있는 것 같습니다. 이번 펄 크리스마스 달력을 통해 펄의 다양한 활용에 대해서 조금이나마 공유할 수 있는 시간이 되어 다행인 것 같습니다.
2011년 마무리 잘 하시고, 새해 복 많이 받으세요!
Articles by Seoul Perl Mongers
Illustrated by Hyunsu Park, Designed by Hojung Youn, Edited by Hojung Youn & Keedi Kim