용의자 X의 헌신

용의자 X의 헌신 – 히가시노 게이고 지음, 양억관 옮김, 현대문학

추리물은 원래 좋아하는 편이지만, 책 읽는 양은 요즘 많이 줄어서, 추리 소설을 읽을 기회가 별로 없었는데, 오랜만에 눈에 띄는 소설이 있길래 골랐다.

이야기는 초반부에 독자들에게 살인 사건을 보여 주고, 이 때, 범인 (야스코)과 범행을 감추어 주기 위해 완벽한 계획을 세우는 수학자(이시가미)가 등장하며, 형사(구사나기)와 그의 물리학자 친구(유가와)가 사건을 해결해 나가는 방식이다. 초반부에서는 범행을 감추기 위한 작업, 중반부에서는 수사의 전개가 이어진다. 중반부까지 읽다 보니, 수사의 진척을 통해 범행이 거의 드러나면서, ‘유명세 치고는 시시하군.’이란 생각을 했는데, 문제는 후반부였다. 그야말로 예상치 못한 놀라운 반전이었는데, 중반까지도 평이하다고 생각했던 제목이 드디어 이해가 가던 대목이었다.

사건의 전개 상으로는 두 천재, 이시가미와 유가와의 대결 구도인데, 실제로 유가와는 이시가미의 친구이기 때문에, 유가와는 입을 다물고 묵묵히 지켜 보는 편이고, 이시가미의 역할이 많이 부각되는 편이다. 그리고, 꼭 천재적이어서 라기보다는 수학자나 물리학자의 성격이나 습관에 대한 묘사도 많이 눈에 띄는데, 흔히 그런 것과 달리, 크게 위화감은 없는 정도라서 만족스러웠다.

눈에 자주 띄는 책이라서 고른 것이었는데, 마음에 들어서, ‘히가시노 게이고’의 다른 소설, 그리고 나오키상 수상작들도 골라서 읽어 봐야겠다.

용의자 X의 헌신 더 읽기"

Crysis를 플레이하기 위한 그래픽 카드는?

Crysis의 후속편인 Crysis Warhead를 구입해서 플레이하고 있다. Crysis는 이른바 ‘크라이실사’라는 별명을 가진, 게임 발전의 한 방향인 photorealism을 극한으로 추구한 게임이다. 물론, 그만큼 요구하는 하드웨어 사양도 높은 것으로 악명이 높다. 현재 내가 보유하고 있는 그래픽 카드가 Nvidia GeForce 8800GT인데, 1280×1024 Mainstream 설정으로도 특정 레벨에서는 플레이하기가 벅찬 면이 있다.

Crysis Warhead

이 때문에 플레이 하다가 잠시 하드웨어 욕심이 나, Tech Report를 뒤져 봤다. (via the Tech Report)

Crysis를 1920×1200 해상도에서 플레이 하고 싶은 것이 내 욕심인데, 최소한의 fps라고 할 수 있는 30 fps를 내는데도 최상의 그래픽 카드가 필요하다는 것을 알 수 있다.. 그러한 최상의 그래픽 카드에 해당하는 것이 Nvidia의 GeForce GTX 280ATI의 Radeon HD 4870 로 보인다. GTX 280은 약 50만원 대, 한 레벨 아래의 GTX 260이 30만원 후반 대, 4870이 약 30만원 초반 대 정도인데, Crysis 외에는 거의 활용하기 힘든 50만원 대의 그래픽 카드는 정신이 나가지 않고서는 도저히 지를 엄두가 안 나고, 그나마 30만원 대를 노려볼 만한데, 4870 쪽이 가격 대 성능비는 나아 보인다.

눈에 띄는 최근의 그래픽 카드 시장의 경향 중 하나가, SLI나 CrossFire를 그래픽 카드 하나에 넣어버린, 이른바 듀얼 코어 GPU다. SLI나 CrossFire를 사용하기 위해서 지원하는 고가의 보드 (물론 2-3만원 정도 비쌀 뿐이지만)를 구입해야 한다는 부담이 있는데, 그런 부담을 덜어 주기 위한 것으로 보인다. 무..물론 버스를 줄여 주는 의미도 있겠지만… 어쨌든, Nvidia의 GX2와 ATI의 X2계열이 그것인데, SLI나 CrossFire 자체가 애초에 효율적이지도 않거니와, 최고 성능을 위해서도 그다지 효과적인 안은 아니어서 관심은 별로 가지 않는다.

GTX 260을 살까 Radeon HD 4870을 살까 고민하다 보니, 몇 프레임 차이 나지도 않고, 별로 높지도 않은 30 프레임을 얻으려고 과연 30만원을 들일 가치가 있을까 싶은 생각이 들어서, 그냥 현재 상태로 얼른 클리어하고, Crysis를 봉인할 생각. 한 2-3년 후에 웃으면서 Crysis를 플레이 할 날이 오겠지…

Crysis를 플레이하기 위한 그래픽 카드는? 더 읽기"

Equality conditionals like if (BAR == foo)

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

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

Equality conditionals like if (BAR == foo) 더 읽기"

COUNT() in MySQL

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를 활용하는 쪽으로 플랜이 만들어 지는 것 같다. 정확한 결과는 다음 포스팅에…

COUNT() in MySQL 더 읽기"

미국 헌법과 인권의 역사

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

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

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

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

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

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

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

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

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

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

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

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

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

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

미국 헌법과 인권의 역사 더 읽기"

Google Chrome 사용 소감

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을 사용해 볼 생각이다. 어차피 리눅스 버전은 없으니…

Google Chrome 사용 소감 더 읽기"

Empire: Total War Naval Battles

Empire: Total War는 2009년 2월 경에 릴리즈 될 Total War 시리즈의 후속편입니다.

기본적으로 실시간 전략 시뮬레이션(RTS)인 Total War 시리즈의 가장 큰 강점은 역시 실제적인 전투입니다. 스타크래프트나 C&C와 같이 가상적인 전투 유닛이 아니라 실제로 그 시대에 존재했던 보병이나 궁병, 기병이 등장하고, 일반적인 RTS에 흔하지는 않은 지형과 피로, 돌격 개념이 들어가 있습니다. 하지만, Total War는 전투 뿐만 아니라, 팩션의 통치, 외교, 무역까지도 포함하고 있기 때문에 전투만 한다고 해서 게임의 목적을 달성할 수 있는 것은 아닙니다. 게다가, 실제 역사를 배경으로 하고 있기 때문에, 역사를 좋아하신다면, 여러 재미를 느낄 수 있습니다.

Medieval II: Total War가 11세기부터 16세기 유럽의 중세시대를 다루었다면, Empire: Total War는 18세기부터 19세기에 이르는 유럽의 제국들이 형성되어가는 시대를 다루고 있습니다. 현재까지 릴리즈된 Total War 시리즈에는, 일본 전국 시대를 다룬 Shogun, 로마 시대를 다룬 Rome, 유럽의 중세 시대를 다룬 Medieval, Medieval II이 있습니다. 다음은 WW2: Total War 아니냐는 얘기들이 많이 있는데, WW2를 다룬 걸출한 게임들이 많아서 어떨지는 모르겠습니다. Total War만의 매력은 역시 중세 역사를 배경으로 한 것이 아닐까 생각이 드네요.

아시다시피, 식민지 경쟁이 불 붙던 이 시기에 역시 해상력은 국가의 우위와 향방을 결정 짓는 빼놓을 수 없이 중요한 요소였죠. 다음은 Empire: Total War에서 3D로 구현된 해전 영상입니다.

게임을 좋아하시는 분이라면, 대항해시대는 한번씩 플레이해보셨을 텐데요. 대항해시대 해전의 이상적인 모습을 Total War 시리즈에서 보게되리라곤 생각못했습니다.

다음은 Empire: Total War의 트레일러입니다.

해전만 있는 것은 아닐텐데, 영상에서 차지하는 비중을 볼 때 역시 해전에 초점이 맞추어져 있다는 느낌이 드네요. 그리고 저택인지 왕궁인지 몰라도 시민들이 횃불을 들고 진입하는 장면이 나오는데, 프랑스 혁명과 같은 장면 연출이 왕정을 공화정으로 바꾸는 형태로 가능할지도 모르겠네요. 어쨌거나 벌써부터 기대가 되니 큰일입니다.

Empire: Total War Naval Battles 더 읽기"

Ship It

Ship It by Jared Richardson, William Gwaltney

Ship It은 소프트웨어 개발에 관한 가이드라인을 담은 책이다. ‘도구와 인프라스트럭처’, ‘실용주의적 프로젝트 기술’, ‘예광탄 개발’, ‘일반적인 문제와 해결방법’의 네 부분으로 나뉜다.

‘도구와 인프라스트럭처’는 CVS 또는 Subversion과 같은 코드 저장소, 빌드의 자동화, 이슈 및 기능 추적, 테스트 자동화와 같은 이슈를 다루고 있다. 사실 이러한 도구들을 사용하라는 가이드라인은 흔히 들을 수 있는 이야기지만, 이 장의 마지막 가이드라인인 ‘실험하지 말아야 할 때’에서는 ‘핵심적인 기술을 기술 실험 대상으로 삼아선 안 됩니다’라는 중요한 교훈을 얘기하고 있다. 의욕에 찬 하지만, 경험은 부족한 개발자들이 흔히 하는 실수다.

‘실용주의적 프로젝트 기술’에서 소개하는 목록 사용은 오래 전부터 나나 내가 일하던 팀, 내 주변의 사람들이 실제로 활용하면서 훌륭한 습관임이 증명된 프랙티스다.

일일 회의나 모든 코드의 검토, 코드 변경 통지 등은 내겐 약간 적용하기 힘들어보이는 프랙티스들인데, 각각의 프랙티스는 나름의 장점들을 갖고 있다는 것에 동의하기 때문에 조금씩 적용해 볼 생각이다.

내가 맡고 있는 조직에 주간 회의를 적용하기 시작한지가 수개월 지났고, 현재는 어느 정도 정착이 되어가고 있다. 하지만, 어차피 작업이나 문제 관리를 위한 의사 소통이 매일 일어나는 것을 생각하면, 일일 회의는 의사소통이 예측 가능하게 일어나게 해주고, 때문에 효율적인 의사소통이 가능하게 해주리라 생각한다. (이는 주간 회의를 포함한 ‘정기적인 회의’의 장점일 것이다.) 하지만, 일일 회의를 시행하기 위해서는 주간 회의라는 익숙한 프랙티스를 포기해야 한다. 이와 같이, 어떤 프랙티스가 좋고, 현재의 프랙티스를 대체하자는 얘기는 너무나 쉽지만, 이것을 적용하기 위한 사람들의 지지를 얻고, 대체 과정의 비용을 줄이고, 실제로 잘 적용하는 것은 여러 고민과 많은 노력이 필요한 일이다.

코드 검토의 경우, 이 책에서는 변경을 포함한 모든 코드를 검토해야 한다고 나와있지만, 그보다 온화한 (덜 진보적인) 단계로, 새로운 모듈이나 프로그램, 시스템이 완성되었을 때, 코드 검토를 하는 프랙티스가 경험적으로는 상당히 좋았던 것 같다. 아마도 이를 코드 검토를 시작하는 팀의 마지노선으로 잡으면 될 것 같다. 코드 검토는, 이 책에서 얘기하는대로, 작은 단위로 할 수록 효율과 정확성이 높아지는데, 작은 단위로 리뷰하는 문화를 정착시키는 것은 또 다른 과제다.

현재 팀에는 기술 리더라고 할만한 사람들이 몇 명 있는데, 팀의 한 파트를 책임지고 있는 나도 그 중의 한명이라고 볼 수 있다. 간단하게 말해서, 기술 리더는 기술 업무와 관리 업무를 수행해야 하는데, 둘 다를 수행하는 것은, 한가지만을 수행하는 것에 비해 절대 쉬운 일은 아니다. 가장 중요한 책임 중 하나는 역시 우선 순위의 조정이다. 업무의 목록은 팀원들 각자가 결정할 수 있지만, 우선 순위의 문제는 항상 기술 리더의 책임이다. 요즘 내가 생각하고 있는 것은, 우선 순위 결정을 주간 보고나 주간 회의와 같은 과정에 자연스럽게 연결해 프로세스화 하는 것이다.

‘예광탄 개발’은 일반적인 애자일 개발과 얼마나 크게 차이가 있는지 모르겠고, 굳이 ‘예광탄 개발’이라는 이름표를 달아주어야 하는지 의문인데, 이 글에서는 설명을 생략하도록 한다.

‘일반적인 문제와 해결 방법’은 분류하기 힘든 가이드라인을 모아놓은 부분이라고 볼 수 있는데, 그 중 ‘불한당 개발자’에 대한 대처 방법을 다룬 항목이 흥미로웠다. 고삐를 채울 수 없는 불한당의 경우, ‘불한당의 행동을 문서화하고, 반항적 행동을 문제 삼아 해고해야 한다’는 것이다. 그리고, ‘대부분의 경우엔, 문서화 과정을 시작하는 것만으로도 충격받아 제자리로 돌아온다’라고 한다. 실제로도, 문제를 일으키는 팀원의 경우, 문제점을 지적당하면, 그 근거를 제시하라는 답이 돌아오기도 한다. 이에 대한 정당한 답변은 다른 사람에게 어떻게 얘기했는가, 어떤 예절 바르지 못한 행동을 했는가 등이 아니라, 잘 문서화된 작업 목록 뿐이다. 이런 수단이 악의적으로 사용되어서는 물론 안되겠지만 말이다. 한편, Jeff Atwood의 ‘Dealing With Bad Apple‘이란 글에서는 불한당 또는 Bad Apple은 팀 전체에 악영향을 미치며, 어떤 사람의 능력은 발전할 수 있어도 태도는 변하기 어렵다는 이유로, 빨리 제거하는 방법밖에 없다고 얘기하고 있다.

이 책 전체에서 드러나는 실용주의적 태도 – 어떤 프랙티스가 절대적으로 옳다고 주장하기 보다는 적합한 것을 적용해나가자는 태도 – 는 상당히 마음에 드는 편이다.

내용이나 태도 뿐만 아니라, 구성 면에서도, 하나의 가이드라인마다 마지막에 ‘어떻게 시작하면 될까요?’, ‘제대로 사용하고 있는 걸까요?’, ‘경고 신호’와 같은 섹션을 두어, 이 책에 나온 가이드라인을 실제로 행동에 옮길 수 있는 지침으로 활용하기 좋게 만들어져 있다.

번역은 따로 언급할 필요가 없을 정도로 잘 되어 있는 편이다. 최근에 출판되는 해외에서 유명한 기술 서적들은 평균적인 번역 품질이 예전보다는 많이 좋아진 것 같다.

Ship It 더 읽기"