The Memory of Black Tea

홍차의 추억

Once upon a time when many people was into green tea, I tried black tea because I always had wanted to be special. But it was too bitter for me because it was just a cheap tea bag listed just to provide an assortment of a menu. Did it taste this bitter? I soon forgot this disappointing moment.

많은 사람들이 녹차에 빠져 있을 무렵, 남들과는 다른 무언가를 좋아했던 나는 홍차를 시도했다. 하지만 메뉴에 구색을 맞추려고 올려진 티백 홍차는 너무나 썼다. 이런 맛이었다니. 실망하고는 이내 잊고 지냈다.

It was our hundredth day anniversary since my girl friend and I met one day. (Yes, most Korean couples count the number of days since two met, and celebrates every hundredth day at least for the first two years 😉 I was looking for a great gift which is destined to move her heart, and a tea pot and cups caught my sight. They were creamy white, chubby and cute, and modern Japanese ceramic tea pot and cups. I loved it much more than other similar ones.

그러던 어느 날 영희씨의 마음을 움직일 백일 선물을 고민하던 중 우연히 찻잔 세트가 눈에 들어왔다. 뽀얀 백색의 통통하면서도 앙증맞은, 모던한 분위기의 일본산 사기 찻주전자와 찻잔이었다. 다른 찻잔 세트들보다도 디자인이 마음에 들었다.

By the way, don’t I need tea if I am going to present tea things? I started to investigate on various kinds of tea because I had no idea on this topic. It was nothing comparing to choosing cosmetics which has encrypted product names and vague description under stress in the future, but I was in agony for at least a couple hours. It was earl gray from ‘Whittard of Chelsea‘.

그런데 찻잔이 있으면 차가 있어야 할 것 아닌가? 차에 대해서는 문외한이나 다름 없는 나는 이것 저것 조사하기 시작했다. 후일 화장품을 사면서 그 난해한 제품명과 애매한 설명에 스트레스 받던 것에 비교하면 아무것도 아니었겠지만 족히 몇 시간은 고민했던 것 같다. 그래서 결국 결정한 것이 ‘위타드 오브 첼시‘라는 브랜드의 얼 그레이였다.

Tea pot and cups as an anniversary gift, it seems like it was a special gift for her. The heat and fragrance of earl gray was mild enough for us to forget cold and harsh weather outside. Surrounded by the mildness, night came sooner than we expected with endless whispering, and my way back home just felt so far away from there. Our love grew up and up like that. The cups have been cracked unexpectedly and became useless now, but the feeling at those moments have been carved into my body and soul. Recalling back, the first place I hold of her hands were also a tea house in Insadong. Special tea might have led two persons’ relationship through a special mood.

백일 선물로 찻잔 세트라, 그녀에게는 특별한 선물이었던 것 같다. 기념으로 따라 본 얼 그레이의 향과 열기는 추운 바깥 날씨를 잊게 할 정도로 포근했다. 그 포근함에 감싸여 담소를 나누다 보면 어느새 밤이 깊고 귀가길은 멀게만 느껴지기 일쑤였다. 그렇게 우리의 사랑은 커갔고, 그 잔은 세월이 흘러 예기치 않게 여기 저기 금이 가 못 쓰게 되버렸지만, 그때의 느낌만은 지금도 내 몸 속에 기억되어 있다. 돌이켜 보면, 내가 그녀의 손을 처음 잡은 곳도 인사동의 한 전통 찻집이었다. 색다른 차는 색다른 분위기를 통해 두 사람의 관계를 이끌어 주었는지도 모르겠다.

It was quite long time after when I bought my own tea cup. It was a ‘tea for one‘ from Jenaer Glas made with glass, which was found after wandering for a couple hours to meet my strict taste that even myself can’t often meet. I was surprised that the cup was bigger than I thought, but its practical design was very attractive. I enjoyed the fragrance and heat radiated from the tea cup after lunches when I am alone in my house. Looking into the calm flow of time from a sandglass, I was able to empty my head at least at that moment. The cup also has broken into pieces thanks to my mother, but I still just feel like I can go back to the touch that the weight of the full cup gave tension to my forefinger.

집에 내 찻잔을 들여 놓은 것은 그 뒤로 짧지 않은 시간이 흘러서였다. 스스로 맞추기에도 벅찬 내 취향에 맞는 찻잔을 찾기 위해 몇 시간 즈음 해매다가 찾은 것은 예나 글래스의 유리로 만든 티포원이었다. 찻잔이 생각보다 커서 조금 놀랐지만 실용적인 디자인이 참 마음에 들었다. 집에서 혼자 점심 식사를 하고 나면 찻찬에 물을 붓고 가만히 앉아 은은히 퍼져나오는 향과 열기를 만끽하곤 했다. 모래시계가 고요히 품어내는 시간의 흐름을 가만히 들여다 보고 있으면, 그 순간만큼은 모든 생각을 비울 수 있었다. 지금은 그 찻잔도 어머니의 실수로 깨어지고 없지만, 그 때를 추억하면 홍차가 가득 차 나도 모르게 긴장한 집게 손가락의 감촉마저도 돌이킬 수 있을 것만 같다.

I ordered two ceramic tea-for-ones today; one for me of the next year, and the other for my acquaintance. I hope I feel the composure moment again and he also enjoys such a moment. I’m waiting for a moment my mind is empty listening to endlessly flowing time in satisfaction, with my beating heart now.

오늘은 도자기 티포원을 둘 주문했다. 하나는 내년의 나를 위해서고, 또 하나는 지인을 위해서다. 다시 한 번 그때의 여유와 행복을 느끼고, 다른 사람도 그 순간을 만끽하기를 기원하고 싶다. 나는 그렇게 아무 것도 생각나지 않는, 하염없이 흐르는 시간을 만족스럽게 받아들이는 그 순간을 두근거리는 마음으로 기다리고 있다.

ALSA OSS Emulation with Multiple Sound Cards

사운드 카드 여러개일 때의 ALSA OSS 에뮬레이션

aoss is a useful command that forwards all OSS (Open Sound System) requests to ALSA (Advanced Linux Sound Architecture) device drivers transparently, but it’s sometimes not so easy to use when an executable is wrapped by a shell script like VMware. The most easiest and clean solution for OSS emulation is loading snd-pcm-oss module by adding the following line in the /etc/modules file.

aoss는 모든 OSS (Open Sound System) 요청을 ALSA (Advanced Linux Sound Architecture) 드라이버로 투명하게 전달해 주는 유용한 명령이지만, VMware처럼 실행 파일이 쉘 스크립트로 둘러싸여 있으면 사용하기가 쉽지 않습니다. OSS 에뮬레이션에 대해 가장 쉽고 깔끔한 방법은 /etc/modules 파일에 다음 행을 추가해 snd-pcm-oss 모듈을 로드하는 것입니다.


Is that all? Not actually if you have more than one sound cards. You have to choose which one is your primary sound card, where the OSS requests should be forwarded to. In my case, my primary sound card is ESI Audiotechinik [email protected], and the secondary one is built-in Intel i8x0 chip. You can set the order of these sound cards by adding kernel options to the /boot/grub/menu.lst file like the following.

이게 다일까요? 사운드 카드가 하나 이상이라면 다가 아닙니다. OSS 요청을 포워딩 받을 첫 번째 사운드 카드를 정해 주어야 합니다. 저같은 경우 첫 번째 카드는 ESI [email protected]이고, 두 번째 카드는 내장된 인텔 i8x0 칩입니다. 다음과 같이 /boot/grub/menu.lst 파일에 커널 옵션을 추가하여 이들 사운드 카드의 순서를 정할 수 있습니다.

## additional options to use with the default boot option, but not with the
## alternatives
## e.g. defoptions=vga=791 resume=/dev/hda5
# defoptions=snd-ice17xx-ak4xxx.index=0 snd-intel8x0.index=1

If you are using a different sound card, you could replace the driver names above (snd-xxxx) with yours. If you are finished editing the menu.lst file, you have to run update-grub command to auto-generate other sections of the menu.lst.

다른 사운드 카드를 사용하고 계신다면 위의 드라이버 이름들을 (snd-xxxx) 갖고 계신 사운드 카드의 드라이버로 바꾸면 됩니다. menu.lst 파일 수정을 마치면, update-grub 명령을 실행해 menu.lst 파일의 다른 부분을 자동 생성해야 합니다.

[email protected]:~$ sudo update-grub
Searching for GRUB installation directory ... found: /boot/grub
Testing for an existing GRUB menu.list file ... found: /boot/grub/menu.lst
Searching for splash image ... none found, skipping ...
Found kernel: /vmlinuz-2.6.17-10-generic
Found kernel: /vmlinuz-2.6.15-27-686
Found kernel: /vmlinuz-2.6.15-26-686
Found kernel: /vmlinuz-2.6.15-25-686
Updating /boot/grub/menu.lst ... done

Presentation Material: Java 5 Generics

발표 자료: Java 5 Generics

Download here. (Korean)
여기에서 받으실 수 있습니다.

Yes, I know. Java 6 has been released. But it is also true that not all developers know how to design their API with Generics, and it’s because they might not have a chance to catch up this big change. So, I wrote a presentation material for my teammates, and of course, myself.

압니다. 얼마전 Java 6가 나왔지요. 하지만 모든 개발자들이 Generics를 이용해 API를 디자인하는 법을 알고 있는 것은 아닙니다. Generics라는 큰 변화를 따라잡을 기회가 없었을 수도 있거든요. 그래서 우리 팀원들, 그리고 물론 제 자신을 위해 발표 자료를 만들었습니다.

(Please note this presentation material is written in Korean, my mother tongue. But wait! Just download and try to read the code and a few English sentences. If you are interested in this material, please let me know. I could translate it to English if I notice there’s demand for it. 🙂

Setting svn:keyword Property Automatically

svn:keywords 프로퍼티 자동으로 설정하기

Subclipse dropped ‘Add Keywords…’ dialog since 1.1.7. I couldn’t understand why they got rid of such a useful feature, but now I figure out that it is because there’s much easier way to do that. Yes, I don’t need to forget to set the property or to make mistakes by applying the properties to wrong targets such as binary files; we got auto-props.

Subclipse 1.1.7부터는 ‘Add Keywords…’ 대화창이 없어졌습니다. 아주 유용한 기능이었는데 왜 없앴는지 이해가 안갔지만, 더 쉬운 방법이 있어서였다는 것을 알게 되었습니다. 프로퍼티 설정하는 것을 잊어버리거나 바이너리 같은 엉뚱한 파일에 프로퍼티를 적용하는 실수를 할 필요가 없었던 것이죠. auto-props가 있으니까요.

auto-props configuration adds specified properties to the files that matches certain patterns automatically when svn add or svn import operation is executed. This feature is disabled by default. To enable it, add the following line to the [miscellany] section of your ~/.subversion/config file.

auto-props 설정을 사용하면 svn addsvn import 명령을 수행할 때 특정 패턴에 맞는 파일들에 프로퍼티를 자동으로 추가할 수 있습니다. 이 기능은 처음에는 꺼져 있습니다. 켜려면 ~/.subversion/config 파일의 [miscellany] 섹션에 다음 라인을 추가합니다.

enable-auto-props = yes

Now, you can add your auto-prop settings to the [auto-props] section. Here’s mine I brought from here.

이제 auto-prop 설정을 [auto-props] 섹션에 추가하면 됩니다. 다음은 제가 여기서 빌려온 것입니다.

*.java = svn:eol-style=native;svn:keywords=Rev Date
*.xml = svn:mime-type=text/xml;svn:eol-style=native;svn:keywords=Rev Date
*.xsl = svn:mime-type=text/xml;svn:eol-style=native;svn:keywords=Rev Date
*.xsd = svn:mime-type=text/xml;svn:eol-style=native;svn:keywords=Rev Date
*.wsdl = svn:mime-type=text/xml;svn:eol-style=native;svn:keywords=Rev Date
*.properties = svn:mime-type=text/plain;svn:eol-style=native;svn:keywords=Rev Date
*.c = svn:eol-style=native;svn:keywords=Rev Date
*.cpp = svn:eol-style=native;svn:keywords=Rev Date
*.h = svn:eol-style=native;svn:keywords=Rev Date
*.dsp = svn:eol-style=CRLF
*.dsw = svn:eol-style=CRLF
*.sh = svn:eol-style=native;svn:executable
*.bat = svn:eol-style=native
*.pl = svn:eol-style=native
*.py = svn:eol-style=native
*.cmd = svn:eol-style=native
*.txt = svn:eol-style=native;svn:mime-type=text/plain
*.htm* = svn:eol-style=native;svn:mime-type=text/html
ChangeLog = svn:eol-style=native;svn:mime-type=text/plain
README* = svn:eol-style=native;svn:mime-type=text/plain
LICENSE* = svn:eol-style=native;svn:mime-type=text/plain
NOTICE* = svn:eol-style=native;svn:mime-type=text/plain
TODO* = svn:eol-style=native;svn:mime-type=text/plain
KEYS* = svn:eol-style=native;svn:mime-type=text/plain
INSTALL* = svn:eol-style=native;svn:mime-type=text/plain
WHATSNEW* = svn:eol-style=native;svn:mime-type=text/plain
*.png = svn:mime-type=image/png
*.jpg = svn:mime-type=image/jpeg
*.gif = svn:mime-type=image/gif
Makefile = svn:eol-style=native
*.css = svn:eol-style=native
*.js = svn:eol-style=native

Inner Game – Work as Experiential Learning

이너 게임 – 체험적 학습으로서의 일

체험적 학습으로서의 일

I drew a mind map of ‘Inner Game of Work‘, written by Timothy Gallwey. It was quite an interesting read though there were several boring sections. (Sorry for not publishing the mind map in English. I don’t have time to translate it and it won’t worth that much because I didn’t read the English edition so the terms used in the translation will be very different from the original.)

티머시 골웨이의 ‘이너 게임‘을 읽고 마인드 맵을 그려보았습니다. 몇 군데 지루한 부분도 있었지만 꽤 재미있게 읽었습니다.

Packet sniffing using tcpdump

tcpdump를 이용한 패킷 훔쳐보기

It is easy to monitor packets being exchanged by network applications in your desktop machine, because we have a great software called ‘Ethereal‘. But what if we are working on a remote console without any GUI? We have to use tcpdump. The following is typical tcpdump options I use to monitor the data being exchanged:

데스크탑 머신에서 네트워크 애플리케이션이 교환하는 패킷을 모니터링하는 것은 쉽습니다. Ethereal이라는 소프트웨어가 있기 때문이죠. 하지만 GUI가 없는 원격 콘솔에서 작업할 때는 어떻게 해야 할까요? tcpdump를 사용해야 합니다. 다음은 제가 교환되는 데이터를 모니터링하는 데 쓰는 전형적인 tcpdump 옵션들입니다:

tcpdump -N -f -s 0 -X -vvv -i eth0 
host and tcp and port 9132 and
'tcp[13] & 8 == 8'

-N and -f option works around performance and stability issues on some systems. -s 0 option prevents tcpdump from printing captured packets as truncated. -X option is used to print captures packets as hexadecimal dump format. 'tcp[13] & 8 == 8' expression filters out all packets except DATA packets because what we have interest in are only DATA packets.

-N-f 옵션은 어떤 시스템에서 발생하는 성능이나 안정성 문제를 해결합니다. -s 0 옵션은 tcpdump가 캡처한 패킷의 뒷부분을 잘라버리고 출력하지 못하도록 합니다. -X 옵션은 캡처한 패킷을 16진 덤프 형식으로 출력하도록 하는데 쓰입니다. 'tcp[13] & 8 == 8' 표현은 DATA 패킷을 제외한 모든 패킷을 필터링합니다. 우리가 관심있는 것은 DATA 패킷뿐이니까요.

Tabbed Editing with GViM and Nautilus File Manager

The default text editor of GNOME desktop environment is ‘gedit‘. I prefer ViM because it has much better functionality and customizability, and moreover, it launches faster. One thing I’ve been missing from GViM, a GUI version of ViM, was tabbed editing. GViM already supports tabbed editing, but opening a text file from Nautilus File Manager always creates a new window by default.

GNOME 데스크탑 환경의 기본 텍스트 편집기는 gedit입니다. 저는 기능도 훨씬 많고 커스터마이즈도 용이한데다가 실행 속도도 더 빠른 ViM을 선호합니다. ViM의 GViM에서 한 가지 아쉬웠던 기능은 탭 편집 기능(탭 브라우징처럼 탭으로 여러 문서를 편집하는 기능)입니다. GViM은 이미 탭 편집 기능을 제공하지만 Nautilus 파일 관리자에서 텍스트 파일을 열면 기본적으로 새 창을 열게 되어 있습니다.

Fortunately, I finally found out how to change this behavior. Nautilus stores its file association information in ~/.local/share/applications directory. You can put customized .desktop files there, and then you can associate certain file type to the customized .desktop file. In my case, I want text files to be opened in a new tab of the current GViM window. I put gvim-usercustom.desktop file to ~/.local/share/applications directory:

운좋게도 이 동작을 바꾸는 방법을 결국 알아냈습니다. Nautilus는 파일 연결 정보를 ~/.local/share/applications 디렉토리에 저장합니다. 이 디렉토리에 커스터마이즈한 .desktop 파일을 넣고 특정 파일 유형을 그 .desktop 파일에 연결할 수 있습니다. 제 경우에는 현재 떠 있는 GViM 창의 새 탭에 텍스트 파일이 열리기를 원하는 것이죠. 그래서 gvim-usercustom.desktop 파일을 ~/.local/share/applications 디렉토리에 넣어 주었습니다:

[Desktop Entry]
Name=GVim Text Editor (Tab)
Comment=Edit text files in a new tab
Exec=gvim --remote-tab %F

If you prefer other text editor and want to change its default bahavior, you could copy its .desktop file from /usr/share/applications/ and rename it to <appname>-usercustom.desktop and tweak it a little bit. Refering to this document will also help you if the application you want to associate with a certain file type isn’t listed in a default setting.

다른 편집기를 더 선호하고 그 편집기의 기본 동작을 바꾸고 싶다면 /usr/share/applications/ 디렉토리에서 그 편집기의 .desktop 파일을 복사해 <appname>-usercustom.desktop으로 이름을 바꾸고 손을 좀 보면 될 겁니다. 특정 파일 유형에 연결하고자 하는 어플리케이션이 기본 설정에 포함되어 있지 않다면 이 문서를 참조하면 도움이 될 것입니다.

Installing Subversion 1.4 in Ubuntu Edgy Eft (6.10)

Ubuntu Edgy Eft (6.10)에서 Subversion 1.4 사용하기

I’ve been using Subversive for a while because one of my colleagues told me it’s better than Subclipse, but I didn’t see any advantage from it, uninstalled it, and installed the latest version of Subclipse.

Subversive가 좋다는 이야기가 있어 사용하다가 그다지 좋은 점을 느끼지도 못했고 UI가 불필요하게 복잡하다는 생각이 들어 설치 제거한 뒤 Subclipse 최신 버전을 설치했습니다.

Duh! I didn’t know JavaHL shared object (DLL) is not provided for Linux. I had to configure Subclipse to use SVNKit instead of JavaHL, and I got another problem! The latest version of Subclipse was using the latest version of SVNKit which is using Subversion 1.4 working copy format and therefore not compatible with Subversion 1.3. Ubuntu Edgy Eft provides only Subversion 1.3, so my working copies didn’t work anymore with the command line Subversion client because SVNKit has upgraded the version of all my working copies to 1.4. svn up fails gracefully saying that I have to upgrade to 1.4.

그런데 Subclipse를 최근에는 윈도우즈에서만 사용해 왔던지라 리눅스에서는 JavaHL 공유 라이브러리가 있어야 제대로 동작한다는 사실을 까맣게 잊고 있었지 뭡니까. 어쩔 수 없이 JavaSVN을 사용하도록 옵션을 설정했는데, 여기서 문제가 발생했습니다. 최신 버전의 Subclipse가 최신 버전의 JavaSVN을 사용하고 있어서 Ubuntu Edgy Eft에서 제공하는 Subversion 1.3과 호환되지 않는 Subversion 1.4용 working copy로 제 로컬 카피를 변환해 버린 것이죠. 덕택에 명령행에서 svn up하니 제대로 되지를 않네요.

I could just check my stuff out again and revert back to Subversive, but I chose to install Subversion 1.4 because people are saying there are several performance improvements. The following is the installation procedure I stepped on.

저장소에서 다시 체크아웃하고 Subversive로 복구하면 되는 문제였지만 Subversion 1.4에서 많은 성능 향상이 있었다고 하여 Subversion 1.4를 설치하기로 했습니다. 다음은 설치 과정입니다.

$ sudo apt-get install gcc g++ libc6-dev libapr0-dev libneon25-dev
$ tar jxvf
$ cd subversion-1.4.x
$ ./configure --enable-dso --enable-javahl --with-ssl
--with-jdk=/usr/lib/j2sdk1.5-sun --without-jikes
$ make
$ make javahl
$ sudo make install
$ sudo make install-javahl

Everything has been installed, so I tried to switch to JavaHL, but there was another problem; JVM bombs out because of a bug of libapr0. We can fix this problem by building apache2 manually.

모두 제대로 설치가 되어 Subclipse가 JavaHL을 사용하도록 하려고 하니, libapr0의 버그로 인해 JVM이 죽어버리는 문제가 있네요. 이 문제는 apache2를 다시 빌드하여 해결해야 합니다.

$ sudo apt-get install dpkg-dev devscripts fakeroot
$ sudo apt-get source apache2
$ cd apache2-2.0.xx/debian
$ vi rules

Looking into rules file, there’s a sentence that sets AP2_CONFFLAGS variable. Add the following line next to the sentence and save the file.

rules 파일 안을 보면 AP2_CONFLAGS 변수를 설정하는 부분이 있습니다. 바로 아래에 다음 라인을 추가하고 저장합니다.


Now, let’s build the new deb package and install it.

이제 새 deb 패키지를 빌드해 설치합니다.

$ cd ..
$ sudo apt-get build-dep apache2
$ debchange -n # vi 뜨면 저장
$ dpkg-buildpackage -rfakeroot -b
$ cd ..
$ sudo dpkg --install libapr0*.deb

NOTE: If you encountered a dependency error while you run dpkg --install, you will also have to install the related packages whose name starts with apache2.

만약 dpkg --install 실행 중 의존성 에러가 나면 apache2로 시작하는 이름의 관련 패키지들도 설치해야 하니 주의하세요.

At last, adding -vmargs -Djava.library.path=/usr/local/lib option in your Eclipse command, JVM doesn’t bomb out anymore when Subclipse is reconfigured.

마지막으로 Eclipse 실행 옵션에 -vmargs -Djava.library.path=/usr/local/lib를 추가하면 이제 Subclipse 설정을 바꿔도 JVM이 죽지 않습니다.

다양한 객체 지향 원칙들이 존재하는 이유

재미있게 주몽을 보고 잠깐 들어와 보니 이런 저런 다양한 글들이 Context 개체가 남발되고 있다거나, 의미의 면적이 좁은 인터페이스를 제공하거나 그에 의존해서는 안된다거나, 최소 권한의 원칙과 같은 이야기를 하고 있습니다.

다 맞는 말씀입니다만, 저는 이런 원칙들의 궁극적인 목표를 생각해야 할 필요가 있다고 봅니다. 그것은 바로 소프트웨어 개발 비용을 절감시키는 것입니다. 소프트웨어 비용을 절감시켜야 한다고들 주장한다면 보나 마나 소프트웨어 비용이 늘어났다는 뜻이겠군요. 그렇다면 소프트웨어 개발 비용은 왜 늘어났을까요? 그것은 더 복잡한 소프트웨어를 만들어 내야 하기 때문입니다. 오늘날 모든 복잡한 소프트웨어는 다른 더 작은 소위 컴포넌트라 불리우는 소프트웨어에 기반해 개발되고 있습니다. 바꿔 말하면, 오늘날의 불필요한 소프트웨어 개발 비용 지출의 대부분이 의존하는 API의 사용성 (usability) 문제 때문에 발생하고 있다고 할 수 있습니다. 사용성 나쁜 API를 노출하는 컴포넌트를 사용하면 monolithic 하게 개발했을때처럼 생산성이 떨어질 수도 있습니다.

그런데 이 API의 사용성이란 것은 사실상 평가가 어려운 광범위한 분야로, 보통 객체 지향 설계 원칙이라는 고상한 말로 포장되어 왔습니다. 개발자의 입장에서 이 둘은 동의어나 마찬가집니다.

사용성이 높은 API는 전부를 모르더라도 쉽게 기본적이면서도 실무에 필요한 핵심적인 작업을 바로 시작할 수 있고, 좀 더 복잡한 케이스를 다뤄야 할 경우 다음 단계를 쉽게 배워 나아갈 수 있도록 학습 곡선을 정교하게 제어합니다. 그 과정에서 물론 과정보 (overinformation)은 억제됩니다. 즉, 누구나 빠르면서도 자신이 모르는 사이에 발전 가능한 방향으로 원하는 바를 성취하고, 학습의 즐거움을 느낄 수 있게 해 주는 것이 API 사용성의 핵심입니다.

그렇다면 Context 객체가 어떤 문제를 갖느냐, Context 객체 자체의 도입은 API 사용성 측면에서 매우 고무적입니다. 컨테이너나 커널이 제공하는 기능을 활용하여 동작하는 비즈니스 로직이 부모 컨테이너/커널이 노출하는 최소한의 기능만을 사용할 수 있도록 해 주는 개체가 Context 의 원래 역할이기 때문입니다. 첫 번째 글에서 static 하거나 ThreadLocal을 사용한 Context 객체를 예로 들었는데, 이는 부적절한 예입니다. static 하거나 ThreadLocal 하게 작성했다는 것이 문제이지, Context 객체 자체의 존재가 잘못된 것은 전혀 아닙니다. 문제가 있다면 Context 를 제공하는 컨테이너의 역할 정의가 모호했기 때문이겠죠. 그도 아니면 컨테이너도 아니면서 주제 넘게 intrusive한 인터페이스를 제공했기 때문이겠죠. 컨테이너나 프레임워크가 Context 개체를 제공하는 것은 전혀 잘못된 일이 아닙니다.

또한, 두 번째 글에서 이야기하고 있는 다양한 Context 개체가 한 코드에서 섞여서 쓰이는 문제는 그 코드가 동시에 다양한 기능을 사용하려고 했다는 뜻을 가질 뿐입니다. 동시에 여러 가지 일을 한다는 것이 항상 잘못된 것은 아니며, 적절한 검토가 필요할 따름입니다. 오캄의 면도날을 쫓는 것은 좋은 일이지만, 의존성에 지나치게 집착하는 것도 좋은 태도는 아닙니다. 클래스 하나 때문에 수백KB 짜리 JAR 쓰는게 왜 나쁩니까? 클래스 하나를 씀으로 인해 다른 원치 않는 부작용이 생겨야 나쁘지, 대부분의 잘 설계된 컴포넌트들은 그렇지도 않습니다. 글쓴이가 HTMLPageParser 하나 때문에 SiteMesh 를 사용한 것처럼요. 문제는 하고자 하는 일에 맞는 제대로 된 컴포넌트를 선택하는 것이지, 컴포넌트를 사용하느냐 마느냐가 아닙니다.

어떤 API 를 설계할 때 결과적으로 중요한 것은, 대상 – 엄밀히 말하면 다수의 – 사용자가 그 API를 편리하게 느끼느냐입니다. API가 불필요하게 많은 기능을 제공한다 하더라도 그것이 결국 그 API를 사용하는 대상이 편하게 느끼고 결과적으로 생산성을 가져다 주면 저는 상관 없다고 봅니다. 과연 관계의 수를 줄여 결국에는 다 제공해야 할 기능을 매우 복잡한 콜 그래프를 그리게 해야 할 필요가 있을까요? 전 당연히 없다고 봅니다. Humane interface 와 Minimal interface 에 대한 논쟁에서와 마찬가지로, 사용자가 얼마나 많은 정보에 노출되기를 바라느냐에 따라 호불호가 갈릴 뿐 정답은 없습니다.

중요한 것은 특정 원칙에 집중하는 것이 아니라, API 를 사용하게 될 사람의 마음을 헤아리고 그 사람이 가장 생산성 있게 개발할 수 있도록 하는 것입니다. 또한 나아가 사용자가 감동할 수 있는 API 를 제공해 그 설계 철학이 그 사용자가 개발하고 있는 컴포넌트에 전해질수 있도록 한다면 금상 첨화겠죠. 이것은 단순히 다양한 원칙들을 고수함으로서 이루어지는 것이 아니라 다분히 사용자층의 취향과도 결부되는 복잡한 상호작용의 결과, 즉, 매우 사회적인 과정입니다.

그러므로 우리는 오늘날 컴포넌트들이 얼마나 사용자를 고려해서 개발되고 있는지 생각해 볼 필요도 있습니다. 유명한 라이브러리나 프레임워크들을 보면 사용자층도 두텁고 피드백도 활발합니다. 닭이 먼저냐 계란이 먼저냐는 질문을 할 수도 있겠지만, 적절한 원칙을 세워 개발하였고, 그 과정에서 생길 수 있는 API의 까칠한 면을 커뮤니티의 도움을 받아 다듬어 나아가는 것이 지금까지 제가 보아 온 성공한 소프트웨어의 모습이었습니다. 원칙도 중요하지만 그 뒤에는 사용자가 있다는 것, 그리고 그 사용자와 상호작용이 제대로 이루어지지 않으면 그 좋은 원칙도 아무 소용 없다는 것 또한 명심해야 합니다.

Modifying Default ulimit Values for a Normal User in Linux

Linux에서 일반 사용자의 default ulimit 값 수정

The default value of ulimit -n (the maximum number of open file descriptors per process per user) is 1024 in Ubuntu Linux. There’s no problem with this default value in my daily life, but I start to get ‘Too many open files’ errors when I test the performance of server applications which accept from 1000 to tens of thousands client connections. A super user (root) can type a command like ulimit -n 10240 to increase the default limit value, but a normal user can’t. If you are at least a sudoer, you can resolve this problem by adding the following lines to /etc/security/limits.conf file.

제가 사용하고 있는 Ubuntu Linuxulimit -n (동시에 열 수 있는 파일의 총 수)의 기본값은 1024입니다. 일상 업무를 보는데는 전혀 지장이 없지만 서버 어플리케이션을 테스트하다 보면 적게는 1000개, 많게는 수만 개의 접속을 테스트해야 할 일이 생겨 ‘Too many open files’ 에러를 볼 수밖에 없습니다. 수퍼 유저 (root)라면 ulimit -n 10240과 같이 입력하여 그 제한을 올릴 수 있지만, 일반 사용자는 불가능합니다. 이때 만약 수퍼 유저 권한을 갖고 있다면 /etc/security/limits.conf 파일에 다음과 같은 내용을 추가하여 이 문제를 해결할 수 있습니다.

trustin         soft    nofile          10240
trustin         hard    nofile          10240
www-data        soft    nofile          10240
www-data        hard    nofile          10240

The example above increases the maximum number of open files per process per user to 10240 for two users; trustin and www-data.

위의 예시는 trustin과 www-data라는 사용자의 최대 연 파일 수를 10240으로 올려 줍니다.