Uncategorized

dp.SyntaxHighlighter

블로깅 하다보면, 코드를 적어야 하는 경우가 자주 발생하고, 하이라이팅을 하기 위한 편리한 방법이 필요합니다.

하이라이팅을 위해 HTML로 변환하는 툴이야 많지만, 중요한 requirement들은 다음과 같습니다.

  1. Presentation의 분리: 코드 텍스트를 (가능한 한) 원래의 형태로 저장할 것.
  2. XHTML 표준의 사용:  예를 들어, <font /> element 보다는 <span /> element, class attribute, CSS를 활용할 것.

Presentation 분리는 대체로 Textile과 같은 formatter를 따로 사용해서 얻을 수 있는데, 블로깅 툴들이 기본적으로 제공하는 경우는 없고, 글 전체에 특정 format을 사용해야하기 때문에 맘에 안듭니다. 조그만 악을 해치우기 위해 더 큰 악을 불러들여오는 꼴이랄까요. 그리고 아쉽게도 기존의 툴들은 대부분 <font /> element를 사용하는 경우가 많습니다.

겐도사마를 통해 알게 된 dp.SyntaxHighlighter를 사용해보았습니다. dp.SyntaxHighlighter의 장점은 코드 텍스트를 그대로 유지하면서, javascript와 CSS를 통해 하이라이팅을 하기 때문에 위의 requirement들을 모두 만족한다고 볼 수 있습니다.

dp.SyntaxHighlighter 더 읽기"

Deposit-Refund System for Disposable Espresso Cups

어릴 적엔 부족한 군것질 용돈을 충당하기 위해서 빈병 모아다가 구멍가게에 가져다주곤 했다. 이것이 바로 공병 보증금제도 인데, 소비자가 제품의 비용에 추가적인 비용을 예치(deposit)하고, 나중에 돌려받는다고(refund)해서 Deposit-Refund System이라고 부른다. 현재 대부분의 에스프레소 커피전문점들은 일회용 컵에 대해 이와 같은 ‘환경 보증금’이라는 이름의 제도를 실시하고 있다.

환경 보증금은 물론 좋은 취지의 제도이고, 환경 문제를 항상 환기 시켜주는 등의 긍정적인 역할을 하지만, 환경 보증금 자체가 경제적인 인센티브가 되기는 힘들다.

예를 들어, 평생동안 하루에 한 잔씩 일회용 컵을 사용해 라떼를 마시고, 컵은 사무실에 가져와서 버린다고 해보자. 이 때 포기하는 기회비용은 얼마일까?

50원 x 365일 x 100년 = 182만 5천원

182만 5천원은 꽤 큰 돈이지만 적어도 한 잔에 3000원 이상인 에스프레소 커피를 소비하는 사람의 평생 수입에 비하면, 별 것 아닌 비용이다. 2006년 상장사의 대졸 초임이 약 2906만원이라고 한다. 환경 보증금의 기회비용은 이 사람 수입의 0.06%에 해당한다. 상식적으로, 연봉 3천만원 받는 사람이 지하철 요금에 인색할까? 지하철 요금이 900원임을 감안할 때 과연 50원의 비용에 꿈쩍이나 할까?

물론 이 기회비용의 가치는 상대적이다. 현재의 최저 임금 시간급 3100원을 받는다고 하면 182만 5천원은 주당 40시간 기준 14주를 일해야 벌 수 있는 돈이고, 평생 벌 수 있는 돈의 0.3%나 된다. 역시 상식적으로 시간급 3100원을 받는 사람이 과연 에스프레소 커피를 마음 놓고 매일 마실 수 있을까?

대부분의 사람들이 커피전문점에서 컵을 되돌려주고 보증금을 되돌려 받지 않는 이유는 단순히 충분한 경제적 인센티브가 되지 못하기 때문이다. 50원의 귀중함도 모르냐는 식의 접근은 좀 곤란하다. 차라리 보증금을 인상해보는 것은 어떨까? 여기서 질문. 사람들은 컵을 돌려주는데 얼마 정도의 인센티브가 필요할까? 나라면? 글쎄, 200원-500원 정도? 물론, 이 정도의 인센티브도 어떤 사람들에게는 전혀 인센티브가 되지 못한다.

환경론자들은 환경을 보호하는 행위는 단기적으로도 당신에게 도움이 되는 행동이라고 얘기하는데 열을 올리지만, 몇몇 경우를 제외하고는 환경을 보호하는 행위는 추가적인 비용과 불편함을 동반하는 것이 일반적이라고 생각한다. 물론, 법적인 기반과 경제적인 제도를 사용해 사람들의 행동을 유도하는 것도 단기적으로는 좋지만, 역시 궁극적으로는 환경을 보호하는 것이 중요한 일이라는 합의를 이끌어내고 그것이 매우 자랑스러운 일이라는 의식을 가질 수 있도록 교육하는 일이 가장 중요하다.

Deposit-Refund System for Disposable Espresso Cups 더 읽기"

모든 것은 마이크로소프트 탓

이런 ‘시장 혼란’은 결국 윈도의 독점력에 따른 결과다. 다른 대안이 없는 만큼 윈도 비스타에 맞게 서비스 프로그램을 고쳐야 하는 것이다. 정통부도 ‘꼼꼼히 확인해 구매하라’는 이용자 안내에 그칠 뿐, 뽀족한 대책을 내놓지 못하고 있다.

비스타 출시에 따른 이런 혼란은 한국이 유독 심한 것으로 알려졌다. 액티브-엑스의 사용이 보편화되지 않았고 인터넷 연결이 우리나라만큼 원활하지 않기 때문이다. 익명을 요청한 정보통신부 관계자는 “지난해 3분기부터 엠에스 쪽과 공동작업을 했는데, 우리나라의 경우 응용프로그램이 발달해 손볼 대목이 많았음에도 엠에스가 기술자료 공개를 늦게 하는 바람에 이런 일이 벌어졌다”고 말했다.윈도 비스타 혼란…지금 깔면 손해, 한겨레

그렇습니다. 외국은 인터넷 연결과 같은 인프라도 미비할 뿐만 아니라, 소프트웨어가 별로 발달하지 않아서 ActiveX라는 뛰어난 기술도 아직 보편화되지 않았답니다. 게다가 마이크로소프트는 인터넷과 소프트웨어가 우월한 대한민국의 상황을 따라오지 못하고 늑장대처를 하는 후진국 기업의 행태를 보여주고 있습니다.

모든 것은 마이크로소프트 탓 더 읽기"

Next Release of IBM Lotus Notes and Domino

IBM also said the long-awaited next release of IBM Lotus Notes and Domino, known until now as “Hannover,” will enter the public beta phase of its testing in February and should be generally available mid-year. (From IBM Expands Line of Collaboration Software Tools)

IBM의 그룹웨어 솔루션인 Lotus Notes와 Domino의 차기버전 Hannover가 나온단다. Lotus Notes의 Usability는 그야말로 최악이다. (Lotus Notes Sucks) 그냥 출시안하면 안되겠니?

Next Release of IBM Lotus Notes and Domino 더 읽기"

StandardAnalyzer in Lucene, and Korean

Lucene에서 Analyzer의 역할은 Field의 텍스트를 TokenStream 즉, 토큰들의 스트림으로 만들어주는 역할입니다. 이 역할을 하는 abstract 메서드가 바로 Analyzer.tokenStream() 메서드인데, signature는 다음과 같습니다.

public abstract TokenStream tokenStream(String fieldName, Reader reader);

Lucene이 제공하는 Analyzer들에서 이 메서드의 구현은 하나의 Tokenizer와 다수의 TokenFilter들을 사용합니다. TokenizerField의 텍스트를 토큰들로 만들어주고, 이 토큰들이 TokenFilter들에 의해 변형되거나 걸러집니다. StandardAnalyzer.tokenStream() 메서드의 구현은 다음과 같습니다.

public TokenStream tokenStream(String fieldName, Reader reader) {

TokenStream result = new StandardTokenizer(reader);
result = new StandardFilter(result);
result = new LowerCaseFilter(result);
result = new StopFilter(result, stopSet);
return result;

}

일단 TokenFilter들에 대해서 설명하면, StandardFilter는 영어에서 소유격을 나타내는 apostrophe 또는 apostrophe s를 제거해주거나 acronym에서 period(.)를 제거해주는 역할을 합니다. LowerCaseFilter는 이름이 의미하듯이 토큰들을 소문자로 만들어주는 TokenFilter고, StopFilter는 지정된 stop word들을 토큰에서 걸러내는 역할을 합니다. StandardAnalyzer가 지정하는 stop word들은 StopAnalyzer.ENGLISH_STOP_WORDS로, 영어에서의 관사나 전치사, 대명사에 해당하는 단어들입니다.

결국 StandardAnalyzer의 한국어 처리에서 중요한 것은 바로 StandardTokenizer인데, 일종의 parser generator에서 생성된 것으로 보입니다. Lucene 소스에서 lucene-2.0.0/src/java/org/apache/lucene/analysis/standard/StandardTokenizer.jj를 보면, 토큰 정의들을 볼 수 있는데, 한국어와 관련해서 다음과 같은 부분이 있습니다.

// basic word: a sequence of digits & letters
<ALPHANUM: (<LETTER>|<DIGIT>|<KOREAN>)+ >

<중략 />

| < CJ: // Chinese, Japanese
[
“u3040”-“u318f”,
“u3300”-“u337f”,
“u3400”-“u3d2d”,
“u4e00”-“u9fff”,
“uf900”-“ufaff”
]
>

| < KOREAN: // Korean
[
“uac00”-“ud7af”
]
>

이것을 보면 한국어 문자들을 유니코드 범위로 표현하고, ALPHANUM이라는 토큰이 한국어 문자를 포함하도록 처리하고 있는데, 따라서, StandardAnalyzer를 사용하면, “911사태”, “Bush대통령”과 같은 것들이 하나의 토큰으로 처리됨을 알 수 있습니다. 중국어와 일본어 문자들은 CJ 토큰으로 따로 분리해놓은 반면 KOREAN은 왜 ALPHANUM으로 들어갔는지는 모르겠지만, 궁극적으로는 모든 언어의 문자들이 ALPHANUM에 들어가는 것이 정확하겠죠.

이렇게 해서, Lucene 2.0의 StandardAnalyzer에서 한국어 문자들로 이루어진 단어들이 제대로 인덱싱된다는 것은 알았지만, 이들을 이용해서 잘 검색할 수 있느냐는 다른 문제입니다. Analyzer.tokenStream() 메서드에서 돌려준 TokenStream에 담긴 토큰들을 인덱스에 그대로 저장하기 때문에, (이들을 다른 식으로 가공하기 위한 별다른 레이어를 발견하지 못했습니다.) 쿼리의 토큰들이 문서의 토큰들과 정확히 match되는 문서만 검색 결과에 포함됩니다. 즉, “Bush대통령”이라는 토큰으로 인덱스에 들어간다면, “Bush”나 “대통령”, “대통” 등으로는 이 토큰이 들어간 Document를 검색할 수 없습니다.

이 문제를 해결하기 위해서는, n-gram 분석이나 형태소 분석을 통해 토큰들을 적절하게 분리한 후, 인덱싱해야할 것입니다. lucene-2.0.0/contrib/analyzers/src/java/org/apache/lucene/analysis/cjk/에 있는 CJKAnalyzerCJKTokenizer2문자 단위로 토큰들을 생성하는 극히 단순한 Bigram 분석을 통해 이 문제를 해결하고 있는 것 같습니다. 이 경우의 문제점은 한국어에 존재하는 조사나 용언 어미등이 들어가는 토큰들을 전혀 배제하지 못하는 것인데, 검색의 품질을 상당히 낮출 가능성이 있습니다.

홍태희님은 루씬과 한글이라는 페이지(via 루씬에 대한 한국개발자의 고민들)에서 이 문제를 조사에 해당하는 부분을 토큰에서 잘라내는 TokenFilter를 도입해서 해결하고 계시긴 하지만, 조사에 해당하는 문자로 끝나는 단어들을 검색하지 못하는 문제가 있습니다.

제대로 된 오픈소스 한국어 Analyzer의 수요가 많음에도 불구하고 없는 것이 아쉽습니다. 짧은 생각으로는 단순한 휴리스틱으로는 힘들 것 같고, 충분히 많은 데이터를 이용한 분석이 필요할 듯 한데, 아무래도 오픈소스 활동에 전념하기 힘든 개인의 수준에서는 힘들지 않을까 싶군요. 좀 더 조사해 봐야겠습니다.

StandardAnalyzer in Lucene, and Korean 더 읽기"

How To Code

‘How To Code’는 팀 내에서 발표할까 생각했다가 취소한 발표자료입니다. 내용은 소프트웨어 개발에서 프로그래머가 지켜야하는, 또는 지키도록 기대되는 기본적인 원칙들 입니다. (빠진 것들도 많겠지만, 생각나는 중요한 것들만 적었습니다.)

발표 자료에 관해 잠시 언급하자면, 이 발표 자료만으로 발표하는 것은 졸린 설교가 될 가능성이 높기 때문에, 충분한 예들이 있어야 합니다. 가능하다면, 팀에서 쓴 코드를 직접 사용하는 것도 괜찮다고 생각이 됩니다.

최근에, 팀 내에서 잘 지켜지지 않는 개발 원칙들을 어떻게 바른 방향으로 유도할 것인가에 관해서 대단히 관심이 많아졌는데, 이런 원칙들만을 나열하는 것은 ‘당신이 잘못 했으니까 고치라’라는 식으로 들릴 가능성이 높고, 그렇다면 절대 변화는 일어나지 않을 것이라는 생각이 듭니다.

다른 사람들을 변화시키려면, 원칙 이전의 가치에 대한 공감대가 필요한데, 우선 그 공감대가 형성되어있는가, 또는 어떻게 형성될 수 있는가를 따져야할 것 같습니다. 공감대를 어떻게 형성할 수 있는가에 대해서는, 이러한 원칙들이 실제로 적용되는 경우를 보여주면서 그것이 좋다는 것을 ‘느낄’ 수 있도록 해주는 것이 가장 좋은 방법인 것 같습니다. 이를 위한 실제적인 방법으로 ‘코드 리뷰’를 생각 중입니다만… 여러모로 아직 고민 중입니다.

How To Code 더 읽기"

2007년 공약: 출근 시간 지키기와 운동

제가 현재 가지고 있는 나쁜 습관 중 하나는 출근 시간을 잘 지키지 않는 것입니다. 제가 현재 잘하지 못하고 있는 것 중 하나는 운동을 소홀히 하는 것입니다. 따라서, 2007년에는 이 두가지 점을 개선해보기로 했습니다. 따라서, 다음의 두가지를 2007년 공약으로 지정합니다.

  • 출근 시간 지키기
    • 30분 이상 늦는 경우를 실패로 봅니다.
  • 운동하기
    • 운동을 주기적으로 그리고, 충분히 합니다.
    • 1주일에 평균 30분 이상씩, 3일간 달성하지 못하는 경우를 실패로 봅니다.

Kent Beck의 변화 유지 비결에서 설명하는 Accountability를 위하여, 매일의 출근 시간운동 내역을 기록하고, 한달마다 요약을 이 블로그에 포스팅 하도록 하겠습니다.

‘출근 시간 지키기’ 공약의 구체적인 계획

최근에 오전 7시 30분에 일어나는 것을 실천하고 있지만, 자는 시각은 그대로이기 때문에 수면 시간이 부족합니다. 평균적으로 7시간, 적어도 6시간 수면을 취하기 위해서는, 0시 30분에서 1시 30분에는 자야합니다. 자는 것을 방해하는 모든 요소들을 제거한 후에도 자는 시각이 늦어지는 이유 중에 하나가 자기 위한 준비 때문인데, 자기 위한 준비에 30분에서 1시간 정도가 소요되므로, 적어도 자정부터는 잘 준비를 해야합니다.  잘 준비를 마친 후부터 잠이 들 때까지는 TV 시청이나 책을 볼 수 있으나, TV 시청은 자제하는 것이 바람직 해 보입니다.

‘운동하기’ 공약의 구체적인 계획

제가 좋아하는 운동이 별로 없고, 기껏해야 수영을 좋아하지만, 수영장을 다닐만한 여건이 좋지 않으므로 Fitness center가 대안으로 떠오릅니다. 하지만, Fitness center를 흥미를 유지하면서 다니는 것은 어렵고, 제게는 대단히 시간 낭비로 느껴지기 때문에, 집에다 운동 기구를 사두고 운동을 하는 방법을 생각하고 있습니다. 일주일 정도 시간을 두고 조사를 한 후, 구입할 예정입니다. 집에서 휴식을 취할 때 미국 드라마를 보는 것을 대단히 좋아하기 때문에, 운동과 함께 드라마를 본다면 좋을 것 같습니다. 운동을 매일 할 수 있으면 좋겠지만, 약속, 야근, 회식 등의 비정기적인 사건 때문에 현실적으로 불가능하고, 일주일에 3일 정도만 30분 이상 할 수 있으면 좋을 것 같습니다. 장기적으로는 일주일에 3일 이상, 하루에 1시간 이상을 목표로 하고 있습니다.

2007년 공약: 출근 시간 지키기와 운동 더 읽기"