Category Archives: 프로그래밍

오랜만에…

작년말부터 계속 글을 못올렸네요.

작년 12월초에 아이폰을 구매하면서부터 컨텐츠 소비(주로 구글리더)를 출퇴근시간에 하다보니 따로 시간 내어서 블로그에 글쓰는게 더 어려워졌던거 같네요.

아이폰 쓰기 시작하면서부터 플랫폼으로써 가능성이 보여서 혼자 공부도 하고, 노트북(Lenovo X61)에 OSX도 깔아보고, 회사에 어필한 결과 올해 2월부터 맥북으로 아이폰앱을 개발하게 됐었습니다. OS도 새롭고, 개발환경도 새롭고, 언어는 더 생소해서 여러가지로 많이 배울수 있었던 시간이었네요. 다만 4월말에 개발이 완료 됐는데, 애플의 정책정리로 얼마전에서야 앱스토어에 올라오게 됐습니다.

생각보다 반응이 괜찮아서 올린지 하루만에 카테고리 1위하고, 열흘정도 됐는데 아직 카테고리 1위를 유지하고 있습니다. 전체 순위도 6위까지 올라갔다가, 현재는 상당히 밀렸네요. iOS4에 맞춰서 새로운 기능이 들어가서 나름 선전한거 같습니다.

개인적으로 만들어보고 싶은 여러가지 어플들이 있는데, 집에 오면 다 귀찮아져서… 아직 개인 앱은 올리지 못하고 있습니다.

아이폰 개발하면서 그전에 사용하던 언어와 개발환경에 대해서 다시 생각해보는 계기가 되었네요.

제가 사용하거나 했던 언어와 개발 환경 정리입니다.

  • BASIC (C-64)
  • UNIX – C, pro-c, X11, Motif, Tcl/Tk, Qt
  • Java
  • FreeBSD/Linux – C, lex/yacc
  • Python
  • Windows – Visual C++, MFC
  • Flash – Actionscript3
  • iOS – Objective-C

언어와 제가 느낀 점.

  • BASIC  – 제가 접한 첫 언어. 초딩때 게임도 만들었어요.
  • C – 가장 기본이 되는 언어.
  • Tcl/Tk – 스크립트 언어로서 UI와 UI builder(XF)까지 놀라웠죠. (95년?)
  • Python – 간결함과 표준 라이브러리가 인상적. 자료구조 쉽게 쓸수 있어서 프로그래밍 방식 변화
  • C++ – STL 좋음. 언어는 너무 복잡. 자유도 많아서 안좋음.
  • Java – 언어는 모르겠고, JVM에는 관심갑니다.
  • Actionscript3 – FlashDevelop와 사용하면 너무 편한 언어. 도움말 및 예제 굿! Javascript에 비하면 좀더 일반적인 객체지향 언어.
  • Objective-C – 강력한 개발환경과 애플의 개선을 위한 필사적인 노력.

이외 관심있는 언어:

  • OCaml
  • LISP
  • Erlang
  • JVM 위에서 돌아가는 함수형 언어들

memcached를 이용한 grace 기능 구현

Varnish Cache의 grace 기능을 PHP/memcached로 구현했습니다.

grace 기능은 백엔드 서버가 죽더라도, 캐싱되어 있는 정보로 지속적인 서비스가 가능하도록 하는 기능입니다. 캐싱할때 여분의 시간(grace 시간)동안 더 캐시를 유지하며, 캐싱 시간이 지났을때 백엔드에 요청이 한번만 전달되게 하고, 나머지 요청에 대해서는 우선적으로 그 전에 있던 캐시로 서비스를 하도록 하여 백엔드 서버의 부하를 줄일수 있습니다.

현재는 memcached에서 expire 되면서 동시에 요청이 발생하는데, grace 기능을 구현하면 오래걸리는 페이지 생성할때 큰 효과를 발휘할수 있을거라 기대됩니다.

PHP 구현은 간단합니다. 원래 key,value 항목의 expire
시간을 grace 시간 만큼 늘리고, 다른 키(key+”_s”)에 expire 시간동안 상태값을 입력해두면, 어렵지 않게 grace 기능을
구현할수 있습니다.

초기에 캐시에 없을때는 백엔드에 동시에 여러 요청이 들어갈수 있습니다. 이미 요청이 처리되고 있을때(state=”G”), 일정시간동안 주기적으로 memcached를 조회해서 key가 있을때까지 대기하는 방법으로 어느정도 해결 가능할 거라 생각하지만 구현은 하지 않았습니다.

[CODE type=php]
array(‘127.0.0.1:11211′), ‘debug’ => false, ‘persistant’ => false));

function generate_value($key) {
sleep(5);
return “VALUE”. $key;
}

function get_value($key) {
global $mc;
$expire = 60;
$grace_timeout = 600;
$generation_timeout = 10;

$state = $mc->get($key.”_s”);
//echo(“state=$state
\n”);
if ($state == “C” || $state == “G”) {
$value = $mc->get($key);
if ($value) {
//echo(“retreive key=$key
\n”);
return $value;
}
}

$mc->set($key.”_s”, “G”, $generation_timeout); // state: Generating
$value = generate_value($key);
$mc->set($key, $value, $expire + $grace_timeout);
$mc->set($key.”_s”, “C”, $expire); // state: Cached
//echo(“insert key=$key
\n”);

return $value;
}

get_value(“hahaha”);
?>

[/CODE]

Flash로 아이폰, 아이팟터치 어플 개발

우리나라 시간으로 오늘 새벽에 Adobe MAX 2009가 열렸습니다.

먼저 Flash 10.1AIR 2.0 에 대한 내용이 소개되었습니다. Flash 10의 기능이 대부분의 스마트폰 플렛폼에 포팅이 되었거나 진행중이라고 합니다. Palm, Windows Mobile, Google Android, Symbian 등의 플렛폼을 지원한다고 하네요. 아쉬운건 아이폰에 대한 지원이 없다는 것이네요.

애플과 어도비의 줄다리기로 아이폰에서 Flash 지원이 언제될지 모르는 상황에서, Flash CS5에서 아이폰 용 응용프로그램으로 출력할수 있는 기능을 제공한다고 합니다. SWF를 기기에서 지원하는것이 아니라 아이폰용 native application으로 컴파일하는거라 하네요. 아이폰용 어플 따로 개발하는 거 자체가 큰 투자였는데 이렇게 되면 많은 회사에서 큰 투자없이 아이폰 플랫폼을 지원할수 있을거라 생각되네요.

아이폰/터치를 지원하는 Flash CS5 베타 버전이 나오면 공지 메일을 받을수 있습니다. http://www.adobe.com/go/flashprobetanotify

관련 URL:
1. http://blog.digitalbackcountry.com/2009/10/rundown-of-the-max-news/
2. http://www.mikechambers.com/blog/2009/10/05/building-applications-for-the-iphone-with-flash/

referer 유지하며 페이지 리다이렉트

페이지 리다이렉트(포워딩)하는 방법이 여러가지 있지만, 대부분의 경우 워래 referer가 사라집니다.

javascript의 href.location 할당 방법, meta tag를 이용한 포워딩 방법, PHP에서 header(“Location: url”) 등 모두 referer가 유지되지 않죠.

HTTP 응답으로 301 Moved Permanently 코드를 사용하면, 원래 referer가 리다이렉트된
페이지에서 잡힙니다.

웹서버에서 특정 페이지에 대해 설정할수도 있지만, PHP에서 아래와 같이 header를 추가한 다음에 Location: 을 설정하면 됩니다.

[CODE type=php]
<?
  header (‘HTTP/1.1 301 Moved Permanently’);
  header (‘Location: newurl’);
?>
[/CODE]

referer는 아래처럼 출력해볼수 있습니다.

[code type=php]
<?
  echo($_SERVER[‘HTTP_REFERER’]);
?>
[/code]

PYCON 2009 비디오

PYCON 2009 (Python Conference 2009) 비디오가 올라와있네요..

http://us.pycon.org/2009/conference/schedule/

몇개의 세션이 취소되서 좀 아쉽지만, 그래도 많은 정보가 있네요 :)

저는 VM쪽 관련한 패널을 흥미롭게 봤고, CPython 이외의 다른 구현들이 이제 많은 부분을 차지하네요.

keynote중에 Reddit에 대한 내용을 재미있게 봤습니다. Reddit이 LISP에서 Python으로 소스를 옮긴 내용도 흥미롭고 서비스 최적화 관련된 내용도 건질게 많았네요.

그리고 Lightning Talks도 참 재미있더군요. Lightning Talks는 한사람에게 딱 5분만 주어지고 한 주제에 대해서 자유롭게 발표하는 것으로 짧은 시간내에 다양한 정보를 얻을수 있고, 넓고 얕은 지식 습득(–)에 도움이 됩니다.

AutoIT MS워드 자동화

전에 AutoIT을 통한 자동화에 대한 글을 쓴적이 있는데, 얼마전에 자동화할때 MS워드에서 정보를 추출할 일이 있어서 AutoIT에 포함된 워드 모듈을 써볼 기회가 있었습니다. AutoIT에서 제공하는 워드 함수에 대한 문서만으로는 자동화하기는 부족하더군요. MSDN을 참고해서 워드의 객체 모델을 어느정도 이해하시고 Range 객초 참고하시면 큰 도움이 될듯합니다. MSDN이 Visual Basic 위주로 되어 있지만, 문법은 동일하게 쓰면 됩니다.

아래 예제 보시면 어느정도 감이 오실듯하네요.

#include <word.au3>

; 화면에 보이지 않고 포커스 안가져가도록 인자 전달
$oWordApp = _WordCreate(“”, 0, 0, 0)

; test.doc 문서 열기
$doc = _WordDocOpen($oWordApp, “test.doc”)

; 문단 객체 가져오기
$paragraph = $doc.Paragraphs
 
; 첫번째 문단 텍스트 가져오기 (텍스트만)
$paragraph1text = $paragraph(1).Range.Text

; 두번째 문단 클리보드에 복사 (포맷,링크,그림등 포함)
$paragraph(2).Range.Copy

; 세번째 문단부터 끝까지 클립보드에 복사
$doc.Range($paragraph(3).Range.Start).Copy

; 세번째 문단부터 다섯번째 문단까지 텍스트 가져오기

$paragraph3to5text = $doc.Range($paragraph(3).Range.Start, $paragraph(5).Range.End).Text

; 문서내 모든 링크 가져와서 출력하고 다른 주소로 변경
For $hyper in $doc.HyperLinks
    ConsoleWrite(“link=” & $hyper.Address & @CRLF) ; 링크 출력
    $hyper.Address = “http://mix1009.net” ; 모든 링크 바꾸기 —
Next

Alchemy를 이용한 Flash Equalizer 구현

Alchemy를 이용해서 Flash 10에서 사용 가능한 Equalizer를 구현했습니다. Flash에서 자체 Equalizer를 제공하지 않아서 여러가지로 고민했었는데… 일단 동작은 정상적으로 하네요. 처음에 PixelBender를 이용해서 구현을 할려고 했었는데 여러가지로 PixelBender는 오디오 처리하기에는 문제가 있는거 같더군요. 회사에서 C로 구현된 Equalizer소스가 있어서 Alchemy를 이용해서 Flash에서 돌릴수 있게 구현했습니다. Flash 10에서만 동작합니다.

 

위에 플래시가 안보이시면 이 페이지로 가시면 보실수 있습니다.

소스는 공개하기 힘들듯 하지만, 요청이 있다면 C Equalizer소스를 제외한 부분만 공개하겠습니다. Alchemy 개발은 그리 어렵지는 않았는데 문서화가 좀 부족해서 여러가지 자료 참고해서 구현했습니다. 막상 개발하고 나니 인터페이스하는 소스는 얼마 안되네요 :)

사용자 삽입 이미지eq.c 소스는 250줄 정도 되고, 이중 100줄 정도가 Alchemy 인터페이스 소스이지만, 많은 부분 재사용할수 있는 부분입니다. 이걸 컴파일하면 플래시 컴포넌트 파일인 swc 파일이 나옵니다. 용량이 82KB 소스에 비하면 많이 커졌네요. 더욱 놀라운건 마지막 as파일의 크기입니다. 파일 열어보면 거의 바이트 코드가 풀어서 적혀 있습니다.

Equalizer소스가 길지않으니 한번 AS3로 직접 짜보고 비교를 해보는것도 재미있을듯하네요. 그리고 인터페이스 소스가 메모리카피가 있어서 좀 비효율적인데 copy 줄일수 있는지도 고민해봐야할듯합니다.

구현하면서 여러가지 좋은 정보들도 많이 얻었습니다. PixelBender에 대해서도 알게 됐고, 플래시 10에서 오디오 처리의 가능성과 한계를 어느정도 알게되었네요.

음악은 아직 제목이 없는 제 음악입니다.^^ (20080208.mp3) 즐감하세요~

MS Authenticode 인증서를 Adobe AIR 서명용으로 변환하기

exe 코드서명할때 쓰이는 pvk(PKCS #7) 파일은 AIR에서는 바로 사용못합니다. PKCS #12 포맷인 pfx나 p12 확장자로 바꿔야하는데 openssl에서는 잘 안되나봅니다(??).

MS에서 배포하는 pvkimprt 와 mmc(Microsoft Management Console)을 통해서 pfx 파일로 변환할수 있고, firefox를 이용하면 다시 p12로 바꿀수 있습니다. 과정이 약간 복잡합니다.

먼저 pvkimprt를 받아서 설치합니다. 설치후에 커맨드 창에서 pvkimprt를 실행하여 인증서를 시스템 개인인증서 영역에 저장할수 있습니다. 중간에 암호 물어보고, 저장위치 지정해서 “개인”으로 선택하면 됩니다.

사용자 삽입 이미지
이제 시작 실행에서 “mmc”를 입력하고 엔터를 치면 Microsoft Management Console를 띄울수 있습니다. 파일 메뉴에서 “스냅인 추가/삭제” 선택후 “인증서”를 추가하세요. 대상을 물어보는데 “내 사용자 계정”을 선택하면 됩니다.

사용자 삽입 이미지

콘솔 루트-인증서-개인-인증서를 선택하면 pvkimprt에서 가져온 인증서를 확인할수 있습니다. 인증서에서 오른쪽 눌러서 속성을
선택하면 인증서 이름을 설정할수 있습니다. (꼭 필요한 과정인지는 모르겠고, 이 과정에서 이름이 바로 적용이 안되거나 오류가
나오면, 스냅인을 삭제했다가 다시 추가하면 정상적으로 보이더군요. 인증서 오른쪽 클릭하여 모든 작업-내보내기 선택하면 드디어
pfx로 저장할수 있습니다. 여기서 몇가지 옵션을 선택해야합니다. “개인키 내보내기”와 “가능하면 인증 경로에 있는 인증서 모두
포함”을 선택하세요. 아래 그림 참조.

사용자 삽입 이미지
이렇게하고 암호 설정을 하면 pfx 파일이 만들어집니다. 이 인증서를 이용해서 AIR 어플에 서명해도 되고, firefox를 이용하면 pfx 파일을 p12 파일로 변경할수 있습니다.

firefox 도구 메뉴-설정-고급-암호화-인증서 보기 클릭하시고, 가져오기 버튼을 눌러서 pfx 인증서를 추가하세요. 인증서 선택하고 백업 누르면 p12 파일로 저장할수 있습니다.

사용자 삽입 이미지
이 문서는 http://www.petefreitag.com/item/117.cfm 를  참고해서 정리했습니다.

jQuery, Jaxer, HTML Parsing

jQuery를 본격적(?)으로 쓰기 시작했는데 쓸수록 마음에 드네요. 자바스크립트 답지 않은 문법, selector를 통한 자유로운 element 선택, 한번에 여러 element에 작업할수 있는 특징. 어떻게 이런 문법으로 라이브러리를 만들 생각을 했는지, 그리고 이렇게 잘 구현했는지 여러가지 생각을 하게끔하는 라이브러리입니다.

웹프로그래밍을 하면 MVC 분리가 잘 안됐었는데 jQuery를 이용하면 이게 어느정도 가능한거 같네요. 일주일동안 사용하는데 너무 마음에 들어서 서버쪽에서도 이런 작업을 하면 편할거 같은 생각이 들어서 좀 찾아봤습니다.

먼저 자바로 짠 자바스크립트 엔진인 Rhino 위에서 여러가지 자바스크립트 라이브러리(jquery, prototype, mochkit)를 돌린 시도가 있어서 저도 따라해봤지만 뭐가 문제인지 정상동작하지 않더군요. 예제에 보면 자바스크립트로 서버쪽 스크립팅을 하는데, 일단 화면에 출력하는거부터 익숙하지가 않으니, 뭐가 잘못됐는지 찾아보기도 힘들더군요. 글 올라온지 1년이 넘어서 버전 차이때문에 그런건지… 자바의 버전때문에 그런건지… 하여간 중간에 포기!

문제 해결을 위해서 웹서핑하다가 Aptana Jaxer에 대해서 알게되었습니다. 전에 이름만 들어봤었는데, 자바스크립트로 서버단에서도 프로그래밍할수 있게 하는 프로젝트입니다. 단순히 HTML에서 script에 runat=”server”로 달아주면, 해당 부분이 서버단에서 처리한 다음에 결과가 클라이언트에 전달됩니다. 클라이언트 단에서 잘 돌아가는 자바스크립트를 서버단에서 수정없이 바로 돌릴수 있습니다. jQuery등의 라이브러리도 서버단에서 잘 돌아갑니다:) 여기서 더 나아가 서버와 클라이언트 자바스크립트간 통신을 할수 있는 방법을 만든거 같네요. 서버단 자바스크립트에서는 디비접속, 파일접근 등 서버단 언어에서 할수 있는 기능들을 라이브러리로 제공합니다. 간단히 클라이언트 단에서 하던 일 정도는 간편하게 서버단에서 처리할수 있지만, 웹서버도 따로 띄워야하고, 다른 서버단 언어와의 연동을 생각하니, 서버단에서 jQuery를 돌린 결과값만 HTML로 받아서 저장하는게 더 편할것 같다는 생각이 들어서 Jaxer 도입은 보류했습니다.

jQuery처럼 편하게 HTML 데이타에 접근해서 데이타를 추출하고, 변경할수 있는 방법을 찾아봤습니다. jQuery의 selector나 XPath등으로 HTML을 파싱할수 있으면 좋을거라 생각하고 검색해보니 libxml2에서 HTML 파싱을 지원하더군요:) python binding이 있고, 그전에 XML에서는 XPath를 이용한 경험도 있으니 금방 될듯하더군요. jQuery로 짠 라인들을 복사하고, 그대로 XPath와 libxml2 라이브러리 함수들로 옮겼습니다. 라인수는 많이 길어졌지만 그래도 소스는 볼만하고, selector로는 불가능한 부분들도 쉽게 구현할수 있다는 생각이 들더군요.

[code type=javascript]
   $(‘a[href^=/]’).each(function(i) {$(this).replaceWith($(this).text()); } );
   $(‘a[href^=#cite]’).remove();
   $(‘span[class=editsection]’).remove();
   $(‘table[class^=navbox ]’).remove();
   $(‘div[class=주석]’).remove();
   $(‘table[id=toc]’).remove();
   $(‘h2 > span’).each(function(i) { if ($(this).text() == “주석”) $(this).remove(); } );
[/code]
[code type=python]
   try:
       parse_options = libxml2.HTML_PARSE_RECOVER + libxml2.HTML_PARSE_NOERROR + libxml2.HTML_PARSE_NOWARNING
       hdoc = libxml2.htmlReadFile(filename, None, parse_options)
   except Exception, e:
       print e
       return

   #$(‘a[href^=/]’).each(function(i) {$(this).replaceWith($(this).text()); } );
   #$(‘a[href^=#cite]’).remove();
   for e in hdoc.xpathEval(‘//a’):
       href = e.prop(“href”)
       if not href: continue
       if href.find(“/”)==0:
           node = libxml2.newText(e.content)
           e.replaceNode(node)
       elif href.find(“#cite”)==0:
           e.unlinkNode()

   #$(‘span[class=editsection]’).remove();
   for e in hdoc.xpathEval(‘//span[@class=”editsection”]’): e.unlinkNode()

   #$(‘table[class^=navbox ]’).remove();
   for e in hdoc.xpathEval(‘//table’):
       cl = e.prop(“class”)
       if not cl: continue
       if cl.split(” “).count(“navbox”)>0:
           e.unlinkNode()

   #$(‘div[class=주석]’).remove();
   for e in hdoc.xpathEval(‘//div[@class=”주석”]’): e.unlinkNode()

   #$(‘table[id=toc]’).remove();
   for e in hdoc.xpathEval(‘//table[@id=”toc”]’): e.unlinkNode()

   #$(‘h2 > span’).each(function(i) { if ($(this).text() == “주석”) $(this).remove(); } );
   for e in hdoc.xpathEval(‘//h2/span’):
       if e.content == “주석”:
           e.unlinkNode()
[/code]

libxml2 python binding의 문제인지 모르겠지만, htmlParseDoc()을 사용하면 xpath가 동작하지 않고, htmlParseFile을 사용하면 html 파싱 관련 경고가 출력되는데 출력안되게 할 방법이 없는듯하네요.

위 소스는 위키피디아에서 글을 읽어서 필요없는 부분을 제거하는 소스이고, 이후로 여러가지 요구사항들이 생겨서 많이 확장됐습니다.