스물한번째 날: Plack on SL4A
저자
@aanoaa - Perl, 야구, 자전거, 낙타, 돌고래, 포청천 마니아. 최신 휴대폰에 관심은 없지만 요일별로 스마트 폰을 바꿔가며 들고다닌다. YAPC::Asia를 다녀온 후 현재 넥서스 원과 갤럭시 탭, 노트북의 바탕화면은 Larry Wall. 현재 안드로이드 앱 개발에 매진 중이다.
시작하며
Perl은 대부분의 운영체제에 이식되어 기본으로 내장되어 있는 범용적인 언어입니다. 비록 기본 내장은 아니지만 안드로이드 플랫폼에도 이식되었습니다. 바로 SL4A가 그 주인공인데요. 자세한 내용은 SL4A 공식 홈페이지를 확인하세요. 아! 물론 이번 크리스마스 달력 16일자 기사도 놓치지마세요! ;-) SL4A가 설치되었다면 여러분의 안드로이드 기기는 웹서비스 머신으로 탈바꿈할 모든 준비가 된 것입니다.
초간단 웹서비스
우선 아직은 안드로이드 기기에서 바로 cpan
명령을 이용하거나
바로 XS 모듈을 설치할 수 있는 간단한 방법이 없다는 것에 유의하세요.
이 두 가지 제약 사항은 꽤나 아쉬운 부분이긴 하지만
순수 펄 모듈로만 구성된 CPAN 모듈이라면 약간의 기교를 부려
어렵지 않게 안드로이드 기기에서 사용할 수 있습니다.
그럼 안드로이드폰에서 보다 편리하게 CPAN을 활용하는 방법을 알아보죠. :-)
다음은 웹서버를 이용해서 파일 디렉토리 나열 옵션을 켜고 브라우저로 접속한 화면입니다.
화면에서 볼 수 있는 웹 서비스를 일반 PC에서 아파치 웹서버를 이용해 구축한다면 다음처럼 설정해야 할 것입니다.
1 2 3 | < Directory /path/to> Options Indexes FollowSymLinks </ Directory > |
앞의 예제 설정 파일은 /path/to
하위 디렉토리를 인덱싱하고
읽기 권한이 있는 파일에 웹서버를 통해 접근할 수 있도록 설정해줍니다.
물론 처음부터 구현해서 동일한 기능을 만들 수도 있겠지만,
대신 CPAN의 Plack::App::Directory 모듈을
이용하겠습니다.
Plack::App::Directory
를 이용하면 HTTP 파일 서버를
띄우는 일은 너무 간단합니다.
1 | Plack::App::Directory->new(root => "/path/to" )->to_app; |
sdcard
를 파일 서버의 루트 디렉터리로 마운트하고
8080
포트로 웹서버를 실행시키는 전체 소스는 다음과 같습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | use strict; use lib '/sdcard/sl4a/scripts/perl5/lib/perl5' ; use Android; use Plack::Builder; use Plack::App::Directory; use HTTP::Server::Simple::PSGI; my $droid = Android->new; my $app = builder { mount "/" => Plack::App::Directory->new(root => '/sdcard' ); }; my $server = HTTP::Server::Simple::PSGI->new(8080); $server ->app( $app ); $server ->run; |
의존 모듈 설치
앞에서 보다시피 CPAN의 모듈을 사용하면 간단히 원하는 웹서비스를
구축할 수 있습니다.
하지만 이렇게 CPAN 모듈을 사용하려면 해당 모듈은 물론
그에 의존하는 모듈을 모두 설치해야 합니다.
앞서 작성한 Perl 스크립트를 실행시키려면
안드로이드 기기의 /sdcard/sl4a/scripts/perl5/lib/perl5
디렉터리에
기본적으로 사용하고 있는 다음 모듈을 설치해야 합니다.
Plack::Builder
Plack::App::Directory
HTTP::Server::Simple::PSGI
이 외에도 동일한 경로에 다음 의존 모듈도 설치해야 합니다.
CGI
parent
integer
CGI::Util
DirHandle
FileHandle
HTTP::Date
Time::Local
URI::Escape
File::Spec::Unix
HTTP::Server::Simple::CGI
사실 parent와 integer 두 모듈은 Perl의 기본(core) 모듈이지만 어찌된 이유인지 SL4A용 Perl에는 기본으로 들어가 있지 않기 때문에 역시 따로 설치해야 합니다.
Use App::cpanminus;
원리는 간단합니다. 순수 Perl로 구성된 모듈을 시스템에 설치한 후 직접 설치한 파일을 안드로이드 기기의 해당 디렉터리에 복사하면 됩니다. 참 쉽죠? :-)
그런데 만만하게 보고 실제로 복사하기 시작하면 녹녹한 일이 아니란란 것을 알게 될 것입니다. 기본적으로 모듈의 의존성 부분을 점검해서 의존하는 모듈을 모두 재귀적으로 복사해야 하기 때문입니다. :-(
하지만 걱정하지 마세요!
우리에겐 CPAN의 App::cpanminus 모듈이 있답니다!
App::cpanminus
를 설치하면 같이 설치되는 명령줄 도구인 cpanm
을
사용하면 우리가 해야할 일은 놀라울 정도로 간단해집니다.
작업 순서는 다음과 같습니다.
- SL4A 설치
App::cpanminus
를 설치- 컴퓨터에 안드로이드 기기를 연결해서 USB 저장소로 마운트
- PC의 명령줄에서
cpanm
의-l
옵션으로 사용할 모듈을 안드로이드 기기에 바로 설치 - SL4A를 실행해서 확인
도전!
SL4A 설치
SL4A 설치는 생략하겠습니다.
SL4A 설치를 완료하면 /data/data/com.googlecode.perlforandroid/files/perl/perl
에
Perl 바이너리 파일이 있습니다.
안드로이드 SDK를 설치했다면 adb
로 확인할 수 있습니다.
1 2 3 4 | $ adb shell "/data/data/com.googlecode.perlforandroid/files/perl/perl -v" This is perl, v5.11.0 (*) built for arm-eabi-linux Copyright 1987-2009, Larry Wall ... |
참고로 SL4A Perl의 @INC
정보는 다음과 같습니다.
1 2 3 4 5 6 | $ adb shell "/data/data/com.googlecode.perlforandroid/files/perl/perl -e 'print join(\"\n\", @INC)'" /data/data/com .googlecode.perlforandroid /files/perl/site_perl/5 .10.0 /arm-eabi-linux /sdcard/com .googlecode.perlforandroid /extras/perl/site_perl/5 .10.0 /data/data/com .googlecode.perlforandroid /files/perl/5 .10.0 /arm-eabi-linux /data/data/com .googlecode.perlforandroid /files/perl/5 .10.0 /sdcard/com .googlecode.perlforandroid /extras/perl/site_perl |
App::cpanminus 설치
이번 크리스마스 달력 18일자 기사에
소개된 cpanm
을 사용하려면 App::cpanminus
모듈을 설치해야 합니다.
1 | $ cpan App::cpanminus |
안드로이드 기기를 USB 저장소로 마운트
안드로이드 기기를 USB로 연결해서 컴퓨터에서 직접 SD 카드에 접근할 것이므로 USB 저장소로 마운트하도록 합니다. 넥서스원의 경우 USB 저장소로 마운트하면 안드로보이 아이콘이 녹색에서 주황색으로 바뀝니다.
cpanm으로 모듈 설치
안드로이드 기기를 USB 저장소로 마운트했기 때문에 컴퓨터에서는
일반적인 하드디스크와 마찬가지로 접근할 수 있습니다.
여기에 cpanm의 설치 경로를 지정하는 -l
옵션(--local-lib
옵션과 동일)을
이용해서 안드로이드 기기에 직접 설치하는 것이 바로 핵심입니다!
이것 말고도 cpanm
의 유용한 옵션은 cpanm -h
으로 확인해보세요.
cpanm
으로 필요한 CPAN 모듈을 설치하려면 다음 명령을 실행합니다.
1 2 3 4 5 6 7 8 9 10 | $ cpanm -l /media/3532-3831/sl4a/scripts/perl5 --reinstall -qfn \ CGI \ CGI::Util \ HTTP::Date \ Time::Local \ URI::Escape \ Plack::Builder \ Plack::App::Directory \ HTTP::Server::Simple::CGI \ HTTP::Server::Simple::PSGI |
하지만 설치해야할 모듈이 많고, 몇 가지 빠진 기본 모듈도 있는 관계로 쉘스크립트로 만들었습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #!/bin/sh DST= /media/3532-3831/sl4a/scripts/perl5 CPAN_MIRROR= file : ///home/hshong/mirrors/minicpan cpanm --mirror $CPAN_MIRROR --mirror-only FileHandle DirHandle cpanm --mirror $CPAN_MIRROR --mirror-only -l $DST --reinstall -qfn \ CGI \ CGI::Util \ HTTP::Date \ Time::Local \ URI::Escape \ Plack::Builder \ Plack::App::Directory \ HTTP::Server::Simple::CGI \ HTTP::Server::Simple::PSGI # cpanm이 설치해주지 않는 기본 모듈중 의존성 있는 항목을 직접 복사 mkdir -p $DST /lib/perl5/File/Spec cp `perldoc -l File::Spec::Unix` $DST /lib/perl5/File/Spec cp `perldoc -l integer` $DST /lib/perl5 # SL4A에 없는 Perl 기본 모듈 cp `perldoc -l parent` $DST /lib/perl5 # SL4A에 없는 Perl 기본 모듈 cp `perldoc -l DirHandle` $DST /lib/perl5 cp `perldoc -l FileHandle` $DST /lib/perl5 # 필요없는 XS모듈 디렉토리 제거 rm -rf $DST /perl5/lib/perl5/auto rm -rf $DST /perl5/lib/perl5/autoi686-xxx |
우선 --mirror
옵션과 관련된 $CPAN_MIRROR
등의 항목은 CPAN을
로컬 미러링해서 사용하는 사용자가 아니라면 필요없습니다.
$DST
에서 사용하는 경로인 /media/3532-3831
는 현재 제가 사용하고 있는
넥서스원의 SD 카드를 마운트했을 때의 경로이므로 실제로 사용하는
안드로이드 기기에 맞는 정보로 변경해주세요.
컴퓨터에 연결했다면 리눅스의 경우 df
명령어로 확인할 수 있습니다.
SL4A에서 확인
자 Plack을 사용해서 작성한 파일서버 스크립트를 실행시켜 볼까요?
내부 IP를 확인하고 http://192.168.x.x:8080/
으로 접속해보죠.
우앙!굳! ;-)
이제 웹서비스를 안드로이드 기기에 구축하고 실행할 수 있게 되었습니다.
참 현재 Android::wifiGetConnectionInfo
에 버그가 있어서
내부 IP를 바로 확인할 수 없다는 것에 유의하세요.
정리하며
안드로이드 기기에서 Perl이 돌아간다는 것은 단순히 안드로이드 기기에서
Hello World를 출력할 수 있는 것 이상을 의미합니다.
비록 cpan
쉘을 바로 사용할 수 없다는 것과 XS 모듈의 경우
크로스 컴파일 환경을 갖추지 않는 이상 설치하기가 번거롭다는 점이
아쉽지만 순수하게 Perl로 구현된 모듈이라면 정말 간단하게 설치해서
사용할 수 있습니다.
안드로이드 기기에서 Perl을 사용해 웹서비스를 만들고
서버로 실행시킬 수 있다는 것, 매력적이지 않나요?
자, 이제 필요한 것은 여러분의 아이디어입니다. ;-)