블로그 이미지
JEEN

서울에 사는 꽃청년의 IT찌질모험기

Rss feed Tistory
IT/Perl 2009.02.10 00:31

[ Perl ] CPAN 모듈에 의존한 프로젝트에서의 주의점



 누군가에게 있어 Perl 은 CPAN 을 사용하는 툴이라고 불릴 정도로 Perl 에서의 CPAN 의존은 빼놓을 수 없습니다. 하지만 어떤 프로젝트라도 그냥 대놓고 superuser 로 CPAN 모듈 깔고 그대로 사용하는 경우는 위험합니다. 어떤 하나의 CPAN 모듈이라도 다른 CPAN 모듈에 의존하고 있기 때문에, 의존성 있는 모듈이 해당 메소드 이름을 바꿔버렸거나 하는 경우가 발생하곤 합니다.

  저 같은 경우에는 예전에 CPAN 모듈을 업그레이드 하고, 오늘 FastCGI 를 재기동했을 때, 기존에 잘 돌아가던 웹사이트가 갑자기 500 Internal Error 를 뱉어내기 시작하거나 하는 일이 있었습니다. JSON::Converter 모듈이 JSON 모듈의 업데이트에 따라가지 못하고 관련 메소드가 없다고 에러가 난 것이었죠. 결국은 라이브러리 폴더에서 직접 JSON::Converter 모듈을 수정하는 방법 밖에는 없었습니다. --  뭐 두 모듈 다 CPAN 에서 이전 버젼의 모듈을 받으면 된다는 것도 있겠지만...

  사실은 회사의 중규모이상의 프로젝트에서는 프로젝트에서 사용되는 CPAN 모듈은 별도의 library 폴더로 지정해줍니다. CPAN 의 설정을 바꿔서 별도의 라이브러리 폴더로 바꿔주는 것이죠. 거기다가 버젼관리도 해줍니다.
기존에 잘 움직이고 있는 라이브러리는 특별한 버그나 큰 퍼포먼스 향상이 기대되지 않는다면 업데이트도 잘 하지 않습니다. 최신경향에 맞춰서 바꿔나갈 경우도 있겠지만, 그렇게 우선도는 높지 않습니다.
  물론 Perl 의 대표적인 Product 인 MovableType 같은 경우에는 CPAN 모듈을 그대로 사용하지 않고 전부 MovableType 용으로 따로 최적화시켜두기도 합니다. 딱 필요한 기능만을 빼낸 것이죠.

  이전에 소개한 경량웹프레임워크인 MENTA 에서는 extlib 디렉토리 아래에 필요하고, 저자 나름대로 추천하고 자주쓰이는 모듈들을 모아놓기도 했죠. 거기에 MENTA 에는 MENTA 로 만드는 프로젝트에 새로 추가되는 CPAN 모듈을 간단하게 extlib 에 추가할 수 있는 스크립트도 제공하고 있습니다.

더보기



  위에서 밝힌 그런 버젼차이에 따른 문제뿐만 아니라 MENTA 같은 경량 웹프레임워크가 지향하는 배포의 용이성을 위해서도 중요한 팁이기도 합니다. 사실 php 같은 경우도 PEAR 모듈같은 것들도 프로젝트 디렉토리에 따로 담아두기도 하니... 굳이 언어와 상관없이 중요하다고 말할 수 있겠네요.

신고
IT/Perl 2009.01.27 17:38

[ Perl ] 경량프레임워크로 시작하는 웹개발


  일본의 유명 Perl 해커 tokuhirom 씨에 의해 만들어진 MENTA 는 한때 Mojo 가 불러일으킨 경량프레임워크 붐을 타고 만들어진 프레임워크입니다. 지금 소개하는 것도 상당히 늦은 감이 없지 않아 있지만... (사실은 실제로 써볼 엄두가 안나봐서 안쓰고 있다가, 업무상으로 쓰게 될 일이 생겨서 이렇게 건드리게 되었습니다.)

 일단은 가볍게 설치부터...

svn export http://svn.coderepos.org/share/lang/perl/MENTA/trunk ~/menta

 로 export 하면 대략 다음과 같은 디렉토리 구성이 나옵니다.
app 
 - app/controller : 어플리케이션을 정의
 - app/data  : 어플리케이션에서 사용할 데이터 (SQLite DB file 따위)
 - app/static : 그림파일, CSS, Java Script
extlib - 저자에게 엄선된 CPAN 모듈
lib - MENTA 가 정의된 라이브러리 디렉토리
plugins - MENTA 에서 사용할 플러그인
t - MENTA 자체의 테스트코드

 튜토리얼등은 MENTA 의 STANDALONE 서버를 돌리면 자세하게 소개되어 있고(app/controller/*), 아래의 MENTA 홈페이지에서도 소개되어 있습니다.
 PHP 스러운 템플릿 파일(.mt)을 준비해서 HTML과 Perl 코드를 혼용해서 쓸 수 있죠. 
 CGI 서버 뿐 아니라, Mod_Perl 로도 돌릴 수 있기 때문에 어느 정도 규모에서도 써볼만 하지 않을까 싶습니다.

  * STANDALONE 서버 가동 (기본 포트는 5555)
./bin/cgi-server 

  * Mod_Perl 사용예제는 매뉴얼 페이지를 참고하세요. (http://gp.ath.cx/menta//manual/mod_perl)

 컨트롤러는 .pl 파일이나 .mt 파일로 지정합니다. 그리고 .pl 은 반드시 최소한 아래와 같은 구조로 되어 있어야 합니다.
use MENTA::Controller;

sub run {
  # blahblah...
}

 MENTA::Controller 를 use 했을 때, 기본적으로...
use strict;
use warnings;
use utf8;
 을 깔고 들어가기 때문에 추가로 지정해줄 필요는 없습니다.
 그리고 .mt 의 경우는 자동으로 렌더링되지만, .pl 의 경우는 템플릿을 지정해서 렌더링해주거나, 다른 HTTP Response 를 지정해줘야 합니다.
  OOP 에 목메지 않고도 간단하게 쓸 수 있는 여러 튜토리얼들이 준비되어 있기 때문에 별다른 설명은 필요 없을 것 같네요.
  개인적으로 필요한 기능이 있다면 MENTA lib 를 직접 건드리는 것도 좋겠지만, 대개의 간단한 공용기능을 정의하려면 plugins/* 에서 정의할 수 있습니다. 저같은 경우에는 MENTA 코어를 건드리지 않으면 좀 번거로워지기때문에 MENTA, MENTA::Dispatch, MENTA::Context 를 만지기도 했습니다.
  Perl 에 대해서 별로 모르거나, 혹은 Perl 로 하는 웹개발에 관심이 있으시다면 Catalyst 처럼 학습비용이 큰 것이 아닌 이런 경량 프레임웍부터 시작하는 것도 괜찮지 않을까 생각됩니다.

신고
IT/Perl 2008.12.04 17:05

[ Perl, PHP ] Job Queue 를 통해 친해지길 바래?


  현재 진행중인 프로젝트의 구성에서... Web 은 PHP 로 다른 사람에 의해 만들어 지고 있고, 백그라운드에서 작동하는 녀석은 제가 Perl 로 쓰고 있습니다.

2008/11/18 - [IT] - [ Selenium ] 웹서비스 테스트 자동화와는 별 상관없는 작업을 위해...
2008/11/18 - [IT] - [ Selenium ] Selenium RC 를 사용해보자. I
2008/11/19 - [IT] - [ Selenium ] Selenium RC 를 사용해보자. II

  이전 Selenium 을 소개했을 때, Test용이 아닌 용도로 사용한다고 했던 게 이것을 위해서 인데요. 웹에서 어떤 파라메터를 날리면 Selenium 쪽에서 그 파라메터를 받아서 백그라운드에서 열심히 달리는 구조입니다.
  그럼 웹에서 어떻게 Selenium 쪽으로 파라메터를 넘겨줄까요?
  제일 간단하게 생각할 수 있는 것이...
  Web 에서 직접 Selenium 을 기동하는 것, 하지만 한번 움직이면 Selenium 으로 5초 이상의 딜레이가 생기는 것은 어쩔 수 없겠죠. Web 에서 이 5초이상 이란 시간은 참 기다려주기 애매할 수 있습니다. 심하면 30초까지 생각할 수 있으니까요.
  다른 방법이 있습니다. 좀 하드코어한 방식으로는 PHP에서 system 으로 ...

  system('perl selenium-work-1.pl doSomething saillinux see fate_stay_night &');

  이렇게 날리는 방법...

  하지만 이런 식이라면 제대로된 파라메터를 날리기 힘듭니다. 예를들어, 다단계 배열이나 해쉬(연상배열) 같은 것을 어떻게 넘기느냐 하면 좀 애매하죠. 뭐 더 하드코어하게 간다면... 매번 파라메터를 JSON 으로 변환해서 이걸 파일로 덤프합니다. 그리고 파일이름을 지정해줄 수도 있겠죠?
 ...
 ...
 설마 이렇게 할 것이라고 생각하는 것은 아니시겠죠?

 제 해법은 Job Queue 입니다. memcached와 Live Journal 의 개발자로 유명하며, 현재 Perl 용 Google App Engine 을 만들고 있는 Brad Fitzpatrick의 Gearman 이 제 눈에 끌렸습니다. TheSchwartz 같은 경우도 생각해 볼 만하지만, TheSchwartz 의 경우라면 전용 DB 를 필요로합니다. 거기에 3-5초 정도의 작업 딜레이도 발생하게 됩니다(3-5초 정도에 한번씩 매번 DB 에 Job 이 등록되었는 지를 확인하기 때문이죠).
  Gearman 은 Client 에서 Job 을 날림과 동시에 Worker 가 움직이게 됩니다.

  Gearman 은 어떻게 입수하느냐. 당연히 CPAN 입니다.
  sudo cpan -i Gearman::Server
  sudo cpan -i Gearman::Client
  sudo cpan -i JSON

  이렇게 cpan 모듈을 인스톨합니다. 중간 중간에 나오는 의존모듈도 같이 인스톨해주시면 됩니다.  Gearman::Server 를 설치하면 gearmand 라는 gearman 데몬용 파일을 실행할 수 있습니다.

  sudo gearmand --daemon --pidfile=/tmp/gearmand.pid --debug=1

  프로세스 리스트를 확인하시면 gearmand 는 데몬으로 작동하는 것을 확인할 수 있습니다.
  그리고 Job 을 날릴 PHP 쪽도 Gearman 라이브러리를 설치해야 합니다. PHP 의 pear 로 간단하게 인스톨 할 수 있습니다.
 
   sudo pear upgrade http://bugs.joestump.net/code/Net_Gearman/Net_Gearman-0.0.4.tgz

  Net_Gearman 의 설치가 끝났다면 php 쪽의 소스는 이와 같습니다.
  client.php
  1. <?php
  2.  require_once 'Net/Gearman/Client.php';
  3.  $data = array( 'who' => 'saillinux', 'what' => 'fate_stay_night', how => 'haak' );
  4.  $pid = getmypid();
  5.  $set = new Net_Gearman_Set();
  6.  $task = new Net_Gearman_Task( 'job', $data, $pid, Net_Gearman_Task::JOB_BACKGROUND);
  7.  $client = new Net_Gearman_Client(array('localhost'));
  8.  $client->runSet($set);
  9. ?>

  짧게 코드를 설명하자면... $data 에 위와 같은 연상배열을 넣고, 6번째에 Task 를 추가합니다.   
  Net_Gearman_Task 에서 첫번째 인수는 function 이름입니다. 어떤 놈에게 일을 시킬까 하는 것인데, 물론 이 function 은 Worker 쪽에 정의되어 있어야 합니다.
  두번째 인수는 Worker 에 넘길 인수입니다. 이 인수는 JSON 으로 파싱해서 넘어가게 됩니다.
  7번째 줄에서 Net_Gearman_Client에서 배열에 localhost 를 넣었습니다. Worker 는 복수의 서버를 지정할 수 있습니다.
  그외에 대해선 문서를 참고하세요.

  위와 같은 Job 이 client 쪽에서 날아온다면, 이것을 받을 Worker 가 기동중이어야 합니다. 그리고 Worker는 아래와 같은 코드로 이루어져 있습니다.
  worker.pl
  1. use strict;
  2. use warnings;
  3. use Gearman::Worker;
  4. use JSON;
  5.  
  6. my $worker = Gearman::Worker->new;
  7. $worker->job_servers(qw/localhost/);
  8. $worker->register_function(
  9.   job => sub {
  10.     my $job = shift;
  11.     my $args = from_json( $job->arg );
  12.     print $args->{who}." ".$args->{how}." ".$args->{what}."¥n";
  13.   });
  14. $worker->work while 1;

  위의 client 에서 job 이라는 function 으로 job 을 날린 것을 $worker->register_function 으로 등록된 job 이라는 function 에서 처리합니다. JSON 으로 넘어온다고 했으니 넘어온 JSON($job->arg)을 해석합니다. 그리고 받은 인수를 찍어냅니다.

  일단 하나의 터미널에서 worker.pl 을 실행시키고, 다른 터미널에서 client 를 실행시킵니다. 그러면 client 에서 job 이 worker 로 넘어가서, worker 는 그 job 에 맞게 정의된 행동을 수행하겠죠.

  그럼 예외의 경우를 살펴보도록 하자면...
  client 에서 job 은 계속 날리는 데, worker 는 죽어있는 상태입니다(이런 상황이 걱정된다면 worker 를 여러개 띄워놓는 것도 한 방법이 될 수도 있습니다). 이렇게 되면 일하는 놈이 없으니까 당연히 일은 못하게 됩니다. job 은 계속 queue 에 쌓여 있겠죠. 그리고 worker 가 살아난다면, 쌓여있는 job 을 하나씩 처리해나가게 됩니다. gearmand 가 어느 정도 큐에 담아둘 수 있는 지는 잘 모르겠습니다. 메모리 여유분 만큼이려나요?
  그럼 gearmand 데몬 자체가 job 을 잔뜩 쌓아놓고 있는데 죽어버렸다면 어떻게 될까요? 이경우는 queue 에 쌓인 job 은 소실됩니다. 그래서 불안하시다면, TheSchwartz 나 Q4M 을 써서, DB 에 job 을 넣는 형식을 쓰는 것도 선택중의 하나가 되겠죠.
  (피드백 주신 a3r0/Luz_Luna님++)

  뭐, 제가 하려는 건 Selenium Agent 를 가동하기 위해 적당한 인수를 받아서 넘겨주는 것 밖에 없으니까요.
  아무튼 이런 식으로 Perl 과 PHP 간의 유대관계를... 쿨럭.. 아니, 그것보다 이런 식으로 Web 상에서 처리하기에는 좀 지지부진한 처리를 Job Queue 를 통해서 해결해보시는 것은 어떠실런지요?
  뭐 관리의 문제를 제외한다면(제외하기 힘들겠지만)... 여러명이 각자의 특색에 맞는 언어를 선택하는 것은 나쁘지 않다고 생각합니다. 저마다의 개성이겠죠. (물론 사람에 따라서 나쁘다고 생각하실 분도 있으시겠죠...;;)

  http://ido.nu/kuma/2008/01/20/implemented-reblogging-server-with-gearman/
 
  위의 링크를 참고로 했습니다.
신고
TOTAL 466,844 TODAY 18

티스토리 툴바