블로그 이미지
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.30 15:53

[ Perl ] 경량프레임워크로 달리는 Perl 웹개발 #2 - MENTA 를 더 만져보기...


  회사업무중에서 MENTA Lib 를 직접 고친 부분와 이유에 대해서 간단하게 읊어보도록 하겠습니다.

   lib/MENTA/Dispatch.pm - Line 16 - 35
  1. -        my $controller = "${cdir}/${path}.pl";
  2. -        my $controller_mt = "${cdir}/${path}.mt";
  3. -        if (-f $controller) {    
  4. -    ~~~ // 중략 //~~~
  5. -            MENTA::finalize($out);
  6. -        } else {
  7. -            die "어쩌구 저쩌구 @{[ MENTA::base_dir() ]} 어쩌구 저쩌구;";
  8. -        }
  대략 컨트롤러와 템플릿 파일이 있었을 경우의 구현 부분을 따로 서브루틴으로 빼내고(run_controller, run_controller_mt) 해당 부분을 지워버렸습니다.
  1. +   my $orig_path = $path;
  2. +
  3. +   while(1) {
  4. +       $path = 'index' unless $path;
  5. +       my $controller = "${cdir}/${path}.pl";
  6. +       my $controller_mt = "${cdir}/${path}.mt";
  7. +       if (-f $controller) {
  8. +              MENTA->context->prepare_path($path, $orig_path);
  9. +       return run_controller($controller, $path, $orig_path);
  10. +       } elsif (-f $controller_mt) {
  11. +       return run_controller_mt($controller_mt, $path, $orig_path);
  12. +       } else {
  13. +       my @tmp_ = split "/", $path;
  14. +       pop @tmp_;
  15. +       $path = join "/", @tmp_;
  16. +       }
  17. +   }

  대충 이와 같습니다. 저렴하게 적어놔서 별거 없습니다만...
  MENTA 의 경우는 /blah/blah/blah 로 접속했을 때.. /app/controller/blah/blah/blah.pl 이나 .mt 파일이 항상 존재해야합니다. 그렇지 않으면 에러페이지가 나오죠. 위의 부가된 처리는 /blah/blah/blah에서 파일이 없다면 /blah/blah 의 파일을 읽어오게 하고... 그게 아니면 계속 상위 페이지의 파일유무를 체크하고 그 파일이 있다면 그것을 읽어오게 합니다.
  그리고 컨트롤러가 존재한다면 prepare_path로 그 경로 정보를 설정하게 합니다. /blah.pl 이 있고, /blah/blah/blah 로 접속했을 때, blah/blah 는 HTTP 쿼리 파라메터가 아닌 별도의 파라메터로 읽어들여집니다. 그 내용은 아래와 같습니다.

  1. diff --git a/lib/MENTA/Context.pm b/lib/MENTA/Context.pm
  2. index e70e729..1122a8a 100644
  3. --- a/lib/MENTA/Context.pm
  4. +++ b/lib/MENTA/Context.pm
  5. @@ -1,7 +1,7 @@
  6.  package MENTA::Context;
  7.  use strict;
  8.  use warnings;
  9. Class::Accessor::Lite->mk_accessors(qw/config plugin_stash request/);
  10. Class::Accessor::Lite->mk_accessors(qw/config plugin_stash request path_args/);
  11.  
  12.  sub new {
  13.      my ($pkg, %args) = @_;
  14. @@ -19,4 +19,13 @@ sub mobile_agent {
  15.      };
  16.  }
  17.  
  18. +sub prepare_path {
  19. +    my ($self, $controller, $path) = @_;
  20. +    
  21. +    return $self->path_args([]) unless $path;
  22. +
  23. +    $path =~ s/^$controller\///g;
  24. +    my @args = split /\//, $path;
  25. +    $self->path_args([ @args ]);
  26. +}
  27.  1;

 뭐없죠? 그리고는 blah.pl에서는 
  1. use MENTA::Controller;
  2.  
  3. sub run {
  4.   my $c = MENTA->context;
  5.  
  6.   warn $c->path_args->[0]; # blah
  7.   warn $c->path_args->[1]; # blah
  8.  
  9.   # blahblah code
  10. }
  이런식으로 그 경로 인수들을 뽑아냅니다.  
  그리고 다른 수정개소는 아래와 같습니다.
  1. diff --git a/lib/MENTA/Controller.pm b/lib/MENTA/Controller.pm
  2. index 6aee162..d9e1166 100644
  3. --- a/lib/MENTA/Controller.pm
  4. +++ b/lib/MENTA/Controller.pm
  5. @@ -21,7 +21,7 @@ sub import {
  6.          my $pkg = do {
  7.              local $_ = (caller(0))[1];
  8.              s{^$controller_dir/*|\.pl$}{}g;
  9. -            s{/}{::};
  10. +            s{/}{::}g;
  11.              "MENTA::Controller::$_";
  12.          };
  13.  
  14.  

  사실 이것을 수정하지 않으면 /blah/blah/blah 의 접속시 /app/controller/blah/blah/blah.pl 이 있는 경우에는  항상 아래와 같은 에러로 끝나게 됩니다.
syntax error at /home/blah/blah/app/controller/blah/blah/blah.pl line x, near ";"MENTA::Controller::blah::blah/blah" 
(Might be a runaway multi-line // string starting on line 3
  힌트는 항상 에러메시지에 담겨 있습니다. 
  일반적으로 /blah 로 접속했을 시의 해당 컨트롤러는 MENTA::Controller::blah 라는 namespace 를 가지게 됩니다. 그런데  /blah/blah/blah 로 접속했을 경우의 에러메시지는 마지막의 namespace 구분자가 / 로 되어 있는 것을 볼 수 있습니다. 원인은 이것이었습니다. 그러므로 위의 코드의 10번째 줄과 같이 g modifier 를 추가해주어 문제를 해결할 수 있었습니다.
  
  사실 위의 문제들은 그리 어려운 문제들은 아닙니다. 코드를 읽으면서 어떻게 돌아가는 지만 살펴보면 금방 알 수 있죠(저같은 경우에는 파일마다 디버그 로그 찍어내면서 파악했습니다 - 필요한 부분만...). 뭐 조금씩 조금씩 알아나가다가 결국에는 제대로 된 거(?) 하나 만들지 않을까요?
신고
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 처럼 학습비용이 큰 것이 아닌 이런 경량 프레임웍부터 시작하는 것도 괜찮지 않을까 생각됩니다.

신고
TOTAL 466,823 TODAY 71

티스토리 툴바