저희팀(TmaxSoft, Compiler팀)은 컴파일러를 개발하고 있습니다. 컴파일러를 개발하다보면 코드의 수정 혹은 추가로 인해 기존에 잘 되던 것이 잘 안되는 문제가 빈번히 발생합니다. 언어를 처리하는 프로그램의 특성상 상호의존적인 코드의 비중이 높기 때문이죠.

그런 까닭에 "실용주의 프로그래머"에서도 강조하는 회귀 테스트가 정합성을 생명으로하는 컴파일러의 개발과정에서 빼놓을 수 없는 영역을 차지하게 됩니다. 

저희팀에서 컴파일러 혹은 인터프리터의 개발과정에서 사용하는, Ruby로 작성된 회귀 테스트 장치(regression test harness) 코드는 다음과 같습니다. (Ruby의 맛만 살짝 본 상태에서 제가 작성한 조악한 코드지만, '이런식으로 회귀 테스트를 하기도 하는구나!' 정도로 이해해주시면 좋겠네요.)

컴파일러나 인터프리터가 제대로 동작하는지 확인하는 가장 간단한(?) 방법은 소스코드를 사용하여 예상대로 동작하는지 확인하는 것 입니다. 일반적인 경우에는 standard output(이하 stdout) 결과를 보고 이상유무를 파악합니다. 기본적인 아이디어는 여기서 정리하고 본론으로 들어가자면...

여기서 소개한 회귀 테스트를 위해서는 2가지 작업이 선행되어야 합니다.

1. 회귀 테스트에 포함시킬 예제 파일의 이름(확장자 제외)을 list.txt에 추가 (newline으로 여러개의 파일구분)
2. 정상 동작할때 stdout을 filename.out 파일에 저장 (e.g. ezp -i filename.ezt > filename.out)

회귀 테스트 과정은 다음과 같습니다.

1. list.txt에서 테스트 할 파일 이름을 추출하여 nameArray에 저장, 이 때 존재하는 파일인지 확인
2. ezp 인터프리터 실행하여 stdout을 filename.tmp에 저장
3. diff로 정상 동작시 결과 filename.out과 현재 실행 결과 filename.tmp를 비교
4. diff의 stdout이 비어 있으면 테스트 성공! 비어있지 않으면 failArray에 추가
5. 회귀테스트 결과 출력

저희팀에서는 (당연한 이야기겠지만) 저장소에 commit하기 전에 회귀 테스트를 통과하는 것을 정책적으로 강제하고 있습니다.
Code::Blocks는 윈도우, 리눅스, 맥 환경을 모두 지원하는 오픈소스 C/C++ 개발 환경입니다.

http://www.codeblocks.org/

리눅스나 유닉스를 기반으로 하는 맥의 경우 C 프로그래밍 환경을 쉽게 갖출 수 있지만, 윈도우의 경우 로컬 시스템에 C 프로그래밍 환경을 마련하기가 애매한 것 같습니다. 윈도우를 위한 gcc환경인 MinGW를 직접 설치해야 하죠.

윈도우 환경에 Code::Blocks를 설치하는 경우 codeblocks-8.02mingw-setup.exe 파일을 다운받아 실행하시면 MinGW가 함께 설치되고 Code::Blocks의 기본 컴파일러로 등록이 됩니다. 별도의 설정없이 바로 프로젝트를 생성하고 빌드하고 실행할 수 있는 환경을 마련할 수 있습니다.

IDE 자체도 훌륭합니다. function outline, folding, debug, syntax highlighting 등등 IDE가 갖추어야 할 기본적인 기능은 모두 포함하고 있습니다. 윈도우에 C 프로그래밍 환경을 마련하고자하는 분들에게 Code::Blocks를 추천하고 싶네요.
iTunes로 음악을 정리해 듣다 보면 앨범 사진까지 깔끔하게 입혀 놓고 싶은 욕심이 들때가 많다. 작은 이미지를 구하는 것은 그리 어렵지 않지만, iTunes의 Cover Flow를 사용해도 볼만할 정도의 큰 이미지를 구하기는 녹녹치 않았다.

지금까지 사용하던 방법은 에반레코드(http://www.evan.co.kr/)에서 해당 앨범을 찾은 후, 플래쉬 화면을 캡춰하여 앨범 사진으로 사용했는데 정확히 자르기도 어려울 뿐더러 여간 불편한게 아니였다.

오늘 우연히 에반레코드의 데이터베이스를 이용해 앨범 사진을 쉽게 얻을 수 있는 사이트를 발견했다.

커버.즐즐넷
http://cover.zzlzzl.net/

이 곳에서는 손쉽게 정말 커다란 앨범 사진을 얻을 수 있다. 특히나 웬만한 클래식 앨범을 모두 찾을 수 있다는 점이 매력적이다. iTunes의 경우 사이트에서 찾은 이미지를 drag and drop으로 음악파일에 입력할 수 있어 매우 편리하다.

추가로 추천하고 싶은 사이트는,

maniadb
http://www.maniadb.com/

커버홀릭
http://www.coverholic.com/


고해상도 앨범 사진으로 음악파일을 정리한 덕분에 음악을 듣는 즐거움에 보는 즐거움이 더해졌다. ^^

맥북을 사서 즐겁게 사용하다 팔아치운지 벌써 1년이 넘었다. 메인 PC로 사용하기에는 국내 웹환경이 옳지 않아서 아쉬움을 뒤로 하고 맥라이프를 접었었는데, 요즘에는 다시 맥을 사용하고 싶은 마음이 굴뚝같아서 전전긍긍하며 지내고 있다. 레오파드도 한번 써보고 싶고, 아이폰 SDK로 어플리케이션 개발도 해보고 싶고...

그래도 가능하면 돈을 굳혀 보려고, 
우분투를 설치해 리눅스에 정을 붙여 보려고 애를 써보기도 하고...
회사에 남는 PC에 해킨토시를 설치해 보기도 하고...
나름 애를 써보았으나 맥에 대한 욕망을 접기가 녹녹치 않았다.

그리하여 싸게 맥을 구할 수 있는 방법을 고민해 보았다. 괜찮아 보이는 중고 맥미니를 사려 했는데, 연락해보니 이미 팔렸고, 새제품을 사자니 성능에 비해 비싸기도 하고, 기왕이면 아이맥으로 가자 싶기도 하고...

이래저래 찾아 다니다 애플 사이트에서 리퍼 제품을 저렴하게 구입할 수 있다는 것을 알게 되었다. 12시에서 2시 사이에 갑자기 떴다가 사라진다는...

오늘 점심 먹고 돌아와 티베로데이 관련 기사를 읽다가 심심해서 링크를 열어보니 리퍼제품이 떠있었다!
http://store.apple.com/kr/browse/home/specialdeals/mac?mco=MTE3NjY


부랴부랴 아이맥 20인치 제품을 장바구니에 넣고 결제를 시도했다! 그러나 현대카드 안심클릭 사이트에 접속이 잘 안되서 살짝 버벅거리는 사이에 물건은 안드로메다로... 오호 통제라...

절호의 기회를 놓치다니... 앞으로 매일 점심시간마다 긴장해야 하나...
집에서 회사일 및 알고리즘, 프로그래밍 공부를 해볼 요량으로 오랜만에 리눅스를 설치해 보았다. iptime 무선 랜카드 G054U-A를 사용하는 환경이라 이를 리눅스에서 동작하게 하기 위해서는 엄청난 삽질이 뒤따를 것을 감안하고 Ubuntu 8.10을 설치했는데, 놀랍게도 아무런 설정없이 바로 무선랜 카드를 사용할 수 있었다!

더욱 놀라운 것은 파티셔닝을 하지 않고 윈도우 파티션 내부에 가상 파일시스템을 구축하여 우분투를 설치할 수 있게 되었다는 것! 단 이때는 파일 시스템의 성능이 다소 저하될 수 있으며 Hibernation 기능을 사용할 수 없다. 그러나 이와 같은 방식으로 설치하고 사용해본 결과 눈에 띌만한 성능의 저하는 느낄 수 없었다. 간단히 윈도우에서 uninstaller를 실행하는 것으로 깔끔히 리눅스를 제거할 수 있다는 점도 상당히 매력적이다.


Ubuntu studio 테마를 설치하고, 네이버에서 받은 나눔고딕을 사용하도록 설정하니 윈도우보다 더 보기좋은 UI가 완성되었다! 회사 컴퓨터에도 설치해볼 계획인데, 부디 듀얼모니터 설정도 별다른 삽질 없이 마법처럼 되었으면...
필자는 국민학생이던 아주 어린시절부터 컴퓨터를 다루어오면서, 컴퓨터 및 주변기기에 대한 관심이 많은 편이였다. 게임을 하기위한 조이스틱에서부터 스캐너, 프린터, Zip 디스크 등등. 그 중에서도 프린터는 단연 나의 소유욕을 불러 일으키는 매력적인 물건이였음에도 불구하고, 부모님은 그다지 필요가 없다(?)는 이유로 사주시지 않았었는데...

바야흐로 시간은 흘러 우리가 접하는 수 많은 정보가 컴퓨터로 전달되는 문화속에 살고 있는 우리에게 프린터는 없어서는 안될 물건이 되었다. 더군다나 아직도 모니터 보다 종이로 글을 읽는게 훨씬 편안한 촌스러운 나에게는 더더욱... 
이번 cp1215 이벤트 덕분에 난생 처음으로 나만의 첫 프린터를 가질 수 있게 되었다. 그 것도 컬러레이저젯 프린터! 지금부터 컬러레이저젯 프린터 cp1215의 외형, 소프트웨어, 출력 속도, 사진 인쇄 품질, 아쉬운 점 등을 차례로 살펴 보도록 하자. 

1. 외형 및 소프트웨어

워낙 cp1215가 컬러레이저젯 프린터 치고는 작은 크기를 자랑한다고 하여, 굉장히 작을 것으로 생각했으나 아쉽게도 설치 기사분이 설치할 때, 첫인상을 보니 생각보다는 제품이 컸다. ^^; 앞뒤로 길이는 회사에서 사용하는 HP 레이저젯 프린터와 비슷한 것 같았다. 대략 데스크탑의 길이 정도?

cp1215의 다지인은 개인적으로 참 마음에 든다. 간결한 디자인은 자주 보아도 질리지 않는다. 사용자 인터페이스도 매우 단순해 토너를 교환할 때, 종이가 걸렸을 때, 종이를 넣을 때 프린터를 여는 것이 전혀 부담스럽지 않았다. 한번은 프린터 위에 가방을 올려놓고 인쇄버튼을 눌러 종이가 걸린 적이 있었는데, 뒷 뚜껑을 열어 손쉽게 문제를 해결할 수 있었다.

컬러를 위한 3개의 토너와 흑백을 위한 하나의 토너가 각 색깔별로 분리되어 장착되어 있다. 각 토너의 가격은 색상마다 다른데 인터넷 최저가로 현재(2008년 10월) 4만원에서 6만원 정도 사이에서 구매할 수 있다. 각 토너당 대략 700장 + alpha 정도의 인쇄가 가능하다고 소프웨어는 안내해 준다.


펌웨어를 두번 업데이트 했음에도 불구하고 특정 카트리지의 잔량을 제대로 체크하지 못하는 점은 제품의 완성도 측면에서 상당히 아쉬움을 남겼다. 사용하는데 크게 문제가 되는 부분은 아니지만 이번 컬러체험단 이벤트를 통해 차후 양산되는 모델들은 이런 문제가 없기를 바란다.

HP가 제공하는 소프트웨어를 살펴보자. 먼저 HP Toolbox는 도움말과 장치의 상태를 상세히 제공하며, Toolbox에서는 전문가 만이 건드릴 법한 장치의 세부 설정이 가능하다. 소프트웨어의 UI는 그저 평이한 수준. 조금 더 신경썼으면 좋았을 것 같다.

이번에는 프린터 인쇄속성 창을 살펴보자. 그동안 HP 프린터를 사용해본 사람이라면 매우 익숙한 화면을 볼 수 있다. 이 리뷰를 작성하다가 처음 발견한 사실은 수동 양면 인쇄가 가능하다는 것!



2. 인쇄속도

장치를 켜둔 상태에서 흑백/컬러 인쇄 작업을 프린터에 보낸 경우 몇 초가 걸리는지 실험해 보았다. 익스플로러 8.0에서 네이버 첫화면을 한번은 흑백으로 한번은 컬러로 출력하면서 출력 시간을 비교해 보았다.



<흑백>
인쇄버튼을 누른 후 종이가 나오기 시작한 시간 : 22초 10
끝까지 인쇄가 완료된 시간 : 25초 98

<컬러>
인쇄버튼을 누른 후 종이가 나오기 시작한 시간 : 25초 81
끝까지 인쇄가 완료된 시간 : 32초 02

흑백을 먼저 인쇄하고 몇 분 후에 컬러를 인쇄했는데 약간 예열의 효과가 있을 지도 모르겠다. 개인적으로 첫 페이지를 출력하기까지의 소요시간은 이정도면 무난하다고 생각한다. 한달 넘게 제품을 사용했지만 아직까지 출력 시간때문에 답답함을 느껴본 적은 없는 것 같다.

3. 사진 출력

일반적인 용도의 인쇄 결과물은 더할나위 없이 훌륭했다. 일하다가 마주치는 pdf 문서나 스프링노트에 정리한 것, 때로는 피아노 악보를 인쇄해 보았을때 그 선명함은 완벽했다. 더 이상의 기술력이 필요 없다는 생각이 들정도로...

그래서 이 리뷰에서는 컬러레이저젯 프린터를 가졌다면 누구나 한번쯤 시도해 보고 싶어 할 것 같은, "사진 출력"을 주제로 잡아 보았다. 여행 중에서 찍은 특징적인 3장의 사진을 뽑아 모니터로 보이는 실제 사진과 인쇄 결과물을 비교하는 방식으로 리뷰를 진행하였다.

사용한 용지는 흔히 구할 수 있는, 일반적인 용도로 사용되는 Double A 80gsm. 이다. 일반 A4 용지에 컬러레이저젯 프린터로 어느정도 수준의 사진 인쇄물을 얻을 수 있는지 알아보도록 하자.

첫번째 사진의 주제는 '음식'이다. 음식 고유의 빛깔과 질감을 제대로 표현해 주는지 확인해 보고 싶었다.


김치에 묻어 있는 고추가루의 디테일 까지는 완벽하게 표현 하지 못했으나 대체로 무난하게 음식이 주는 느낌을 그대로 인쇄물에서 얻을 수 있었다. 다만 한가지 아쉬운 것은 색감이 모니터로 보는 것 보다 다소 어둡다는 것.

두번째 사진은 채도가 극명하게 대비되는 사물들이 많은 사진이다. 채도가 높은 사물들을 출력해 보았을 때 어떤 결과물을 얻을 수 있을까 궁금하여 이 사진을 선택하게 되었다. 파리에 어느 잡화점에서 찍은 사진!


이 사진을 프린트 할때 회사 동료가 옆에서 지나갔는데, 결과물을 보고 감탄을 자아냈다! 빠른 시간에 이 정도의 훌륭한 결과물을 얻을 수 있다는 것에 놀랐던 것이다. 오밀조밀한 사물들을 선명하게 표현하고 있어 결과물은 대체로 만족감을 준다. 그러나 역시나 색감은 모니터로 보는 것과 다소 차이가 있었다. 앞의 사진과 마찬가지로 다소 진하게 표현되는 경우가 많았다. 그리고 사진의 어두운 영역은 더 어두워 지면서 디테일을 다소 잃어버리는 느낌을 주었다.

마지막으로 풍경사진을 살펴보자.


전체적으로 멀리서 보면 역시나 색감의 차이가 있을뿐 무난한 결과물을 얻을 수 있다. 그러나 DSLR로 찍은 풍경사진의 묘미는 선예도에 있는데, 컬러레이저젯 프린터로 그 선예도 까지 표현해 내길 기대한다는 것은 다소 무리가 있는 것 같다. 디테일을 살펴보자.


나무와 논의 경계 부분이 사진과 확연히 차이를 확인할 수 있을 정도로 조악하게 표현되었으며, 나뭇잎 부분은 워낙 세밀한 부분이라 그런지 약간 어색한 느낌을 주었다.

색감이나 디테일 면에서 약간 아쉬움을 남겼으나 예전에 컬러 잉크젯 프린터를 사용해본 경험을 비추어 보면 상당히 만족스러운 결과물을 안겨주었다. 색감 문제는 모니터 설정의 문제일 수도 있을 것 같고, 사진 전용지를 사용하게 되면 색감이나 디테일 면에서 훨씬 좋은 결과물을 얻을 수 있을 것이다. 컬러레이저젯 프린터의 고질적인 색감문제는 차차 보완되어 언젠가는 보급형 컬러레이저젯 제품에서도 원본과 동일한 색감의 결과물을 얻을 수 있기를 기대한다.

4. 아쉬운 점

컬러 + 흑백 토너 한 세트의 가격이 프린터의 가격과 맞먹는다. 재생 토너의 유혹을 느끼지 않을 수 가 없는데... 업무용으로 사용하기에는 경제성이 다소 떨어지는 것 같다. IT 업계에서 일하는 필자는 20페이지를 훌쩍 넘는 문서를 종종 인쇄하곤 하는데  4~5만원 하는 하나의 흑백 토너로 700여장 밖에 찍을 수 없다는 것은 많이 아쉬움을 남긴다.  

인쇄를 마치고 몇분 후에 소음을 발생시킬때가 있다. 트레이 아이콘에 마우스를 가져가보면 보정 중이라는 메세지가 뜨는데, 보정 작업이 끝난 후에도 1, 2분 더 소음이 발생한다. 사무용이라면 크게 문제 될 것은 없겠지만 컴퓨터 작업을 끝낸 후에도 가끔 프린터가 소음을 내는 것은 가정용으로는 조금 아쉬운 부분이다.

5. 총평

만약 필자가 필요해 의해 컬러레이저젯 프린터를 구매해야 하는 상황이였다면 아마도 cp1215를 심각하게 고려해 보았을 정도로, 디자인, 가격, 스펙, 성능 모두 훌륭한 제품이라고 생각한다. 프린터 제품에서 HP의 인지도와 명성은 충분히 신뢰를 주고 있으며, 이번 cp1215 제품 리뷰로 인해 그 신뢰가 더욱 굳건해 진 것 같다. 

문서 인쇄, 웹 페이지 인쇄 등등 업무나 생활에서 자주 활용되는 용도로서 cp1215는 최적의 선택이라 생각한다. 더이상 바랄 것이 없을 정도로 선명한 결과물을 빠른 시간에 얻을 수 있으니... 다만 사진 출력시에 색감 문제는 다소 아쉬움을 주었는데, 가까운 내일에는 보급형 컬러레이저젯 제품으로도 사진의 그대로 색감을 표현할 수 있었으면 하는 바램을 가져본다.

사용자 삽입 이미지

회사에서 삼성컴퓨터를 새로 지급받았는데, 정품 비스타 DVD가 있길래, XP를 밀어 버리고 비스타를 설치해서 사용하고 있다. 리눅스 배포판만 수십가지 종류를 설치해서 사용해 보았고, OS/2 Warp까지 도전해 봤을만큼 OS에 대한 호기심이 큰 편이라 비스타 DVD를 그냥 지나칠 수 없었다.

프로세서: Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz
메모리(RAM): 4.00GB

비스타를 쓰기에 전혀 무리가 없는 환경이라 xp보다 느리다는 느낌은 전혀 못 받고 있고, 개인적으로 깔끔한 GUI에 만족하면서 사용하고 있다. 차기 OS임에도 불구하고 막상 사용해보니 별로 달라진 것이 없어서 당황스럽기도 하지만... 

Active X를 설치할 때 마다 깜빡이는 화면을 보면서, 부디 우리나라 웹환경에서 하루 빨리 Active X가 사라지길 간절히 바라는 마음을 가지게 된다. Active X가 완전히 사라진다면 다시 맥으로 돌아갈 수 있을텐데...
이클립스는 JDT라는 자바개발환경을 포함하고 있습니다. 그리고 JDT는 자바개발과 관련하여 다양한 기능을 제공(e.g. Code Formatting)하기 위해 자바파서와 AST를 내장하고 있습니다. 따라서 이 부분을 잘 뜯어서 사용하면 훌륭한(!) 자바 파서를 공짜로 얻는 셈이 되는 것이죠.

앞으로 몇부에 걸쳐 JDT에 내장된 자바파서와 AST를 활용할 수 있는 방법을 설명하려고 합니다. 1부에서는 AST의 구조를 파악하는데 도움이 되는 ASTExplorer를 실행해보도록 하겠습니다. 이 과정에서 개발환경을 설정(e.g. 클래스패스 설정)하는 방법도 함께 다루겠습니다. 질문은 덧글로 남겨주세요.

올초에 빠른 시간안에 자바 코드 읽어 다른 형태의 코드로 변환하는 프로그램을 개발해야 했는데, 여러가지 방법을 찾아 고민하던 중에, JDT에 내장된 자바파서를 활용방안을 다룬 다음 웹문서를 발견하게 되었습니다.

Exploring Eclipse's ASTParser


이 문서에서 ASTExplorer라는 예제 프로그램을 다운 받을 수 있는데, 이클립스 v3.02를 기준으로 하고 있어 다른 버전의 이클립스에 이 프로젝트를 import 하는 경우, 클래스패스에 추가된 JDT 라이브러리의 경로와 이름이 달라 에러가 발생합니다.

이 문제를 해결하는 가장 쉬운 방법은 클래스패스에 등록된 라이브러리를 지우고, eclipse\plugins에 존재하는 라이브러리를 클래스 패스에 추가하는 것입니다만 불필요한 라이브러리가 많이 추가되겠죠?

제가 사용하는 User Library를 첨부합니다. (이클립스 v3.3.1.1 기준) User Libraries에서 Import 하시면 됩니다.


첨부한 User Library를 클래스패스에 추가하셔도 JDT 버전이 올라가면서 변경된 부분 때문에 컴파일 에러가 발생할 것 입니다.

ASTMain.java의 다음 2라인의 코드를

return new NameEnvironmentAnswer(unit);
return new NameEnvironmentAnswer(classFileReader);

다음과 같이 수정해 주시면 컴파일 에러가 해결됩니다.

return new NameEnvironmentAnswer(unit, null);
return new NameEnvironmentAnswer(classFileReader, null);

ASTMain.java와 ASTExplorer.java 모두 main 메서드를 가지고 있습니다. ASTMain.java의 코드를 읽어보면 AST를 생성하는 작업을 정의하고 있는데, JDT 버전이 달라서 그런지 Exception이 발생하며 제대로 실행되지 않습니다.

ASTExplorer.java의 경우 실행에 문제가 없습니다. 실행해 보시면 다음과 같은 화면을 보실 수 있습니다.

사용자 삽입 이미지

이 프로그램은 JDT 내장 자바파서가 생성하는 AST 객체의 구조를 한눈에 파악할 수 있도록 화면 왼쪽에 AST의 구조를, 화면 오른쪽에 소스코드를 보여줍니다. AST에 익숙하지 않은 경우에 큰 도움을 주는 프로그램이죠.

AST에 대한 API Reference는 이클립스의 Help Contents에서 찾아 볼 수 있습니다. 웹에서 확인하고 싶으신 경우 다음 URL을 참조하세요.

http://help.eclipse.org/help33/index.jsp?topic=/org.eclipse.jdt.doc.isv/reference/api/org/eclipse/jdt/core/dom/package-summary.html

1부에서는 간단히(?) JDT에 포함된 파서와 AST를 활용한 ASTExplorer를 실행해 보았습니다. 2부에서는 자바소스코드를 읽어 AST를 얻는 방법에 대하여 설명하겠습니다. (물론 ASTExplorer 소스코드를 읽어보시면 쉽게 이해하실 수 있겠습니다만... ^^;)

팀원 4명이 함께 진행하던 프로젝트를 몇 일전부터 혼자 담당하게 되었다. 업무의 인수인계 후에 살펴보니 코드리뷰 한번 없이 각자 개발한 코드는 동일한 기능이 비효율적으로 중복되어 있는 구조를 가지고 있었다. 그리고 언어를 다루는 프로그램의 특성상 언어의 의미(Semantic)은 엄밀히 지키면서 동작해야 하는데 그렇지 않았다. 내가 작성했던 코드 역시 마찬가지...

적절히 책임감이 분산되었던 함께하는 코딩과 혼자 모든 책임을 짊어지고 하는 코딩은 다르지 않아야 하는데 달랐던 것 같다. 마치 범죄 현장을 목격하고 아무도 신고 하려하지 않았던 다수의 대중들처럼...

실장님은 거의 완성된 것으로 보고 계시지만, 실제로는 그렇지 않은 상황에서 적절한 타협점을 찾기 위해 나에게 약간(?)은 버겁지만 실장님도 받아들일만한 프로젝트 예상일정을 보고했고 그로 인해 조금(?)은 조바심을 느끼면서 일을 홀로 진행하고 있다.

4명이 함께 프로젝트를 진행하면서, 코드가 비효율적으로 작성되어가고 있음을, 언젠가 한번은 이러한 비효율적이고 명확하지 않은 구조 때문에 더 큰 비용이 발생할 수 있음을 예상하고 있었지만 일개 팀원으로서 어떤 조취를 취하는 것은 영 부담스러웠다.

어려움에 처하긴 했지만, 거대한 코드를 내가 원하는 모습으로 마음껏 리펙토링 하고 하나의 작품을 만들어 가듯 아름답게 꾸미는 작업을 마음껏 할 수 있다는 것이 즐겁다.

1년 정도 회사에서 소프트웨어를 개발해보니 소프트웨어를 개발의 가장 큰 어려움은 기하급수적으로 증가하는 복잡도(Complexity)를 관리하는 것이 아닐까 하는 생각이 든다. 언젠가 팀장이 되어 프로젝트를 관리하는 입장이 되기전에 많은 경험과 많은 생각으로 충분한 역량을 쌓아 두어야겠다는 생각이 든다. 때문에 이번 프로젝트는 나에게 도전이자 기회다.

사용자 삽입 이미지

작업환경을 완전히 리눅스로 옮겼다. 윈도우 컴퓨터에서 Putty로 셀레론 컴퓨터에 접속해서 GCC를 컴파일 하며 작업하다 듀얼 코어 컴퓨터에 리눅스를 설치하고 직접 컴파일 하니 속도가 2배 가까이 향상 된 듯한 느낌을 준다. 게다가 우분투 7.10은 설정하고 사용하기가 정말 편리하다.

빨간색을 좋아하다 보니 입맛에 맞게 글꼴과 테마를 수정했다. 그럭저럭 마음에 드는 개발 환경을 마련하는데 성공! 출근해서 저녁먹을때까지는 리눅스 환경에서 업무에 집중하자!
펄, 파이선, 루비 등의 스크립트 언어 중에 하나 정도는 알아 두는게 편할 것 같다는 생각에 이번 달에는 루비를 공부하고 있다. 책의 절반을 쭉 읽어 나가면서 코드는 한번도 작성한 적이 없었지만 언어가 간결해서 그런지 몰라도 쉽게 원하는 코드를 작성할 수 있었다.

지금 진행하고 있는 프로젝트는 코볼 컴파일러의 개발인데, 컴파일러가 생성한 코드가 정확한가를 확인하는 가장 쉬운 방법은 기존의 컴파일러가 생성한 코드와 수행 결과(stdout)을 비교하는 것.

지금까지는 급한 마음에 두 실행파일을 번갈아 실행하며 눈으로 수행결과를 비교했는데, "실용주의 프로그래머"를 보면 테스트를 포함한 프로젝트 빌드의 전과정을 자동으로 수행할 수 있도록 할 것을 강조하고 있다.

그리하여 고즈넉한 저녁에 잠깐의 짬과 약간의 용기를 내어 처음으로 루비를 사용해 간단한 test harness를 작성해 보았다.

name_list = [
    'intrinsic_math_func',
    'intrinsic_char_func',
    'intrinsic_case_func',
    'intrinsic_value_func',
    'intrinsic_divide_func',
    'intrinsic_numval',
    'intrinsic_annuity'
]

test_cnt = 0
succ_cnt = 0
fail_cnt = 0

# TODO
# compare execution time
name_list.each do |name|

    test_cnt += 1

    mf_exec = "./" + name + ".cob32"
    tmax_exec = "./" + name + ".gcobol"

    mf_stdout = `#{mf_exec}`
    tmax_stdout = `#{tmax_exec}`

    print "[#{test_cnt}] #{mf_exec} vs #{tmax_exec}"
    if (mf_stdout == tmax_stdout)
        puts " ...success"
        succ_cnt += 1
    else
        puts " ...fail"
        fail_cnt += 1
        puts "[#{mf_exec}]"
        puts mf_stdout
        puts "[#{tmax_exec}]"
        puts tmax_stdout
    end
    puts
end

puts
puts "Total : #{test_cnt}"
puts "Success : #{succ_cnt}"
puts "Fail : #{fail_cnt}"
puts

컴파일러가 생성한 코드의 수행시간 역시 컴파일러를 평가하는데 중요한 이슈이므로, 두가지 컴파일러가 생성한 코드의 수행시간을 자동으로 비교해 주는 프로그램을 루비로 간단히 작성하는 것도 큰 의미가 있을 것 같다. 사용하기 쉬운 루비 언어를 조금 더 연습해서 프로젝트의 여기저기에 잘 활용한다면 생산성을 향상 시킬 수 있을 것이다.
beta4에 이어 rc1을 사용하고 있었는데 8월 6일 정식 발매 된다는 소식을 듣고 그동안 미뤄오던 pre-order($39.99)를 해버렸다. 정식 발매 이후에 구입하게 되면 $79.99를 지불해야 한다.

윈도우를 사용할 수 밖에 없는 현실이 슬프지만 어쩔 수 없는 노릇. 플랫폼에 independent한 인터넷 환경은 얼마나 시간이 지나야 갖춰질까? 당장 이 글을 쓰고 있는 테터툴 마저도 사파리에서 html 모드로 글을 쓸 수 밖에 없으니 안타까움을 금할 길이 없다.

아마도 이번 pre-order가 최초의 정품 소프트웨어 구입이 될 것 같다. $39.99 정도의 가격이면 충분히 감당할 수 있을 정도. 오히려 맥용 정품 소프트웨어가 윈도우용 소프트웨어보다 대체로 저렴한 것 같다.

다음 구입할 맥용 소프트웨어는 차기 맥OS인 레오파드! 10월이 기다려지는구나. 즐거운 컴퓨팅을 기대하며 그 날을 기다린다.
지금 진행중인 프로젝트는 gcc의 back-end를 사용하기 때문에 빌드할 때 gcc 소스코드와 함께 컴파일 된다.

컴파일 할 때 make를 수행하면 늘 cygwin에서 컴파일하는 동희형과 달리 mac osx에서 하는 나는 늘 한번에 컴파일이 안되고 에러가 발생하곤 했다. 한번 더 수행하면 에러 없이 make가 완료되었다.

난 쉽게 생각했다.

"뭔가 깔끔하진 않아도 한번 더 수행하면 되니까 괜찮겠지"
"플랫폼이 달라서 그렇겠지"

철주형 아들 서호의 돌잔치에 다녀와서 사택에서 낮잠 한시간 푹 잔후 다시 회사에 나와 본격적인 테스트를 하려고 하는데 그 동안 무시했던 이 에러가 나를 괴롭히고 있는 원인이였음을 깨닫게 되고는 또 무릎을 치게 되었다.

오호 통제라!

나는 또 한번 경험에서 교훈을 얻게 되었다. 오직 0과 1로 데이터를 표현하는 정교한 컴퓨터를 다루는 입장에서 애매한 태도를 지양해야 한다는 것을. 남겨둔 애매함이 언젠가 나를 곤란하게 한다는 것을. 개발자에게 경험은 그 무엇보다 소중한 자산인 것 같다. 경험이 농익을 때까지 맨땅에 해딩을 마다하지 말자.

하지만 연애에서의 애매함은 피할 수 없는 숙명인 것 같다. 확실한 것을 좋아하는 어쩔 수 없는 공돌이인 내가 늘 작업에 실패하는 이유는 애매함을 견디지 못하는 나약한 혹은 소심한(?) 심리상태에 있는 것 같다. 남녀사이의 애매함을 즐기는 작업의 대가들이 부러울 따름이다.
gmp (gnu multiprecision) 라이브러리를 쓸 일이 있어서 메뉴얼과 헤더파일을 보던 중 재밌는 코드를 발견!

typedef struct
{
  int _mp_alloc;        /* Number of *limbs* allocated and pointed
                   to by the _mp_d field.  */
  int _mp_size;         /* abs(_mp_size) is the number of limbs the
                   last field points to.  If _mp_size is
                   negative this is a negative number.  */
  mp_limb_t *_mp_d;     /* Pointer to the limbs.  */
} __mpz_struct;

typedef __mpz_struct mpz_t[1];

이 부분에 대해서 메뉴얼은 다음과 같이 설명하고 있다.

For interest, the GMP types mpz_t etc are implemented as one-element arrays of certain structures. This is why declaring a variable creates an object with the fields GMP needs, but then using it as a parameter passes a pointer to the object. Note that the actual fields in each mpz_t etc are for internal use only and should not be accessed directly by code that expects to be compatible with future GMP releases.

이 정의를 활용하는 코드를 보면 다음과 같다.

     void
     foo (mpz_t result, const mpz_t param, unsigned long n)
     {
       unsigned long  i;
       mpz_mul_ui (result, param, n);
       for (i = 1; i < n; i++)
         mpz_add_ui (result, result, i*7);
     }
    
     int
     main (void)
     {
       mpz_t  r, n;
       mpz_init (r);
       mpz_init_set_str (n, "123456", 0);
       foo (r, n, 20L);
       gmp_printf ("%Zd\n", r);
       return 0;
     }

이렇게 선언해 놓고 참조하면 자연스럽게 함수 호출할 때 call-by-reference가 가능하다. c언어의 묘미란 이런게 아닐까?


맥으로의 스위칭으로 인해 갖게 되는 여러가지 장점중에 나에게 가장 유용한 것은 Virtue Desktop을 사용해 다수의 데스크탑 활용하는 것이다.  

13.3인치 맥북에 22인치 와이드 LCD모니터를 함께 사용하고 있다. 물리적으로 2개의 데스크탑을 갖춘 셈이다. 여기에 Virtue Desktop을 활용하면 몇 배수의 데스크 탑을 활용할 수 있다. 갯수는 계속해서 늘릴 수 있지만 화면 전환의 편이성을 고려하여 논리적으로 3개의 데스크 탑을 할당해서 사용하고 있다.

확장 모니터까지 합하면 총 6개의 데스크탑을 사용하는 셈인데 아침에 출근해서 세팅할때 각각의 데스크 탑에 필요한 유틸을 모두 펼쳐놓고 하루를 시작한다. 이후에 데스크탑 내의 어플리케이션의 레이아웃은 건드릴 필요가 없다. 사용하고자 하는 어플리케이션을 Dock에서 클릭하면 자동으로 해당 데스크탑으로 넘어가며 특정 어플리케이션을 특정 데스크탑에 할당해 두었기 때문에 최초에 어플리케이션을 수행할 때도 자동으로 지정된 데스크탑으로 이동한다.

총 3개의 데스크탑은 나름 각각의 테마가 있다.

첫번째 데스크탑 : 일
두번째 데스크탑 : 계획, 기록
세번째 데스크탑 : 놀이

사용자 삽입 이미지

첫번째 데스크탑의 맥북 모니터 - Neo Office

사용자 삽입 이미지

첫번째 데스크탑의 확장 모니터 - Terminal

사용자 삽입 이미지

두번째 데스크탑의 맥북 모니터 - Jourlner

사용자 삽입 이미지

두번째 데스크탑의 확장 모니터 - iCal

사용자 삽입 이미지

세번째 데스크탑의 맥북 모니터 - Firefox

사용자 삽입 이미지

세번째 데스크탑의 확장 모니터 - Itunes, Mail, iChat, MSN Messenger


차기 mac osx인 레오파드에서는 이러한 기능을 기본 탑재(스페이스)하고 있다고 한다. 맥에 발을 들여 놓은지 얼마되지 않았는데도 차기 운영체제를 기다리고 있다니 단단히 빠졌나보다. 이렇게 좋은 것을 왜 진작 몰랐을까?

사용자 삽입 이미지

vmware fusion을 사용해 윈도우의 Excel 2007과 맥의 터미널을 함께 띄워 작업하는 모습
(Dock에 정박해 있는 Internet Explorer, 네이트온, Excel 2007)
사용자 삽입 이미지

맥북이 도착한 후 맥을 사용한 것이 오늘로 3일째다. 처음 맥북을 받았을 때의 첫 인상은 이쁘다! 그리고 보기보다 무겁다! 오후 1시쯤 맥북을 받아서 하루 종일 일 안하고 세팅한다고 시간을 보냈다. 듣던데로 흐릿흐릿한 한글폰트에 좌절하기도 하였으나 쓰면 쓸 수록 매력이 느껴지는 운영체제의 인터페이스와 어플리케이션에 대만족하고 있다. 대충 구조를 파악한 지금에 와서 판단해 보면 윈도우보다 훨씬 간결하고 쓰기 편하다. (우리나라 웹환경을 빼고)

가장 큰 매력은 유닉스를 기반으로 하기 때문에 터미널이 있다는 것! Xcode를 설치해서 GNU 개발도구를 모두 갖췄고 Fink를 이용해서 기타 필요한 라이브러리나 도구들을 debian package를 사용해 쉽게 설치할 수 있었다.  (현재 gcc 4.1.2가 완벽하게 컴파일 된다!) 회사에서 하는 모든 작업을 이제 맥북에서 하고 있다. 22인치 모니터를 연결해서 흑백 사진을 배경으로 걸어 놓고 배경을 약간 투명하게 한 터미널을 3개 나란히 띄워놓고 작업하고 있다. 15분 마다 배경화면이 변경되게 해놓아 심심하지 않다.

맥은 멀티미디어에 강하다! 윈도우에서 무척이나 버벅이던 iTunes가 winamp처럼 가볍게 돌아간다. 맥북에 들어 있는 리모콘으로 언제든지 iTunes를 제어 가능하다.  iTunes를 Party Shuffle 모드에 두고 코딩을 하다가 음악이 마음에 안들면 iTunes 창을 열 필요 없이 리모컨 버튼을 눌러 다음 곡으로 넘기고 코딩을 이어 나간다. 일하다 쉴때는 의자에 기대어 앉아 프론트로를 실행하여 리모콘으로 음악을 바꿔 듣거나 사진을 감상한다.

맥의 사용자 인터페이스는 이쁘기도 하거니와 편리하다. 벌써 맥의 단축키에 익숙해졌으며 대시보드를 부르는데 인색하지 않다.  그리고 기본 어플리케이션이 훌륭하다. 특히 iLife에 포함된 모든 어플리케이션은 정말 쓸만하다.  개인적으로 설치해서 사용하는 어플 중에 가장 유용한 것은 저널러! 이것 저것 많은 것을 기록하고 있는데 이 처럼 맥에도 쓸만한 어플리케이션이 상당히 많다. 윈도우 어플리케이션에 비해 복잡하지 않고 인터페이스가 직관적이라 배우기도 쉽다.

그러나 치명적인 단점이 있으니 국내환경에서의 웹브라우징이다. 맥의 한글 폰트는 정말 흐릿흐릿해서 웹서핑할 때 눈이 아플정도다. 한글 폰트 뿐만 아니라 전체적으로 동일한 해상도에서 바라보면 윈도우의 프로그램이 훨씬 선명하다는 느낌을 준다.  굴림체의 선명함이 너무나 아쉽다. 게다가 active  x를 사용하는  사이트를 이용할 수 없다는 것도 상당한 단점!

그럼에도 불구하고 맥을 메인으로 쓸 수 있는 것은 vmware fusion이라는 훌륭한 버추어 머신 어플리케이션이 있기 때문이다.  (심지어 원격데스크탑 어플리케이션도 있다!)  1기가 메모리의 맥북에서 무리 없이 동작한다. 파일 공유 기능이 있어서 맥의 특정 디렉토리를 윈도우에서 네트워크  드라이브로 공유해 사용가능하다. 맥 안의 윈도우에 Gample을 띄워 영화를 다운 받고 이 것을 복사 없이 바로 맥에서 VLC로 보고 있다. 더욱 놀라운 것은 unity 기능이다. 윈도우 어플리케이션을 맥 어플리케이션 처럼 창으로 띄울 수 있다.  (말로 설명하긴 힘드니 동영상을 감상하시길)



앞으로 새로운 데스크탑을 구매하더라도 나는 맥을 구입하고 싶을 정도로 맥의 매력에 푹 빠졌다. 국내의 기형적인 웹환경만 아니라면 컴퓨터를 처음 배우는 사람에게 맥을 추천하고 싶지만 우리나라에서는 쉽지 않은 것이 현실.  vmware fusion의 unity기능 덕분에 완전히 맥과 윈도우를 동시에 사용할 수 있는 것이 가능해진 지금 맥으로의 스위칭은 완벽하다. 내일 집으로 가는 길고 긴 5시간의 여정을 맥북 그리고 영화와 함께 해야겠다.
맥북은 다음주 도착 예정인데 벌써부터 맥용 프로그램을 다운받고 있다. 맥북이 도착하면 당장 설치해야할 gcc, vim, subversion 등의 링크도 미리 메모해 두었다. 맥용 스타크래프트를 다운받는 것은 기본! 그만큼 맥에 대한 기대로 가득한 요즘이다.

미리 준비해야할 필수 물품 중에 하나가 케이스 혹은 가방인데 노트북 가방의 투박함을 이미 많이 경험해 봤기에  가능하면 케이스를 구하려고 한다. 튼튼한 케이스가 있다면 일반 가방에 넣어다녀도 충분하기 때문이다. 보기와 다르게 미적 감각을 추구하는 편이라 저렴하면서 이쁘고 실용적인 녀석을 찾고 있는데 다음 두가지 제품으로 후보가 압축되었다.
사용자 삽입 이미지
첫번째 상품은 ava Sleevz for MacBook으로 네이버 쇼핑 최저가 15,190원이다. 맥북을 타겟으로 만든 슬리브기 때문에 사이즈가 정확히 맞으며 심플하고 깔끔하다는 장점이 있지만 충격 흡수 기능은 거의 없다고 봐도 무방할 듯 하다. 회사에서 사택까지의 거리가 도보로 10분인 것을 감안한다면 한손에 끼고 조심스럽게 돌아다니면 큰 무리는 없을 듯 한데 아무래도 불안함을 지울 수 없을 듯.
사용자 삽입 이미지

두번째 상품은 ELECOM의 제로쇼크(ZSB-IB015)로 네이버 쇼핑 최저가 18,000원이다. (첫번째 제품은 배송료가 붙는데 반해 이 제품은 배송료가 붙지 않아 둘의 가격차이는 미비하다.) 흰색인 맥북과 어울리게 흰색 파우치 제품이 있어서 마음에 드는데 문제는 12~13.3인치용으로 나온 제품이라 맥북이 빡빡하게 딱 들어맞는 다는 사실. 게다가 오래쓰면 보송보송 나온 엠보싱의 물결이 맥북에 남을수도 있다고 한다. (물론 물파스(?)로 지울 수 있다고 한다.) 중고로 팔 생각이 없고 평소에 많이 사용하는 물건의 경우 부담없이 막 사용하는 나에게는 별 큰 문제는 아닌 듯 하지만 2% 아쉬운 단점! 이 제품은 확실히 첫번째 제품보다는 충격 흡수능력이 훌륭할 것이다.

아마도 두번째 상품을 선택할 듯 한데 대체 맥북은 언제오는걸까?

몇 일의 고민끝에 결국 지르고야 말았다. 때마침 신제품이 어제밤 출시되는 바람에 '신제품을 기다릴까? 기존의 모델을 살까?' 하는 고민을 덜어 주었다. 이전모델에 비해 동일한 원가에 메모리와 하드용량 그리고 시피유 클럭이 업그레이드되어 출시되었다.
 

사용자 삽입 이미지
 
어제 민규형에게 부탁해서 잠시 맥북 프로를 가지고 놀 수 있었는데 다만 반응속도가 윈도우에 비해 다소 느린 것에 약간 실망했지만 익스포저 등 사용자에게 편리한 인터페이스에 감동 받았다. 게다가 더욱 놀라웠던 것은 터미널에서 gcc, make등의 gnu 개발 도구가 동작하고, ssh, sftp 접속에도 문제가 없었으며, 심지어 x11을 설치하면 리눅스 GUI 어플리케이션도 자연스럽게 동작했다. 심지어 요즘 내가 주로 사용하는 도구인 lex, yacc까지 설치되어 있었다. 한마디로 맥북 로컬에서 리눅스를 설치한 것 처럼 내가 하는 작업을 할 수 있다는 사실에 매료되었던 것이다.

새로운 운영체제에 대한 호기심을 충족시킬 수 있다는 것은 또 하나의 보너스. 심심하면 죽어버리는 익스플로어와 수년째 사용해온 윈도우 고전 테마도 이제 지겨울 때가 되었다. 그리고 이제 게임도 그만 둘 나이가 되지 않았는가.

애플스토어에서 동생의 도움(?)으로 교육할인을 받아 Apple Mini-DVI to VGA Adapter 컨버터를 포함하여 110만원에 구매했다. 다음주에 도착할 듯 한데 맥북이 도착하면 맥으로의 완전한 스위칭을 실행에 옮길 것이다. 회사에서 지급해준 윈도우가 깔린 고사양 컴퓨터는 맥에서의 원격데스크탑 접속용으로 전락할 것인가?

내일은 회사의 10주년 기념식이 있는 날이라 몇 일동안 계속해서 공연 연습을 했다. 입사 동기가 광고 패러디 퍼포먼스(?)의 영상을 맥북에서 키노트를 사용해서 구성했는데 처음보는 맥북과 키노트의 프리젠테이션은 나의 호기심을 자극했다. 특히나 가장 나의 시선을 끌었던 것은 바로 터미널의 존재!

그리하여 요즈음에는 지름신의 강림에 시달리고 있다. '어차피 사택에 컴퓨터가 없어서 불편하지 않은가'하는 자기 합리화 메커니즘을 가동하며. 그리고 지금까지 월급탄 이래로 나를 위해 지른 것이 없기도 하고. 게다가 아무 이유 없는 LG카드 6개월 무이자 할부 혜택까지 ...

지금까지 웬만한 OS는 다 사용해봤는데 MAC OS만 경험이 없다. 내가 가장 궁금한 것은 'MAC OS가 프로그래머에게 적합한 운영체제인가?' 하는 것이다. 내가 개발할 때 사용하는 것은 윈도우의 경우 거의 Putty 밖에 없다고 볼 수 있다. 그 다음으로 중요한 것은 운영체제의 안정성과 인터페이스의 간결함!

큰 돈(?)을 들이지 않고 MAC을 사용해 보기 위한 방법에는 2가지가 있다. 맥북을 구입하던지

사용자 삽입 이미지
 혹은 맥미니를 구입하던지

사용자 삽입 이미지

맥북의 경우 100만원대, 맥미니의 경우 60만원대에 구입이 가능하다.

MAC OSX에 경험이 있는 여러분에게 묻습니다. SSH에 접속해서 콘솔에서 주로 작업하는 프로그래머에게 MAC OSX는 어떤 선택이 될까요? 물론 MAC OSX에서 게임할 생각은 없습니다. 안정성, 편의성, 간결함 등이 중요한 항목이 되겠네요.

1. 설치

apache2와 svn과 apache2에서 svn을 사용하기 위한 모듈을 각각 설치한다.

sudo apt-get install apache2
sudo apt-get install subversion
sudo apt-get install libapache2-svn

이제 프로젝트 저장소(Repository)를 생성한다. 여기서는 tbpcb라는 프로젝트의 저장소를 /home/svn/tbpcb에 생성하는 것을 기준으로 설명한다.

/home/svn# sudo svnadmin create tbpcb
/home/svn# sudo chmod -R g+sw tbpcb
/home/svn# sudo chown -R www-data:www-data tbpcb

svn의 설정파일을 다음과 같이 편집한다. 예제는 아이디와 비밀번호를 통해 인증을 받아야 svn에 접근할 수 있도록 한다.

sudo vi /etc/apache2/mods-available/dav_svn.conf

<Location /svn/tbpcb>
  DAV svn
  SVNPath /home/svn/tbpcb

  AuthType Basic
  AuthName "Subversion Repository"
  AuthUserFile
/etc/apache2/dav_svn.passwd
   
  Require valid-user
</Location>

dav_svn.conf 파일에서 지정한 인증파일(dav_svn.passwd)에 아이디와 비밀번호를 추가하기 위해 htpasswd2를 사용한다. 여기서는 reshout라는 유저의 아이디와 비밀번호를 dav_svn.passwd에 저장한다. 유저를 추가하고 싶다면 -n 옵션을 써서 출력되는 내용을 dav_svn.passwd에 추가해 주면 된다.

/etc/apache2# sudo htpasswd2 -c -m dav_svn.passwd reshout

2. 사용

svn 저장소에 프로젝트를 처음 올릴 때 (import)

svn import -m "Initial Import" src http://192.168.12.12/svn/tbpcb

svn 저장소에서 프로젝트를 처음 받아 올 때 (check out)

svn co http://192.168.12.12/svn/tbpcb src

작업한 내용을 저장소에 반영할 때 (commit)

svn ci

저장소의 변경사항을 내 작업 공간에 반영할 때 (update)

svn up

소스코드를 들여다 보는 일이 삶의 커다란 부분이다 보니 코딩할 때 사용하는 폰트에 민감한 편이다. 심플하고 깔끔하면서도 수려한 것을 좋아하는 개인적인 성향도 무시할 수 없을 것이다. 아마 별로 이런쪽으로 무감각했다면 "굴림체"만 쓰고 있었겠지. "굴림체"의 한글은 여전히 아주 깔끔하고 만족스럽지만 코딩할 때의 영문 "굴림체"는 영 매력이 없다!

얼마전 웹서핑 중에 우연히 Finding the Best Programmer's Font라는 제목의 웹페이지를 찾아가게 되었고 몇 가지 시도해본 중에 괜찮다고 생각되는 폰트 3가지를 소개하고자 한다. 개인적인 선호도 순서대로 나열해 보았다. 스크린 샷은 Putty로 해당 폰트를 사용한 것이다.

1. Monaco
귀여운 느낌이 들면서도 깔끔한 폰트로 최근에 애용하고 있다.

사용자 삽입 이미지

2. Bitstream Vera Sans Mono
참고한 사이트에서 1위를 차지한 폰트. 정갈하고 절제된 멋이 일품. 허나 다소 심심한 느낌.

사용자 삽입 이미지

3. Anonymous
힘이 느껴지면서도 깔끔한 맛이 있다. 숫자 0의 표현이 인상적인 폰트.

사용자 삽입 이미지

여러분은 어떤 폰트가 가장 맘에 드시나요?
사용자 삽입 이미지

사람의 기억력이라는 것에는 한계가 있기에 한번 봤던 것들을 체계적으로 관리해 놓고 활용하는 것이 일 또는 공부의 능률을 향상시키는데 커다란 역할을 한다. 특히 한달 동안 파견근무로 SI일을 하면서 절실히 깨달았다. 개발과정에서 무수히 등장하는 이전 시스템의 테이블과 컬럼들 그리고 그 것이 매핑되는 새로운 테이블과 컬럼들을 매번 뒤지고 다니자면 짜증이 밀려오는 것은 시간문제! 이대로는 안되겠다 싶어 포스트잇을 활용해보기도 하고 엑셀파일에 기록하기도 하면서 나름의 효율적인 자료정리 방법을 찾아 나섰다.

종이에 정리하는 방법은 확실히 한계가 있다. 추가 및 삭제를 자주 하다보면 글자가 종이에서 옮겨가거나 지워질 수 없는터라 불편한 점이 이만저만이 아니다. 결국 컴퓨터에 정리하는게 정답이라 생각되지만 문제는 자료를 체계적으로 정리할 수 있도록 도와주는 툴이 있어야 한다는 것. 그동안 그나마 자료를 정리하기에 적합하다고 생각했던 툴이 바로 moniwiki 였는데 올블로그를 서핑 중 스프링노트의 동영상을 보고나서 감동 받았다.

moniwiki의 방식을 따라가면서도 사용의 편리함과 외모의 수려함을 더했다! 편집이 간편하고 쉬울 뿐더러 상위, 하위 페이지 개념이 있어 페이지를 찾아 이동하거나 페이지 사이의 관계를 체계적으로 관리하기에 유용하다. 많은 사람들이 스프링노트에 애정을 가지고 개선할 부분에 대하여 거침없이 의견을 쏟아내고 있으니 좀 더 완성된 서비스가 되길 기대해 본다.

스프링노트 사이트를 방문해보면 여러가지 활용예제들을 볼 수 있다. 나의 경우 프로젝트 관련 자료들을 체계적으로 정리하고 월간, 주간, 일간 계획을 기록한다. 앞으로 공부하면서 얻은 전산관련 지식들을 잘 정리해 두면 두고두고 요긴하게 사용할 수 있을 것이다.

자료정리에 어려움을 겪는 분들은 한번쯤 고려해보세요.
대우증권에 파견나가서 하고 있는 일은 대우증권의 차세대 시스템을 구축하는 것인데, 이때 사용되는 우리회사의 솔루션은 티맥스와 프로프레임이다. 티맥스는 미들웨어로서 프로프레임은 프레임워크로서의 위상을 가지며 이 둘은 물론 서로 긴밀히 연동되어 동작한다.

기존의 신한은행 프로젝트와 SK Telecom 프로젝트에서는 프로프레임 3.0이 사용되었는데, 이번 대우증권 프로젝트는 프로프레임 4.0이 처음 사용되고 있다. 그만큼 새로운 도전이기에 다소 파일럿 프로젝트의 성격을 가지게 되고 개발과정에서 변동사항이 있어 어려움을 겪기도 한다.

"프로프레임 4.0 사상"이라고 부를 만큼 프로프레임 4.0의 개발방법론은 기존의 날코딩과 확연히 다르다. 회사 보안상, 대우증권 업무 프로세스 보안상 스크린 샷을 보여드릴 수는 없지만 대략적으로 소개하자면, 가장 눈에 띄는 것은 EMB Desiner라고 할 수 있다. 프로그램을 작성하는데 있어 코드부터 작성하는 것이 아니라 업무의 플로우를 순서도 그리듯이 사각형과 화살표를 사용하여 나타낸다. 이는 DB접근에 해당하는 DBIO 모듈이나 비지니스 모듈 등을 끌어와 붙이는 작업을 포함한다. 모듈을 끌어다 쓰는 경우에는 Pro Mapper를 통해 입, 출력 데이터를 매핑한다.

프로젝트를 진행할 때 일주일에 한번씩 회의를 갖는다. 이 시간에는 프로프레임 4.0을 사용하여 시스템을 개발하면서 생각해볼만한 개선사항, 표준안등을 토론한다. 그리고 토론결과의 일부는 연구소로 피드백되어 프로프레임 4.0의 개선을 도모하고 있다.

우리회사가 만든 미들웨어 위에, 우리회사가 만든 프레임워크와 개발툴을 사용하여 시스템을 구축하면서 회사에 대한 자부심이 커가는 요즘이다.

이클립스의 기본적인 사용자 인터페이스는 크게 view와 editor로 구성됩니다. 이 글에서는 매우 간단한(!) VICODE의 Log View를 가지고 View의 구현방법을 소개하겠습니다.

사용자 삽입 이미지

먼저 plugin.xml에서 View를 확장하는 부분을 보겠습니다.

<extension
         point="org.eclipse.ui.views">
      <view
            category="kr.ac.kaist.vicode"
            class="kr.ac.kaist.vicode.view.log.LogView"
            icon="icons/esterel_image.gif"
            id="kr.ac.kaist.vicode.logview"
            name="Log"/>
      <category
            id="kr.ac.kaist.vicode"
            name="VICODE"/>
   </extension>

org.eclipse.ui.views 확장점을 사용합니다. 해당 View를 포함할 카테고리를 지정하고 View를 표현하는 아이콘을 정의합니다. 이제 LogView.java 코드를 보겠습니다. 그렇게 길지 않으니 전체 코드를 늘어놓고 글을 이어나가도록 하지요.

public class LogView extends ViewPart
{
 private Table table;
 private TableColumn[] columns;
 private final String[] TABLE_COLUMN_NAMES = { "Message", "Location", "Time" };
 private final int[] TABLE_COLUMN_WIDTH = { 400, 400, 150 };
 public LogView()
 {
  super();
 }
 public void createPartControl(Composite parent)
 {
  table = new Table(parent, SWT.BORDER | SWT.V_SCROLL);
  columns = new TableColumn[TABLE_COLUMN_NAMES.length];
  for(int i=0, n=TABLE_COLUMN_NAMES.length; i < n; i++)
  {
   columns[i] = new TableColumn(table, SWT.NONE);
   columns[i].setText(TABLE_COLUMN_NAMES[i]);
   columns[i].setWidth(TABLE_COLUMN_WIDTH[i]);
  }
  table.setHeaderVisible(true);
  table.setLinesVisible(true);
 }
 public void setLog(String message, String location)
 {
  Date date = new Date();
  SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm:ss");
  String dateString = dateFormat.format(date);
  TableItem ti = new TableItem(table, SWT.NONE);
  ti.setText(0, message);
  ti.setText(1, location);
  ti.setText(2, dateString);
  for (int i = 0; i < columns.length; i++)
  {
   columns[i].pack();
  }
 }
 public void clearLog()
 {
  table.clearAll();
 }
 public void setFocus()
 {
  table.setFocus();
 }
}

View를 구현한 클래스는 ViewPart 클래스를 상속합니다. 예제의 Log View 처럼 단순히 정보를 보여주는 View를 구현하는 경우에는 createPartControl() 메서드에서 보여주고 싶은 위짓을 정의하는 것으로 간단히 View를 구성할 수 있습니다. View에 Action을 추가한다던가 워크벤치의 다른 View 혹은 Editor와 상호작용하도록 하려면 조금 더 복잡해지겠지요.

여기서 한가지 명확히 해야할 것은 JFace viewer의 위상입니다. JFace viewer는 모델-뷰 구조를 기반으로 사용자가 쉽게 유려한 viewer를 만들 수 있도록 돕기 위해 제작된 일종의 UI 프레임워크입니다. 따라서 JFace viewer를 제작할 때 모델의 데이터를 뷰에 전달하는 Contents Provider, Label Provider 등을 구현해야 하는 것이죠. 중요한 것은(!) JFace viewer는 이클립스에서 UI를 표현할 수 있는 어떤 곳에도 붙일 수 있다는 것 입니다. 마법사의 한 페이지에 붙일 수도 있고 Editor에 붙일 수도 있죠. 이 글에서 말하는 Viewer가 아닌 View는 이클립스 워크벤치의 일부로서 화면에 정보를 나타내기 위한 부분이라고 생각할 수 있습니다. 구현하기에 따라서는 ViewPart를 상속하여 Editor의 역할을 수행하도록 만들 수도 있습니다.

본론으로 돌아와서 createPartControl() 메서드에서 SWT의 table 컨트롤을 추가하고 초기화 합니다. View에 정보를 제공하고자 하는 다른 클래스에서는 clearLog(), setLog() 메서드를 이용해서 View에 포함된 table 위짓에 값을 추가 및 삭제하게 됩니다. LogView의 인스턴스는 id를 이용해서 다음과 같이 얻을 수 있습니다.
 
 public void init(IWorkbenchWindow window)
 {
  this.window = window;
 }

 ...
 LogView logView =
    (LogView) window.getActivePage().findView(IResourceIDs.LOG_VIEW_ID);

Multi-page Editor는 여러페이지를 가진 에디터로, VICODE에서 spec.xml을 편집하는 Specifiaction Editor를 다음과 같이 총 4페이지로 구성된 형태의 에디터로 작성하였습니다. 이 글에서는 에디터 자체에 대한 내용보다는 여러페이지로 구성된 에디터를 작성하는 경우에 구현방법과 고려해야할 사항들에 대해서 소개하겠습니다.

0123

Specification Editor에서 편집할 spec.xml 파일은 총 3가지 section으로 구성되어 있습니다. 에디터의 처음 3페이지는 각 section의 편집과정을 돕기 위해 컨트롤로 구성된 폼 에디터를 제공하며 마지막 페이지는 spec.xml을 직접 편집할 수 있도록 XML 에디터를 포함하고 있습니다.

구현 디테일로 들어가기 이전에 Multi-page Editor를 구현할 때 고려해야 할 사항에 대해서 설명하겠습니다. Multi-page Editor는 하나의 EditorInput을 여러 페이지에서 편집하게 되므로 편집하는 내용이 겹치는 경우에는 서로 다른 페이지 간의 값을 동기화 처리를 해주어야 합니다. 이 글에서 설명하는 페이지간의 동기화 방법은 직접 고안한 것이므로 효율적이지 않을 수 있습니다. ^^;

VICODE의 Specification Editor의 경우에 EditorInput은 spec.xml 입니다. 처음 3페이지의 폼 에디터와 마지막 페이지의 spec.xml 페이지는 편집의 범위가 겹치게 됩니다. 게다가 spec.xml을 구성하는 3가지 section 사이에서도 서로 값이 의존적으로 사용되기 때문에 각 페이지에서 변경된 값은 항상 다른 페이지에도 적용되어야 합니다. VICODE의 경우 다음과 같이 3가지 객체의 값이 동기화된 상태로 유지되어야 합니다.

spec.xml - AST - 각 페이지의 컨트롤이 가지는 값

AST는 spec.xml을 파싱해서 얻게 되는 Abstract Syntax Tree를 의미합니다. 에디터가 실행되면 spec.xml을 파싱해서 AST에 저장하게 되고 각 페이지의 컨트롤의 값은 AST의 값을 바탕으로 채워지게 됩니다. 이 것은 제가 말한 동기화의 아주 일부분이죠. 상세내용은 뒤에서 다루기로 하고 일단 코드를 보도록 하겠습니다.

우선 Editor의 확장점은 org.eclipse.ui.editors 입니다. Multi-page editor의 확장은 다른 editor의 확장방법과 다르지 않습니다. 다음은 확장을 정의한 plugin.xml의 일부입니다.

<extension
         point="org.eclipse.ui.editors">
      <editor
            class="kr.ac.kaist.vicode.editor.spec.SpecEditor"
            contributorClass="kr.ac.kaist.vicode.editor.spec.SpecEditorContributor"
            default="true"
            filenames="spec.xml"
            icon="icons/sample.gif"
            id="kr.ac.kaist.vicode.editor.spec.SpecEditor"
            name="Specification Editor"/>
</extension>

filenames 속성을 통해 spec.xml 파일에만 적용되도록 정의하였습니다. 이제 에디터를 구현한 SpecEditor 클래스를 살펴보겠습니다.

public class SpecEditor extends MultiPageEditorPart
    implements IResourceChangeListener
{
 private final String endl = "\n";
 private TextEditor editor;
 private String specFilePath;
 private int currentPageIndex = 0;
 private int editorPageIndex;
 private CommunicationPage communicationPage;
 private ApiPage apiPage;
 private RulePage rulePage;

 private Spec spec;

MultiPageEditorPart를 상속하여 구현합니다. 멤버변수로 눈여겨 보아야 할 것은 각 페이지를 참조할 수 있는 인스턴스와 AST를 저장하는 spec 입니다. ApiPage 등은 Composite을 상속한 클래스로 페이지를 구성하는 컨트롤을 정의하고 있습니다. editor는 마지막 페이지를 구성하는 XML 에디터의 레퍼런스 입니다. 이제 각 페이지를 어떻게 에디터에 추가하는지 살펴보겠습니다.

 protected void createPages()
 {
  createCommunicationPage();
  createApiPage();
  createRulePage();
  createXmlEditorPage();
 }
 void createRulePage()
 {
  rulePage = new RulePage(getContainer(), SWT.NONE, this);
  int index = addPage(rulePage);
  setPageText(index, "Rule");
  rulePage.setSpec(spec);
 }
 void createXmlEditorPage()
 {
  try
  {
   editor = new XMLEditor();
   editorPageIndex = addPage(editor, getEditorInput());
   setPageText(editorPageIndex, editor.getTitle());
  }
  catch (PartInitException e)
  {
   ErrorDialog.openError(getSite().getShell(), "Error creating nested text editor", null, e.getStatus());
  }
 }

createPages() 메서드에 페이지를 추가하는 코드를 작성해 주어야 합니다. 여기서 불리는 createRulePage()를 살펴보면 addPage() 메서드를 이용해서 에디터에 페이지를 추가하는 것을 확인할 수 있습니다. XML 에디터를 추가하는 createXmlEditorPage() 메서드에서는 addPage() 메서드의 두번째 인자에 Multi-page Editor의 EditorInput(spec.xml)을 넘겨줍니다.

Multi-page Editor에서 save가 발생한 경우 호출되는 doSave() 메서드를 작성해야 합니다.

 public void doSave(IProgressMonitor monitor)
 {
  if (currentPageIndex == editorPageIndex)
  {
    getEditor(editorPageIndex).doSave(monitor); // save
   Xml2Spec parser = new Xml2Spec(specFilePath);
   spec = parser.parseSpec(); // parsing to get AST

   communicationPage.setSpec(spec); // set AST to each page
   apiPage.setSpec(spec);
   rulePage.setSpec(spec);

  }
 }

Specification Editor에서 첫 3페이지는 저장 명령이 유효하지 않고 Apply 버튼을 클릭함으로써 수정내용을 AST와 파일에 적용하도록 구성되어 있습니다. Reply 버튼을 클릭하면 AST의 내용으로 컨트롤의 값을 복구 합니다. 반면에 4번째 페이지인 XML 에디터 페이지를 선택한 경우에 저장하게 되면 XML 에디터의 doSave() 메서드를 호출하여 spec.xml에 저장하게 됩니다. 저장이 완료되면 spec.xml의 내용이 갱신되었기 때문에 이를 다시 파싱하여 새로운 AST를 얻고 각 페이지에 setSpec() 메서드를 이용해 AST를 갱신해줍니다. 각 페이지는 이 AST를 이용해 컨트롤에 값을 설정하겠죠.

다음으로는 페이지가 변경되었을 때 호출되는 pageChange() 메서드를 볼까요?

 protected void pageChange(int newPageIndex)
 {
  switch (newPageIndex)
  {
  case 0:
   communicationPage.updatePage(); // AST to control
   break;
  case 1:
   apiPage.updatePage();
   break;
  case 2:
   rulePage.updatePage();
   break;
  case 3:
   updateSpecFile(); // AST to spec.xml
   break;
  default:
  }
  currentPageIndex = newPageIndex; // save current page index
 }

처음 3페이지가 선택된 경우에는 AST의 내용을 바탕으로 컨트롤의 값을 채워주는 함수인 updatePage() 메서드를 호출합니다. 4페이지가 선택된 경우에는 AST의 내용을 spec.xml에 저장합니다. 따라서 XML 에디터는 최근 변경된 spec.xml의 코드를 출력하게 됩니다.

흐름을 다시 정리해보면, 에디터가 열리면서 spec.xml을 파싱하여 AST를 저장합니다. 처음 3페이지가 선택된 경우에는 AST의 내용을 가지고 페이지를 구성하는 컨트롤의 값을 채웁니다. 이 컨트롤의 값을 수정한 후 Apply 버튼을 누르게 되면 AST를 갱신함과 동시에 spec.xml 파일을 AST를 가지고 저장합니다. 반대로 XML 에디터에서 수정하고 저장한 경우에는 저장된 spec.xml 파일을 다시 파싱하여 AST를 구하고 이 것을 각 페이지에 넘겨줍니다.

이해를 돕기 위해 아래에 SpecEditor.java, RulePage.java 파일을 예제로 남깁니다.
 

이 글에서는 SWTJFace가 대략 무엇인지, 그리고 이클립스에서 차지하는 위상은 어떤 것인지에 대해서 개괄적으로 이야기하겠습니다. JFace는 일종의 프레임워크이다 보니 공부를 상당히해야 코딩이 가능하지만, SWT를 이용한 코딩은 AWT/Swing으로 UI를 작성해 보신 분이라면 쉽게 적응하실 수 있으리라 생각됩니다. 구조에 큰 차이가 없습니다.

SWT는 Standard Widget Toolkit의 약자로 이클립스에서 UI를 표현하는데 사용되는 API 입니다. SWT가 나오기전에는 AWT와 Swing을 사용했습니만, 써보신 분은 아시겠지만 UI가 어설프고 예쁘지가 않습니다. SWT의 특징은 현재 사용중인 OS에 어울리는 미려한 UI를 제공한다는 것입니다. JNI를 이용해 호스트 운영체제가 제공하는 사용자 인터페이스를 불러서 사용하기 때문이죠. 이클립스를 윈도우, 리눅스에서 각각 실행해보면 SWT와 Swing의 차이를 확인할 수 있습니다. Swing을 사용한 어플리케이션은 윈도우에서나 리눅스에서나 적당히 비슷하면서도 적당히 어설픈 UI를 보여줍니다.

이클립스 플러그인을 제작할 때, SWT는 빈번히 사용됩니다. 마법사의 각 페이지나 Preference 페이지를 작성할 때 등등 세부 사용자 인터페이스를 정의할 때 SWT 코딩을 해야 합니다. 이클립스에서 UI를 제공하는 클래스는 다음과 같이 createContents() 메서드를 오버라이딩 함으로써 유저 인터페이스를 정의합니다. 이때 사용되는 것이 SWT 입니다.

 protected Control createContents(Composite parent) {
  // TODO Auto-generated method stub
  initializeDialogUnits(parent);
  // Get composite and set layout manager
  Composite composite = new Composite(parent, SWT.NONE);
  GridLayout layout = new GridLayout();
  layout.marginHeight = convertVerticalDLUsToPixels
    (IDialogConstants.VERTICAL_MARGIN);
  layout.marginWidth = 0;
  layout.verticalSpacing = convertVerticalDLUsToPixels(10);
  layout.horizontalSpacing = convertHorizontalDLUsToPixels
    (IDialogConstants.HORIZONTAL_SPACING);
  composite.setLayout(layout);

AWT/Swing과 다른 몇가지 SWT의 특징을 언급하고 JFace로 넘어가겠습니다. 우선 Widget간의 부모/자식 관계를 맺는 방법에서 차이가 있습니다. AWT/Swing에서는 다음과 같은 방법으로 부모 인스턴스에 자식 인스턴스를 추가합니다. 패널에 버튼을 추가하는 것을 예로 들 수 있겠습니다.

부모_인스턴스.add(자식_인스턴스);

반면에 SWT에서는 자식 인스턴스를 생성할 때 부모의 인스턴스를 첫번째 인자로 넘겨줍니다. 예제코드에서 Composite을 추가하는 부분을 참조하세요. 그리고 두번째 인자로 스타일 비츠(style bits)라는 것을 정의합니다. SWT.NONE, SWT.PUSH, SWT.CHECK 등이 스타일 비츠에 해당합니다. 이 상수들을 |로 묶어 Widget의 속성을 결정합니다. 물론 각 Widget마다 유효한 스타일 비츠가 정해져 있습니다. 마지막으로 언급할 것은 SWT가 실제 운영체제의 리소스를 사용하기 때문에 더 이상 쓰지 않을 때 해제해야 한다는 점 입니다. 대부분의 SWT Widget은 앞서 살펴본 것 처럼 생성자에서 부모를 지정하기 때문에, 부모를 폐기하면 자식도 폐기된다는 규칙에 의해서 문제가 되지 않습니다. 하지만 부모의 Widget 없이 생성된 SWT 오브젝트인 Font, Image, Color 등등은 사용하지 않을 때 직접 폐기해야 합니다.

JFace는 SWT를 보완하기 위해, 모델 기반 접근 방법(model-based approach)을 기반으로 더 적은 시간에, 더 이해하기 쉬운, 재사용 가능한 코드를 작성할 수 있도록 설계되었습니다. JFace는 UI를 효과적으로 작성하기 위한 일종의 프레임워크라고 할 수 있습니다. JFace 뷰어를 예로 들자면, JFace 뷰어가 제공하는 클래스를 상속해 정해진 절차를 따라서(!) '뚝딱뚝딱' UI를 코딩하면 '짠!' 하고 그럴듯한 하이퀄리티(?)의 UI를 화면에서 확인할 수 있는 것 입니다. JFace는 모델-뷰 구조로 구성되어있기 때문에, 이미 어플리케이션에서 사용하던 모델을 자연스럽게 사용할 수 있습니다. 물론 모델과 뷰사이의 연결을 담당하는 코드를 작성해야 하겠지만요. (e.g. ContentProvider , LabelProvider) JFace는 UI의 얼개에 해당하므로 SWT 역시 함께 사용해야 합니다. 

아주 오랜만에 이클립스 플러그인에 관한 글을 다시 적게 되었습니다. 연구실에 남아있을 마지막 2주일 동안 그 동안 못다뤘던 부분들을 정리하려 합니다. 오늘은 마법사에 대해서 다루겠습니다. 마법사(Wizard)가 무엇인지는 각종 개발툴을 써보셨다면 이미 잘 알고계실 것 같습니다.  VICODE 사용자 메뉴얼을 존대말로 쓰다보니 탄력받아(?) 존대말로 쓰게 되었네요.

마법사는 여러 페이지로 구성되어 있습니다. 각 페이지는 프로젝트를 생성하는 등의 작업을 위한 일련의 단계를 표현합니다. 그리고 각 페이지는 자신에게 필요한 정보가 입력되었는지를 판단하여 마법사에게 알립니다. 마법사는 페이지의 상태에 따라 다음 페이지로의 이동가능 여부를 판단하여 UI에 반영하는 것이죠. 모든 페이지가 완료 상태에 도달하면 Finish 버튼이 활성화 되어 마법사를 종료할 수 있습니다. Finish 버튼이 클릭되면 마법사는 각 페이지에서 받은 정보를 바탕으로 원하는 작업을 수행하게 됩니다.

코드레벨에서 살펴보면 마법사는 마법사 클래스각 페이지에 해당하는 클래스의 집합으로 구성됩니다. 마법사 클래스는 페이지 클래스를 참조하고 있고  addpages() 함수에서 페이지 클래스를 마법사에 등록합니다.

지금부터는 코드를 가지고 상세구현 과정을 살펴보도록 하겠습니다. 이클립스 플러그인의 시작은 확장점입니다. 마법사를 추가할 수 있는 확장점은 총 3가지가 있는데, 이 글에서는 프로젝트 생성 마법사를 추가하는데 사용되는 org.eclipse.ui.newWizards를 사용하겠습니다. 다음코드는 확장을 정의한 plugin.xml 코드의 일부분입니다.

   <!-- new project wizard -->
   <extension
         point="org.eclipse.ui.newWizards">
      <category
            id="kr.ac.kaist.vicode"
            name="VICODE"/>

      <wizard
            canFinishEarly="false"
            category="kr.ac.kaist.vicode"
            class="kr.ac.kaist.vicode.wizard.NewProjectWizard"
            finalPerspective="kr.ac.kaist.vicode.perspective"
            hasPages="true"
            icon="icons/esterel_image.gif"
            id="kr.ac.kaist.vicode.newprojectwizard"
            name="VICODE Project"
            preferredPerspectives="kr.ac.kaist.vicode.perspective"
            project="true"/>
   </extension>

마법사 확장점에는 여러가지 속성이 있습니다. Perspective 관련 속성에는 VICODE perspective의 id를 정의하였습니다. canFinishEarly는 모든 페이지를 다 거치지 않아도 완료할 수 있는 마법사인지를 정의합니다. hasPages는 여러 페이지를 가진 마법사인지를 정의합니다. 예제로 보여드릴 VICODE 프로젝트 생성 마법사는 2페이지로 구성되어 있고 모든 페이지를 거쳐야 하므로 위의 코드와 같이 정의하였습니다.

먼저 마법사 클래스(NewProjectWizard)를 살펴보도록 하겠습니다.

public class NewProjectWizard extends Wizard implements INewWizard
{
 private WizardNewProjectCreationPage mainPage;
 private WizardInitialPage initialPage;

 private IProject newProject;

 public boolean performFinish()
 {
  createNewProject();
  initialPage.finish(newProject);
  return true;
 }

 public void addPages()
 {
  mainPage = new WizardNewProjectCreationPage("New VICODE Project (1/2)");
  mainPage.setDescription("Create a new VICODE project in the workspace");
  mainPage.setTitle("Create VICODE Project");
  initialPage = new WizardInitialPage("New VICODE Project (2/2)");
  initialPage.setDescription("You can specify top module name and communication event.");
  initialPage.setTitle("Module declaration for hardware and Communication Event");
  addPage(mainPage);
  addPage(initialPage);

 }

프로젝트 마법사 클래스는 Wizard 클래스와 INewWizard 인터페이스를 상속합니다. 예제 마법사의 목표는 두 페이지에 걸쳐 정보를 받아 들인 후 프로젝트를 생성하는 것 입니다. 총 2페이지로 구성되어 있는데, 첫번째 페이지는 구현하지 않고 이미 작성된 프로젝트 생성 페이지를 가져다가 사용하였습니다. 이 페이지는 단순히 프로젝트 이름과 저장위치를 지정할 수 있도록 구성되어 있습니다. 두 번째 페이지는 VICODE 프로젝트를 생성하는데 있어 필요한 정보를 입력받기 위해 직접 구현한 페이지입니다.

addPages() 메서드에서는 각 페이지의 인스턴스를 생성하고 초기화한 후에 addPage() 메서드를 호출하여 마법사에 각 페이지를 등록합니다. Finish 버튼이 클릭되면 호출되는 performFinish() 메서드에서 마법사 완료시에 필요한 일들을 기술합니다. 실제 프로젝트가 생성되는 코드는 첨부파일을 참조하시기 바랍니다.

01

지금부터는 두번째 페이지에 해당하는 코드를 살펴 보겠습니다.

public class WizardInitialPage extends WizardPage
{
 public void createControl(Composite parent)
 {
  Composite composite = new Composite(parent, SWT.NONE);
  GridLayout gridLayout = new GridLayout();
  gridLayout.numColumns = 1;
  composite.setLayout(gridLayout);
  createModuleNameGroup(composite);
  createCommunicationGroup(composite);
  setControl(composite);

  updatePageComplete();
  setMessage(null);
  setErrorMessage(null);

 }
 private void updatePageComplete()
 {
  setPageComplete(false);
  // 페이지의 완결성 체크
  if (moduleNameText.getText().equals(""))
   return;
  // 페이지의 완결성 체크를 건너 뛰었다면 페이지를 완료상태로 변경
  setPageComplete(true);
  setMessage(null);
  setErrorMessage(null);

 }

마법사의 모든 페이지 클래스는 WizardPage 클래스를 상속합니다. UI를 정의하는 다른 클래스와 마찬가지로 createControll() 메서드에서 SWT로 사용자 인터페이스를 작성합니다. 마지막에 호출되는 메서드인 updatePageComplete()는 페이지에 필요한 정보가 입력되어 있는지를 판단하기 위해 제가 작성한 메서드 입니다. 이 메서드는 각 컨트롤에서 값이 변경될때마다 호출되어 페이지가 완료상태인지를 setPageComplete() 메서드를 호출하여 마법사에 알립니다.

이상으로 이클립스 플랫폼에서 마법사를 구현하는 방법에 대해서 말씀드렸습니다. 아래 첨부한 소스코드를 참조하시면 이해하시는데 도움이 될 것 같습니다.


사용자 삽입 이미지

블로그 스피어에서 우연히 발견한 다음 웹인사이드를 사용한지 일주일이 지났다. 어느정도 데이터가 성숙되었다고 판단하고 reshout.com의 분석결과를 살펴보았다. 재밌는건 대부분의 방문이 검색엔진으로부터 발생하고 있으며, 그 검색엔진에 입력된 검색어 중에 단연 "적천사주"가 절대적인 위치를 차지하고 있다는 점이다.

나는 reshout.com이 많은 사람들의 RSS 리더에 등록되어 고정적인 독자가 방문하는 블로그가 되었으면 한다. 특히 내가 읽은 책과 공부한 전산지식을 소개하는 공간으로서 의미를 가졌으면 좋겠다. 그런 측면에서 이번 분석 결과는 다소 실망스럽군.

그러나 그나마 고무적인 사실은 reshout.com의 RSS가 한RSS에서 15명에게 등록되어 있다는 사실. 아주 오랫동안 5명이였는데 최근에 급상승한 것 같다. 그다지 재미있는 주제를 다루고 있는 블로그는 아니지만, 책에 대한 데이터가 쌓이면서 조금씩 알려지고 있는 것 같다.

우연히(?) 한글 오피스 2007의 RTM 버전을 P2P에서 발견하고는 호기심을 참지 못해 다운받아 설치하고 말았다. 그 당시 디펜스 슬라이드를 만들고 있었을 때니 업그레이드 밖에 안된다면 모험이 될 수도 있었는데, 기존의 버전을 유지하는 옵션을 제공하고 있었다. (오피스 사용기라고 하기는 조금 뻘쭘한 것이 내가 몇일 동안 제대로 사용해본 것은 파워포인트와 아웃룩 뿐이다.)

사용자 삽입 이미지

Microsoft PowerPoint 2007


처음 사용해 본 것은 PowerPoint. 디펜스 슬라이드의 대부분이 완성된 상태에서 2007 버전으로 갈아탔기 때문에 편집과정을 많이 경험해보지는 못했다. 일단 눈에 띄는 것은 메뉴의 구성. 개인적으로는 새롭게 바뀐 UI가 상당히 마음에 든다. 직관적이라고나 할까? 편집에 필요한 모든 것들이 상단에 일관적으로 배치되어 있고, 텍스트를 편집할 때 마우스 오른버튼을 누르면 그 자리에서 속성을 결정할 수 있어 매우 편리하다. 대부분의 메뉴가 아이콘으로 제공되어 원하는 기능을 찾기가 수월하다. 개인적으로는 오피스 2007 설치 후 추가되는 몇가지 폰트 중에 Corbel 폰트가 마음에 들어 디펜스 슬라이드의 폰트를 교체했다.

사용자 삽입 이미지

Microsoft Outlook 2007


연구실에 처음 들어왔을 때 한동안 Outlook을 메일 클라이언트로 사용하다가 그만둔 이유는 메일을 읽어오는게 느렸기 때문이다. 문제는 수 없이 쏟아지는 스팸메일을 읽는데 시간을 소비한다는 것. 그래서 이번에는 Gmail의 POP를 사용해서 계정을 설정하고 Outlook을 사용해봤다. Outlook을 쓸때의 단점은 Outlook에서 보낸 메일이 웹메일에서 보이지 않는다는 것이였는데, Gmail을 Outlook에 사용한 경우 Outlook에서 보낸 메일도 Gmail의 보낸편지함에 저장되어 둘을 동시에 사용하는데 문제가 없었다.

범주라는 개념이 추가되어 Gmail의 레이블처럼 메일을 분류하는데 유용하다. 색깔 별로 메일과 작업을 분류할 수 있는데 나는 연구실 관련일을 빨간색, 문화 생활 관련일은 노란색으로 표시하여 사용하고 있다.

Outlook에서 지원하는 메일, 작업, 일정이 유기적으로 통합되어 오른쪽에 할 일 모음 윈도우에 보기 좋게 정리해서 출력해준다. 덕분에 당장 신경써야 할 일들을 한눈에 확인할 수 있다. 전에도 있었던 기능인지는 모르겠지만 이메일에도 어떤 날에 관련있는 것인지를 표시하여 할 일 항목으로 활용할 수 있다. 항상 시간관리를 어떻게 해야하는 것이 가장 효율적인가에 대해 고민하고 여러가지를 시도해보았지만 앞으로는 Outlook 2007을 이용할 계획이다.

전체적인 느낌은 UI가 예쁘고 편리하다는 점. 특히 윈도우 비스타 RC2에서 어설퍼 보이던 맑은 고딕 폰트가 오피스 2007에서 깔끔하게 보여서 매우 마음에 든다. 내년 2월 회사에 가면 오피스 2007을 쓸 수 있었으면 좋겠다.

사용자 삽입 이미지


한가지 현재 아쉬운 것은 RTM 버전이라 그런지 잊을 만 하면 한번씩 오류메시지가 뜬다는 점.

+ Recent posts