The Last Mind

Captain's Log

Monthly Archives: September 2008

IIR Chapter 19-21

30 September 2008 by Joseph Jang

몇몇 가벼운 기술 서적들을 읽다가, 다시 IIR을 들어 Chapter 19-21을 읽었습니다.

  • Chapter 19 Web search basics
  • Chapter 20 Web crawling and indexes
  • Chapter 21 Link analysis

이제 Chapter 13-18을 읽을 차례군요.

Comments Off | Categories: Software Development

Equality conditionals like if (BAR == foo)

25 September 2008 by Joseph Jang

내가 싫어하는 코딩 스타일 중의 하나가 바로 다음과 같은 코딩 스타일이다.

if (BAR == foo) {
// whatever..
}

Java에서는 다음과 같이 쓰기도 한다.

if (BAR.equals(foo)) {
// whatever..
}

원래 이러한 코딩 스타일은 if 문 내에서 의도하지 않은 assignment가 일어나는 것을 방지하기 위한 것이다.

// XXX: assignment not intended
if (foo = BAR) {
// whatever..
}

Java의 경우에는 NullPointerException (이하 NPE)을 방지하기 위한 목적도 있다고 한다.

// XXX: when foo is null, throws NPE
if (foo.equals(BAR)) {
// whatever..
}

일단, 이런 스타일을 싫어하는 첫 번째 이유는 읽기가 힘들다는 것이다. ‘if foo is BAR’는 내 마음의 회로에서 바로 처리가 되지만, ‘if BAR is foo’는 위화감이 있다. 아마도 언어적인 이유이거나 (an student is not me?) 수학식을 읽는 방식 (when pi is x?) 을 기대하기 때문이라고 생각한다.

두 번째 이유는 이러한 스타일을 사용함으로써 얻으려는 이익은 다른 방법으로도 얻을 수 있기 때문이다. 단순히 잘못된 방식이라는 것이다.

일단 conditional에서의 의도하지 않은 assignments를 방지하기 위해서는 이미 오래 전부터 컴파일러가 보여 주고 있는 경고 (warning) 메시지를 이용하면 된다. 게다가 프로그래밍에 익숙해 지면 저런 실수는 흔치는 않은 일이 된다.

NPE의 방지는 방어적인 프로그래밍의 입장에서 일견 설득력이 있어 보이지만, Java의 스타일을 해치고, 결과적으로 오류 가능성을 감추어서 견고한 코드로 만드는 길을 막는다고 생각한다.

일반적인 프로그래밍에서 nullity는 말 그대로 invalidity를 의미하고, Java에서는 이러한 의미를 잘 살려서 코딩 할 수 있다.

Case 1

Foo foo1 = new Foo();
assert foo1 != null;
foo1.bar();
Foo foo2 = getValidFoo();
assert foo2 != null;
foo2.bar();

foo1과 foo2의 경우가 바로 그런 경우다.

foo1의 경우 Java의 new 키워드를 통해 valid하다는 것 즉, null이 아니라는 것이 보장된다.

getValidFoo()는 항상 valid한 Foo instance를 돌려준다라는 의미를 가지고 있다. 만약 getFooValid()가 null을 돌려준다면 assertion failure나 NPE가 발생할 것이다. 하지만, 그것은 getValidFoo()의 오류이므로, getValidFoo()를 사용하는 코드에서는 이 점을 무시할 수 있다. 그리고, getValidFoo()에서 제대로 Foo instance를 돌려줄 수 없는 상황이라면 exception을 throw할 것이다.

우리는 모든 코드에서 모든 변수의 validity를 체크할 수 있지만, 우리는 단순히 그렇게 하지 않는다. 만약 그렇게 한다면, 그것은 편집증 환자의 코드로 보일 뿐이다. 좋은 프로그래밍 언어는 그렇게 하지 않아도 되도록 하는 여러 장치들(new keyword, types, exception, assertion, …)을 가지고 있다.

만약 getValidFoo()가 믿을 만 하지 않아서 불안하다면 assertion을 사용해 명시적으로 오류를 발생시키면 된다.

Case 2

Foo foo3 = getFoo();
if (foo3 == null)
throw new RuntimeException("foo2 is null");
assert foo3 != null;
foo3.bar();

getFoo()가 semantic 상으로 null을 돌려줄 수 있을 경우가 있다. 이 경우 우리는 foo의 메서드를 호출할 예정이고 이후로도 다른 처리를 해야 하므로, 명시적으로 nullity 체크를 해서 적절한 처리를 하면 된다.

nullity는 위에서 얘기 한대로 invalidity를 의미하므로 이러한 상황에 대해서는 어떻게 대처할지 미리 준비가 되어 있어야 한다. 단순히 if (foo.equals(BAR))로 해결되었다고 착각하는 것은 위험하다. 그러한 코드가 invalidity 상황을 해결할 수 없다는 것이 아니다. 이러한 코딩 스타일이라는 것은 곧 invalidity 상황에 대해서 무시하는 습관을 들이는 것이랑 같다는 것이다.

한편, Case 1의 getValidFoo() 처럼, 원래의 의미는 validity를 보장해야 하나 실제로 그렇지 않을 경우, 안정성을 보장해야 하는 상황에서, 치명적인 결과를 가져오는 것이 걱정된다면, Case 2로 처리하라. 명시적으로 invalidity 상황을 처리하지 않고 위와 같은 코딩 스타일로 해결하고자 하는 것은 단순히 게으른 것이다.

Case 3

Foo foo4 = getFoo();
if (foo4 == null || foo4.equals(BAR) != true) {
// do A
}
else {
// do B
}
Foo foo5 = getFoo();
if (BAR.equals(foo5)) {
// do B
}
else {
// do A
}
// XXX: possible to throw NPE
foo5.bar();

마지막으로, foo4의 nullity가 invalidity라고 보기 힘든 경우가 있다. value object일 경우가 많을 텐데, 이 경우 null인 경우는 foo4의 상태 중 하나일 뿐인 것이다. 이 경우만이 겨우 위의 코딩 스타일이 약간이나마 빛을 발하는 경우라고 볼 수 있는데, 약간의 코드를 절약할 뿐, 충분히 명시적이지 못한 코드라고 생각한다. 만약 단순히 equality test만 있는 것이 아니라 메서드 호출도 필요한 상황이라면 실수할 여지가 있다.

이러한 경우라면 Null Object 패턴을 활용해 보라고 조언하고 싶다.

Foo foo6 = getValidFoo();
assert foo6 != null;
if (foo6.equals(BAR)) {
// do B
}
else {
// do A
}
foo6.bar();

즉, null 값으로 invalidity를 표현하지 말고 이를 표현하기 위한 객체를 만드는데, 이렇게 되면, null 값이 다시 invalidity를 의미하게 되므로, Case 1 또는 Case 2와 같은 방식으로 처리하면 된다. 그리고, 훨씬 Java 언어에 자연스러운 스타일이 될 것이다.

Closing

프로그래밍에 있어서 nullity 문제와 같이 사소한 코딩 상의 버그를 발생시키지 않는 비결은 의도를 발생할 수 있는 모든 경우를 명시적으로 처리하는 것이다. 코너 케이스들을 대충 해 놓는 경우들이 자주 보이는데 , 결국은 자신 또는 누군가가 그에 대한 비용을 치르게 될 것이란 점을 기억하라고 조언하고 싶다.

Comments | Categories: Software Development

COUNT() in MySQL

23 September 2008 by Joseph Jang

MyISAM을 쓰던 시절에는 당연히 COUNT(val) 보다는 COUNT(*)을 써야 한다는 조언을 들어왔는데, InnoDB에서도 그렇게 해야 하는가는 약간 혼란스러운 문제였다.

Peter Zaitsev의 결론은 대부분의 경우, COUNT(*)를 사용하는 것이 좋다라는 것이지만, 역시 의도에 따라 정확하게 사용하는 것이 가장 바람직하다.

MySQL 5.0 Reference Manual에 따르면, COUNT()의 정확한 의미는 다음과 같다.

  • COUNT(*): SELECT문에 의한 결과 row들의 개수. (NULL 여부에 상관없음.)
  • COUNT(expr): SELECT 문에 의한 결과 row들 중 expr의 non-NULL 값의 개수.
  • COUNT(DISTINCT expr): 서로 다른 non-NULL 값들의 개수.

MyISAM은 테이블마다 row 개수에 대한 카운터를 가지고 있고, 이 카운터의 이점을 얻으려면 COUNT(*)를 사용하라는 조언이 자주 제시되었는데, COUNT()의 정확한 의미를 알고 나면 이러한 조언의 근거를 알 수 있다.

즉, COUNT(*)는 단순히 row들의 개수를 의미하기 때문에, row 개수에 대한 카운터를 사용할 수 있지만, COUNT(expr)은 non-NULL 값의 개수를 의미하기 때문에, 만약 expr이 NOT NULL constraint를 가진 필드가 아니라면, row 개수에 대한 카운터를 사용할 수가 없다. (물론, NOT NULL constraint를 가진 필드라면 그렇지 않다.)

MyISAM의 row 개수 카운터는 매우 유용하지만, 매우 한정된 쿼리, 즉 전체 row들의 개수를 얻는 데에만 사용할 수 있을 뿐이다.

Update: 오늘 낮에 InnoDB의 구조에 따른 COUNT() 성능에 관해 남세동 팀장님과 이야기를 나누었는데, 집에 돌아와서 실험을 해보니 InnoDB에서는 COUNT()의 쿼리 플랜이 MyISAM의 경우와 확실하게 다른 것으로 보인다. 실험 결과는, 한마디로 하자면, Index가 존재하는 경우에는 Index를 활용하는 쪽으로 플랜이 만들어 지는 것 같다. 정확한 결과는 다음 포스팅에…

Comments | Categories: Software Development

미국 헌법과 인권의 역사

16 September 2008 by Joseph Jang

미국 헌법과 인권의 역사, 장호순 지음, 개마고원

우리가 현재 당연하다고 생각하며 누리고 있는 기본권의 혜택들이, 실은 20세기 초에도 제대로 확립되지 않았다는 사실은, 보통 사람들에게는 의외로 잘 알려지지 않은 사실이다.

대한민국이 근대적인 헌법을 기초한 것은 1948년의 일이고, 사회적인 논의나 합의의 과정을 거쳐서 만들어진 것이 아니라, 주어진 것이나 다름없는 헌법이었기 때문일 것이다. 그렇다고 해서, 현대의 미국이나 유럽의 정치사를 접할 기회가 많이 있었던 것도 아니기 때문일 것이다.

일단 나만 해도, 고등학교 교육과정에서도 역사 과목이라고는 ‘국사’ 밖에 없었으며, 공과대학이었던 대학교에서도 ‘한국 근현대사’, ‘정치학’ 정도 수준이 다였기 때문이다.

‘정치학’ 수업에서 본 비디오를 통해 막연히, 영국이나 미국은 오랜 민주주의의 전통을 가진 정치 선진국이라는 이미지를 가지고 있었는데, 처음으로 이러한 이미지가 깨어지기 시작한 것은, ‘포레스트 검프’나 ‘미시시피 버닝’, ‘말콤 X’ 등의 영화를 보면서 알게 된, 남북전쟁 이후에도 지속된 백인들의 강력한 유색 인종 차별이었다. 여성투표권이 주어진 것도 20세기의 일이라는 것은 가히 충격적이었다.

그렇다면, 20세기 동안 무슨 일이 있었기에, 미국 시민들은 현재와 같은 권리를 누리고 있는 것일까? 그동안 미국의 사법제도를 다룬 글이나 책 (미국 헌법과 민주주의)을 통해 약간씩은 알게 되었지만, 미국의 역사를 제대로 알지 못하기 때문에, 내 질문에 초점이 맞춰진 이 책을 가벼운 마음으로 고르게 되었다.

이 책에서는 현재 우리나라의 헌법재판소의 지위에 해당하는 미국의 최고 사법 기구인 연방대법원들의 주요한 판례를 중심으로, 우리가 당연하다고 생각하며 누리고 있는 권리들, 또는 현재도 논란이 되고 있는 이슈들이 어떠한 과정을 통해 논의가 되고 결정되어 왔는가를 읽기 좋게 분야 별로 정리해놓았다.

미국 연방대법원은 역시 오랜 민주주의의 전통을 가진 나라 답게, 헌법을 초안한 국부들의 생각을 존중해, 어떤 헌법 조항이 애매할 경우, 학자들에게 그 조항이 어떠한 배경에서 나왔는지 조사를 요구하는 경우도 있다. 1948년과 1987년의 ‘주어진’ 헌법을 가지고 있는 대한민국으로서는 이해하기 어려운 문화다.

연방대법원은 이러한 헌법에 비추어 해석을 할 가치가 있을 경우에만 사안을 받아들이는데, 미국은 대한민국과는 달리 판례중심주의이고, 이에 따라 연방대법원도 기존의 판례들에 벗어나지 않고, 일관성을 지키는 것을 매우 중요시하며 보수적인 편이다. 그럼에도 불구하고, 이 책에는 기존의 판례를 뒤엎고 새롭게 인권을 보호하기 위한 해석을 내놓은 사례들이 많이 등장한다.

상식적으로, 사법의 과정에서, 정치적, 경제적, 사회적 환경과 독립적으로, 판례 (또는 법 조항의 해석)의 일관성을 지키는 것은 매우 중요한 일이고, 실제로도 미국의 법조계는 그러한 점들을 중요하게 여겼다.

그럼에도 불구하고, 백인과 유색인종 사이의 평등권 문제나, 노동시간 제한 등과 같은 당연해 보이는 문제도, 그러한 환경의 변화에 따라, 연방대법원의 판단은 180도로 달라졌다는 것을 우리는 이 책에서 볼 수 있다. 결국은 정치적, 경제적, 사회적 환경의 변화에 따라, 법의 적용도 달라질 수 밖에 없었다는 것이다. 물론 그러한 일이 자주 일어나서도, 바람직하지 못한 방향으로 일어나서도 안될 것이다. 다만, 기존 법이나 판례 등을 지키는 것만이 중요하지는 않다는 보수주의자를 일깨우는 교훈일 것이다.

판례의 일관성을 깨는 일은 당시의 사회로부터 많은 비판을 받았으며, 기득권 세력으로부터도 많은 비난을 받는다. 그로부터 수십년 후에 태어난 우리는 그러한 결정이 옳았다는 것을 알지만 (그렇게 생각하지만), 그러한 결정을 하는 시점에서 어떤 결정이 역사적으로 올바른지는 어떻게 판단할 수 있을까? 그리고, 올바른 결정을 하기 위한 사법 시스템을 확립하기 위해서는 어떠한 환경과 조건이 필요할까? 미국의 국부들에 의해 쓰여진 국가의 철학, 이를 지켜나가는 것을 전통으로 확립하기 위한 역사, 도그마와 무관하게 자유롭게 의견을 개진해 올바른 방향을 찾아나갈 수 있는 민주주의의 문화 모두가 필요한 것이 아닐까 싶다.

이 책이 다루고 있는 각각의 사안에 대해서, 사회적 분위기 뿐만 아니라, 역사적인 측면, 정치, 경제적인 사건들도 자세히 설명을 하고 있어서, 따로 찾아보지 않아도 될 정도로, 읽기가 매우 편리했다.

다음 번에는 미국의 현대사에 관한 책을 읽어보고 싶다.

Comments Off | Categories: Book

Google Chrome 사용 소감

04 September 2008 by Joseph Jang

Google Chrome을 잠시 사용해 본 느낌은 다음과 같다.

Fast (but not that fast)

내가 들어가는 사이트는 한정되어있고, 느린 사이트는 아예 들어가지 않아서, V8의 벤치마크 등에서 나타나는 Javascript 엔진의 이점을 100% 누리기는 힘든 것 같다.

실제로 빠른 것은 사실이지만, ‘빠르다’는 느낌이, 페이징이나 스크롤 방식의 차이에서도 오는 것 같다.

Convenient

Google Chrome은 나의 취향과 일치한다. 말하자면, Firefox를 처음 설치했을 때, 내 입맛에 맞도록, 설정하고, Firefox Extension들을 설치해야하는 과정들을 생략해도 된다는 점이 편리하다. 하지만, 기존의 브라우저들을 넘어서는 획기적인 개선이 있는가 하면 잘 모르겠다.

Final Thoughts – Yet Another Browser

일단, Javascript가 더욱 더 보편화 되어가고 있고, 성능 문제가 되어가고 있는 시점에서, Javascript 엔진의 성능이라는 과제를 모든 브라우저 벤더에게 던져준 것을 칭찬하고 싶다.

하지만, 성능의 개선이나, 사용자 인터페이스 개선에도 불구하고, 내겐 또 하나의 브라우저일 뿐이다.

또한, 브라우저를 사용한 작업은 단순히 브라우징에만 국한되지 않고 다양하기 때문에, Firefox의 Extension으로 인한 여러가지 이점은 버릴 수 없다.

결국, 내가 원하는 것은 Google Chrome의 이점들이 Firefox에 잘 흡수되었으면 하는 것이다.

앞으로, 주로 웹 브라우징만 하는 곳 – 내 경우엔 노트북 – 에서는 Google Chrome을 사용해 볼 생각이다. 어차피 리눅스 버전은 없으니…

Comments Off | Categories: Software