Sunday, April 26, 2009

Perl 스크립트 개발의 개발부 방식과 운영부 방식

제가 "지금" 하고 있는 호스팅 가상화에 대한 API부분을 하고 있습니다.
"지금"이라는 것은, 원래 하는 일은 아니라는 의미입니다.

웹에이전시에서 여러가지 OS와 여러가지 Language로 작업을 해오다 일본 회사로 전직했는데,
최근 불경기 영향으로 회사에서는 파견사원들을 쓰지 않고, 필요한 Skill을 가지고 있는 사원들을 그때 그때 팀을 재편성해서(소속은 그대로이고, 업무지원형식으로) 작업을 하는 방식으로 진행중입니다.
이러다 보니, 깊이는 옅어지고, 손을 대본 것은 많고 하는 상황이 되어 어떤것이 나의 Speciality인지 잘 모르게 되어버렸습니다.

그중에서 어떤 일을 담당하고 있느냐면,
이 회사의 호스팅부는 Viruozzo라는 가상화 소스프웨어를 이용해 OS를 가상화해 호스팅합니다.
한대의 서버에 약 100대정도의 OS의 가상화가 가능하다는군요. 쉽게 말씀드리면 한대의 서버에 100개의 VMware나 VirtualPC를 동작시키는 셈입니다.

이중에서 제가 맡은 일은, 가상시스템을 생성해서, 관리하고, 파괴하는 일련의 API를 웹, Zend방식(SOAP방식이 아닌)의 API를 만드는 일입니다.
Request를 받아 DB(MySql)에 기록하고, LDAP에 도메인생성이나, 메일계정생성을 호출하는 perl을 system call하고, 가상서버의 Quota를 제어하고,
가상서버에 메일계정을 만든다던지, Ftp서비스를 세운다던지, 심지어는 phpadmin, wiki, MovableType까지 만드는(실제로는 그런 perl script를 call해서 결과만 돌려줍니다) 그러한 부분을 작업하고 있습니다.

개발 환경으로는, 작업언어는 Perl, 웹인터페이스는 HTML::Template 모듈, MySql의 UDF를 사용합니다.
아. 그리고 Python으로 된 Func라고 하는 Tool을 사용하는 Python 스크립트 작업도 약간 참여합니다.
역시 Perl에서 System Call하는 스크립트죠.

이 일을 하게되어, 2001년도를 마지막으로 손댔던 Perl을 다시 만지게 되었습니다.
그 당시는 CGI.pm사용해서 웹을 작성하는 정도로, 다른 언어에의 동경이 많았는데, 지금 다시 사용하게되어보니, Perl이 굉장히 훌륭하네요. (왜 그때는 미처 몰랐지)
특히 Groovy와 비교해 가며 작업하면 재미있습니다. Groovy OneLiner

Perl을 선택한 것은 제가 아닙니다. 여기는 시스템본부 아래에 운영부와 개발부가 있는데, 저는 개발부 소속입니다. 이 작업은 운영부의 책임으로 제작되는 것이고, 저는 여기에 지원을 나와있는 거죠.
운영부이니 Perl이나 Vi와 같은 유닉스 시스템 작업을 잘 하는 사람들이 많습니다.

그런데 이 운영부의 특징이랄까 개발자의 입장에서 보면, 조금 안타까운 점이 있습니다. 객체지향적인 코드보다는 절차지향적인 방식으로 진행하는 경우가 많고,
파일을 분리하는 것보다 하나로 뭉쳐서 개발하는 방식이라던지 하는 부분이 그렇습니다.
하긴, 예전에 어떤 소스를 보면, 300메가정도되는 펄스크립트 파일을 pperl로 돌리더군요. (vi가 가장 손에 익을 에디터라면 나라도 하나의 파일로, ctags정도를 사용해서 하는 것이 편할 것 같군요.)
또 최근에는 Perl도 SQL::Library를 사용해서 SQL과 Perl을 분리하는 것이 가능한 것 같습니다. 이를 사용하고자 하면, "꼭 사용할 필요가 있느냐"라고 얘기하는 군요.
객체로 나누어 하면, 이해해야하는 범위를 캡슐화 하기 좋고, 단위 테스트에 좋다라는 개발자의 입장과
유지보수시의 Simplicity를 우선하고, cron으로 실행할때라던지와 스크립트언어이기 때문에 퍼포먼스를 먼저 생각하는 admin의 입장이 서로 드러나는 부분인 것 같습니다.

만약 운영부에서 python이나 ruby를 시스템관리 언어로 사용한다면 제 의도가 많이 반영될 지 모르겠습니다만, 아직까지는 시스템 관리 언어로 perl이 압도적입니다.
이러한 의미에서 Perl6가 매우 기대되네요. Perl VM이라니, IL을 사용하는 지는 잘 모르겠습니다만, 사용한다면 ruby나 java를 IL로 컴파일 하는 것도 가능할까요?
재미있을 것 같습니다. :-)

Saturday, April 25, 2009

ActivePerl의 Tip - package의 선언후 처리

우선 코드보터 보시죠. 다음의 코드는 파일로 저장해서 실행하는데 아무런 문제가 없습니다.
Moose의 예제입니다.

package Whitecat;
use Moose;

has name => (is => 'ro');
has age => (is => 'ro', isa => 'Int', required => 1);

1;

my $whitecat = Whitecat->new(
name => 'ねこ',
age => 30,
);
print $whitecat->name;

그런데 이 코드를 Emeditor의 매크로로 실행하기 위해
ActivePerl로 넘겨 실행하기위해 살짝 바꾸어 처리를 하면

evalperl #이하의 코드를 ActiverPerl로 실행하게 하는 명령입니다.
package Whitecat;
use Moose;

has name => (is => 'ro');
has age => (is => 'ro', isa => 'Int', required => 1);

1;

my $whitecat = Whitecat->new(
name => 'ねこ',
age => 30,
);
$window->document->writeln($whitecat->name); #window는 Emeditor에서 제공받는 객체입니다.

다음과 같은 에러가 발생합니다.

ScriptControl.ExecuteStatement Error
16389:Global symbol "$window" requires explicit package name
source:PerlScript Error

이 에러를 회피하기 위해서, Compile할 때와, 실행할 때로 나누도록 BEGIN문으로 block을 잡아주니 문제없이 실행되었습니다. 다음은 에러가 없는 전체 코드입니다.
evalperl
BEGIN {
package Whitecat;
use Moose;

has name => (is => 'ro');
has age => (is => 'ro', isa => 'Int', required => 1);

1;
}

my $whitecat = Whitecat->new(
name => 'ねこ',
age => 30,
);
$window->document->writeln($whitecat->name);

perl의 설계상 특성중 동적언어의 유연함을 잘 이용하려면, Scope라고 해야 할까요. Phase라고 해야할까요. 다음의 block을 이용해야 할 때가 있을 것 같습니다.

컴파일시 : BEGIN,
초기화시 : CHECK(역순), INIT
실행시 : 일반코드
종료시 END(역순)

ActivePerl의 Tip - 2바이트언어 주석

나는 Windows환경(2003 server)에서 Perl은 ActivePerl을 사용하고 있습니다.

Strawberry Perl을 사용하면 gcc가 함께 있어 CPAN에 있는 많은 모듈을 사용할 수 있는 반면(유닉스 시스템명령어나 네트웍관련 명령어를 사용하는 모듈, 또는 fedora관리용등의 legacy모듈은 사용할 수 없겠죠.),

ActivePerl은 보통 PPM(perl package manager)으로 누군가의 Repository에서 Win32용으로 컴파일된 모듈을 설치해 사용하는 것이 보통이기 때문에, Strawberry Perl보다 제한된 모듈을 사용할 수 있습니다.

그럼에도 불구하고 ActivePerl을 사용하는 이유는(저도 무척이나 Strawberry Perl을 사용하고 싶습니다...만, 진짜 Perl(?)이 필요한 경우는 Fedora10 VirtualPc를 기동시켜 사용하고 있습니다.) ActiveX를 제공하기 때문입니다. Strawberry Perl는 이 것을 제공하고 있지 않습니다. (참조 http://win32.perl.org/wiki/index.php?title=Win32_Distributions)

Perl의 ActiveX지원 기능이 나에게 중요한 이유중에 가장 중요한 이유로는 바로 Emeditor때문입니다. 파일로 저장해 실행하는 방식만이라면 저도 Strawberry Perl을 추천할 것 같습니다.

이 Emeditor 에디터는 WSH를 이용하여 매크로를 작성하는 것이 가능합니다. 즉 VBS, JScript, ActivePerl, ActivePython, PHPScript, RubyScript(ActiveScriptRuby 의 다운로드는 여기 http://arton.hp.infoseek.co.jp/indexj.html)를 이용하여 매크로를 작성하는 것이 가능하게됩니다.

가까운 사람들의 매크로 작성의 참여를 위해, JScript로 선택해 만들기 시작했던 매크로가 점점 기능이 많아져 꽤 도움이 됩니다. (이 기능 때문에 GVim을 떠났고, HappyHacking 키보드도 사용하지 않게 되어버렸습니다. 에디터가 많은 것을 바꾸게 하는군요.) 그런데 매크로 언어로 선택한 JScript로는 가능하지 못한 작업들도 있습니다. 예를 들면, GD라이브러리로 그래프를 그린다던가, ImageMagic으로 이미지를 손대는 매크로는 JScript로는 시도해 보고 싶지 않습니다. 이러한 경우는 ActivePerl을 사용합니다.(아직까지 ActivePython이나 ActiveRuby등은 사용하고 있지 않습니다.)

그런데, ActivePerl에 한글주석이나, 일본어 주석이 있는 경우, 제대로 실행해 내지 못합니다. 예를 들면 다음과 같은 코드(JScript코드입니다.).

var perlcode = "sub main { return \"Perl ! \"; }";
var perl = new ActiveXObject("ScriptControl");
perl.Language = "PerlScript";
perl.AddCode(perlcode);
var result = perl.Run("main");
document.writeln(result);

제가 사용하는 Emeditor매크로에서는 실제로는 위와 같이 사용하지 않고 있습니다만, 위 예제는 Excel등에서 응용하기 좋은 Sample이라고 생각합니다. 제 Emeditor매크로에서는 #language="PerlScript" 이외에도 몇가지 지저분한 코드를 사용해 사용하고 있습니다.


위 코드를 JScript로 실행하면 예상하듯, Perl ! 이라는 출력을 얻을 수 있습니다. (물론 ActivePerl이 설치되어 있어야 합니다.)

그런데 펄의 코드중에 한글로 주석을 달거나 한글을 출력하도록 다음과 같이 수정했을 때, 제대로 실행되지 않습니다.

var perlcode = "sub main { return \"한글\"; }";

나오는 에러코드는 다양했습니다.
Can't find string terminator '"' anywhere before EOF
Illegal division by zero
...그리고 에러가 발생하지 않는 경우도 있었습니다.

이 코드는 테이타를 파일에서 불러오는 경우는 잘 됩니다. 이 경우는 Strawberry Perl이던지 ActivePerl이던지 문제가 없죠.

오늘의 Tip이란 이 부분의 해결입니다. 해결의 Url은 http://miau.s9.xrea.com/blog/index.php?itemid=642 입니다.

원인이라던지 대책은 다음의 URL에 적혀 있습니다만, 이 이야기는 Tip의 내용을 벗어나네요.
http://miau.s9.xrea.com/blog/index.php?itemid=659
http://undine.sakura.ne.jp/diary/d200608b.html#r18
http://www.namazu.org/~tsuchiya/perl/perl-5.8.html#opened_questions

사실. 이 내용이외에도 2바이트 문자열을 사용하는 경우, 조금 더 문제가 있는 듯 합니다. 예를 들면 윈도우즈 환경이다보니, 파일명에 한글을 넣거나 일본어를 넣었을 경우 file handle하는 부분이라던지.... 이 내용은 경험하게 되면 올리도록 하겠습니다. 파일명을 한글, 일본어가 아닌 영어로 적도록 늘 신경을 쓰고 있어서 아직 경험하지 못한 것도 있습니다만, miau님의 블로그에 그 해결내용이 있었던 것이 기억납니다.

여러 언어를 사용하다보면, 역시 각각의 장점이 있다라는 생각이 듭니다. 그것이 컴퓨터 언어든, 자연어든지 말이죠 ;-)

이상. 잘부탁드리겠습니다. m(__)m

Tuesday, April 7, 2009

블로그 정리하겠습니다.

그만 두겠다는 말이 아니고, 정리해서 다시 잘 쓰겠습니다. :-)

Thursday, March 5, 2009

Chapter 5. The IoC container

Spring의 DI공부하고 싶다면,

Spring.Net 1.2 설치하고, 설치되는 Document의 Chapter 5를 보라.

public static void Main(string[] args) {
try {
// Create AOP proxy using Spring.NET IoC container.
IApplicationContext ctx = ContextRegistry.GetContext();
} catch (Exception ex) {
Console.Out.WriteLine(ex);
}
}

이거 하나면 하루종일 xml로 인스턴스를 계속 만들었다 부셨다 해도 좋다.

Js.Net이고 try catch가 필요없다면,

var ctx = ContextRegistry.GetContext();

이거 한줄이면 된다. 충분히 연습해 보길.
xml로 instanciate한 것을 출력하는 xstream같은 XML serializer가 있으면 좋겠군

Wednesday, March 4, 2009

app.config에 대해서

csc, vbc, jsc등 커맨드라인으로 컴파일하거나, nant를 사용하여 컴파일 할 때,
사용자가 만든 라이브러리를 reference해서 컴파일 하는 경우,
dll파일이 현재 디렉토리에 있지 않고 다른 곳에 있는 경우가 있다.

즉 nant같으면

<target name="build">
<mkdir dir="${build.dir}">
<csc target="exe" output="${build.dir}/${basename}.exe" debug="${debug}">
<sources>
<include name="*.cs">
</include>
<references>
<lib>
<include name="C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727">
<include name="C:\dev\rensaba\LivedoorServiceApiClient\LivedoorServiceApiClient\bin\Release">
<include name="C:\dev\rensaba\MobileLivedoorApiWrapper\MobileLivedoorApiWrapper\bin\Release">
</include>
<include name="mscorlib.dll">
<include name="System.dll">
<include name="System.Data.dll">
<include name="System.Xml.dll">
<include name="Livedoor.dll">
<include name="LivedoorBatch.dll">
<include name="LivedoorServiceApiClient.dll">
<include name="MobileLivedoorApi.dll">
</include>
</include>
</include>

위와 같이 컴파일 한 경우,
실행하면

<target name="run" depends="build">
<exec program="${basename}.exe" basedir="${build.dir}">
</exec>

어떤 에러가 나오느냐 하면

C:\crowdy\LivedoorTest>bin\CDBAccountTest.exe

ハンドルされていない例外: System.IO.FileNotFoundException: ファイルまたはアセンブリ 'Hosting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'、またはその依存関係の 1 つが読み込めませんでした。指定されたファイルが見つかりません。
ファイル名 'Hosting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' です。
場所 Test.CDBAccountTest.Main(String[] args)

警告: アセンブリ バインドのログ記録がオフにされています。
アセンブリ バインドのエラー ログを有効にするには、レジストリ値 [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) を 1 に設定してください。
注意: アセンブリ バインドのエラー ログに関連するパフォーマンス ペナルティがあります。
この機能をオフにするには、レジストリ値 [HKLM\Software\Microsoft\Fusion!EnableLog] を削除します。

와 같은 에러가 나온다.

나는 처음에 저렇게 레퍼런스를 주고 컴파일 하면, static library로 실행파일 안에 함께 Link될 줄 알았다.
이게 무슨 말이냐면, 어셈블리를 찾을 수 없다라는 얘기다.
마치 java에서 jar를 찾을 수 없다라는 얘기와 같다.
java에서 컴파일 할 때, 실행할 때, 모두 외부 라이브러리가 필요한 것처럼, 닷넷에서도 실행할 때 외부라이브러리(어셈블리)정보를 알아야 한다.
그런데 닷넷에서는 -classpath와 같은 옵션은 주지 않는다. 자체로 실행파일이기 때문에.

그렇다면 그 정보는 어디서 가져오나? (어떻게 줄 수 있나?)
바로 app.config를 이용한다.
이 app.config는 IDE에서 빌드하면 debug나 release디렉토리에 <타겟이름>.exe.config (dll 타입인 경우는 .exe.config)로 복사된다.
이 app.config를 이용하여 실행시 default parameter를 주는 것도 가능하고,

<configuration>
<appsettings>
<add key="OperatorName" value="Rita"></add>
<add key="LoggerLevel" value="5"></add>
</appsettings>
</configuration>

string name = System.Configuration.ConfigurationManager.AppSettings["OperatorName"];
Console.Writeline("Welcome " + name);
string level = System.Configuration.ConfigurationManager.AppSettings["LoggerLevel"];
Console.Writeline("Logger level: " + level);

참고로 전체에 영향을 주는 Machine.config파일도 있다.
The machine configuration file, Machine.config, contains settings that apply to an entire computer. This file is located in the %runtime install path%\Config directory. Machine.config contains configuration settings for machine-wide assembly binding, built-in remoting channels, and ASP.NET.
from http://msdn.microsoft.com/en-us/library/ms229697.aspx

또한 잔넹이지만, Nant는 컴파일 할 때 app.config파일을 알아서 복사해 주지 않는다.
수동으로 다음과 같이 하는 방법이 있다고 한다.
간단하게라면
<copy file="${Foo.src.dir}/app.config" tofile="${build.dir}/Foo.exe.config">
from http://kseek.blogspot.com/2005/04/rename-appconfig-to-fooexeconfig-in.html
로 끝나고,

좀 복잡한 프로젝트 라면 다음과 같이 하면 된다.
<foreach item="File" property="exefile">
<in>
<items>
<include name="${build.configuration}/*.exe">
</include>
</items>
<do>

<property name="basename" value="${path::get-file-name-without-extension(exefile)}">
<copy file="${basename}/App.config" tofile="${outputdir}/${basename}.exe.config">
</copy>
</property>
from http://d.hatena.ne.jp/Horiuchi_H/20060529/1148880306

닷넷 프레임웍의 Configuration File Scheme은 굉장히 복잡한데
from http://msdn.microsoft.com/en-us/library/1fk1t1t0.aspx

내가 필요로 하는 샘플은 이쪽 http://blogs.msdn.com/suzcook/archive/2004/05/14/132022.aspx 에 있었다.


<configuration>
<runtime>
<assemblybinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentassembly>
<assemblyidentity name="assemblyName" culture="" publickeytoken="8968ee41e78ce97a">
<codebase version="1.0.0.0" href="http://www.yourwebsite.com/filename.dll">
</codebase>
</assemblyidentity>
</dependentassembly>
</assemblybinding>
이 href부분을 “file:///c:/localfile/filename.dll“ 와 같이 정의하면 된다라고 한다.

또 이 샘플로 내가 필요로 하는 정보가 하나 더 있음을 알게 되었는데,
내 로컬머신에는 닷넷 프레임웍 1.1, 2.0, 3.5가 설치되어 있다.
어떤 버전의 프레임웍으로 실행해야 하는지 정의하는 것도 이 app.config파일에서 하는 것임을 알게 되었다.


<configuration>
<startup>
<requiredruntime version="v1.0.3705">
<supportedruntime version="v1.0.3705">
</supportedruntime>
</requiredruntime>

App.Config를 만드려면

To create App.Config:
1. From Project, select Add New Item…
2. Select "Application Configuration File", and click Add.

from http://blogs.msdn.com/andyhar/archive/2005/06/25/432691.aspx

또는

Right-click the project in the Solution Explorer and choose the Add->New Item... tab.
In the Add New Item window select the Application Configuration File.

from http://download.oracle.com/docs/cd/E13924_01/coh.340/e12192/netsampformapp.htm#BCEGGFDA

Windows WorkFlow의 App.conf를 세팅하려면 http://msdn.microsoft.com/en-us/library/ms734706.aspx

IDE가 아닌 Console App로 자동으로 app.config를 만드는 방법은 없을까?

이 파일은 XML 형식으로 되어 있는데, 이를 전부 외워서 설정하기에는 많은 어려움이 있다.
그래서 설정 툴을 사용하면 되는데, 엔터프라이즈가 설치된 폴더의 bin 폴더 아래에 보면 EntLibConfig.exe 파일이 있다.
바로 이 프로그램이 구성 설정 파일을 손쉽게 그래픽 기반으로 해주는 프로그램이다. 이 프로그램을 이용하면 해당 구성 파일을 손쉽게 편집할 수 있다.
from http://saga21.net/970?TSSESSION=42e9e1052d8b9bd855d134515955372d

위의 블로그에서 본 것이지만, Enterprize Library Configuration 이라는 유틸리티가 app.config파일을 만드는데 도움이 된다.
또 이 app.config의 값은 암호화해서 배포하는 것도 일반적인 것 같다.
java의 Apache Jakarta의 Common처럼 닷넷에서도 자주 쓰이는 라이브러리 기능을 모아서 발표하는 곳이 있었다.
msdn에 소개되어 있지만, Open project이다. 다운로드는 이쪽에서 받고 (글을 쓰는 현재 최신버전은 4.1버전)
http://www.microsoft.com/downloads/thankyou.aspx?familyId=1643758b-2986-47f7-b529-3e41584b6ce5&displayLang=en

하지만,
Microsoft.Practices.EnterpriseLibrary.Common.Configuration.SystemConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
과 같이 정의하는 PublicKeyToken은 뭘 넣어야 하는지 알 수 없다.
FrameWork을 설치하면 이것을 알아내는 유틸리티가 두개가 있다.
이 정보가 이 Post의 핵심.

sn -T MyAssemby.DLL
IlDasm is another utility. Both come with the FrameWork.

from http://www.eggheadcafe.com/conversation.aspx?messageid=32180871&threadid=32180864

p.s.>
sn -T MyAssemby.DLL 이건 emeditor에서 쉽게 만들도록 매크로로 만들어야겠다.

p.s.>
Nant에도 ildasm task가 있기는 하다.
http://nant.sourceforge.net/release/0.85/help/tasks/ildasm.html

p.s.>
또 MS에 Guidance Automation Tookit과
Guidance Automation Extension이 있다. 뭐하는 건지는 따로 나중에 조사해야겠다.

Tuesday, March 3, 2009

엔터프라이즈 솔루션 개발의 생산성: java vs dotnet

나는 내 경험으로, 하드웨어나 라이센스비용을 제외하고, 생산성만을 얘기한다면,
*) 엔터프라이즈 어플리케이션 개발에 있어서,
Java와 닷넷 언어에 한해 비교하자면(다른 언어는 제외하고 말하자면),
java쪽 언어는
팀단위로 일을 한다면
닷넷 언어를 선택하는 하여 개발하는 것과 비교해
같은 생산성을 내기에 비용이 훨씬 많이 든다.

단, 혼자서, 또는 오랜기간 호흡을 맞춰온 훈련된 지극히 소수의 팀으로 일을 한다면
어느쪽을 선택하던 상관없다.

그런데 실은 Java나 그 라이브러리가 닷넷의 것에 비해 너무 어렵다거나,
복잡하다고 생각하지 않기 때문에, 비슷해야할 것 만 같은 느낌이 든다.
하지만 경험상으로 결과는, 명백히 닷넷쪽이 훨씬 비용이 적게든다.