Extremely Agile/General2009.01.21 23:51
보통 프로그래머들에게는 한가지씩의 무용담이 있습니다. 그 중 가장 흔한 것이 바로 "내가 만났던 가장 개같은 버그" 류의 무용담입니다.

이런 이야기는 왜 하는 것일까요? 뭐 다들 잘 아시겠습니다만, (1) 이런 무용담이 많으면 어디가서 분위기를 띄우기 좋고 (2) 자기가 경력이 꽤 된다는 걸 간단하게 입증해 보여줄 수 있으며 (3) 다른 프로그래머에게 유용한 정보를 전해줄 수 있다는 장점이 있습니다. 물론 이런 이야기는 '군대에서 축구한 이야기'랑 비슷하기 때문에, 프로그래머들이 둘 이상만 모이면 저절로 튀어나오게 되는 경향도 있긴 합니다. ^^;

프로그래밍 심리학이라는 책에도 나옵니다만, 천공 카드를 통해 프로그래밍을 했던 중세시대에도(ㅋㅋ) 소위 '개발자 커뮤니티'라는 것이 있었습니다. 천공 카드를 컴퓨터에 입력하려면 순번을 기다려야 하니까, 기다리면서 노가리들을 깠던 것이죠. 인터넷이 없었으니 당연했겠죠? 그 시대의 개발자들은 아마 지금 개발자들에 비해 백배는 수다스러웠을 겁니다.

각설하고... 그런데 버그에 관한 그런 무용담들을 들어보면, 보통 '버그를 잡았다'에서 스토리가 끝나버려요. 그 뒤의 이야기들은 좀체로 하질 않습니다. 오늘도 커피를 마시러 휴게실로 가다가 같이 일하는 분들하고 잠시 이야기를 할 기회가 있었는데요. 개발자를 한달간 애먹인 버그에 대해서 들려주시더군요. 관련된 모든 사람들의 영혼을 한달동안이나 잠식했던, 정말 가공할만한 버그였습니다. (가장 큰 문제는 그 버그가 그분들이 개발한 시스템에서 나온게 아니라는 점이었죠.) 듣는 제가 다 소름돋을 정도였으니....

보통은 거기까지 듣고 마는데, 오늘은 제가 이런 질문을 한번 해봤습니다.

"그런 버그를 한 번 겪고 나면 본인이 어떻게 달라졌다고 느끼나요?"

질문을 좀 뜨악하게 들으시는 것 같아서 좀 다르게 물어봤습니다.

"그런 버그가 (프로그래머로서의) 자신의 인생을 바꿔 놓았다고 느낄 때가 있나요?"

생뚱맞게 들리실수도 있겠습니다만, 저는 이런 질문을 한번쯤은 던져 보아야 하지 않나 합니다. 제가 이 직장에 처음 들어왔을때 처음 맞닥뜨린 가장 심각했던 'UNDETERMINISTIC' 버그[각주:1]는 시그널 핸들링 관한 것이었습니다. 시스템이 죽긴 죽는데, 진짜 어쩌다 한번 죽는 겁니다. 그리고 그 상황 사이의 일관성을 찾기가 정말 힘들었어요.

이 문제의 해결책을 찾기 위해 정말 많은 삽질을 했습니다. (지금 생각하면 삽질이 아니라 당연하게 해야 하는 일들이지만요.) 첫 번째로 했던 일은 메모리 누수가 시스템의 crash로 이어지는 시점을 정확하게 동기화시키기 위해 MALLOC_CHECK_ 환경 변수의 값을 설정하는 것이었습니다. (Linux라면 man malloc하시면 관련 자료가 나올 겁니다.) 처음에는 시스템이 죽는 이유가 메모리 누수 때문이 아니었을까 하고 추측했거든요. (그당시에는 valgrind에 대해서 몰랐습니다.)

물론 그래도 문제가 해결이 안되었습니다. 한달 뒤에야 겨우 문제의 실마리를 찾을 수 있었죠. (쪽팔립니다ㅎㅎ) 문제인즉슨 이런거였습니다. write를 할 때 리턴 값으로 '파이프가 깨졌다'는 오류 메시지를 받을 수 있을 것으로 기대했었는데 (write를 하는 중에 서버가 죽을 경우를 대비하려던 거였죠) 문제는 그게 SIGPIPE 시그널을 block 하지 않으면 제대로 동작하지 않고 프로세스가 죽는다는 거였습니다. (그것도 꼭 항상 죽는건 아니었죠. ㅋㅋ)

이 문제의 교훈은 이런 거였습니다. 매뉴얼에 의존해서 그대로 몇 줄 코드를 구현했습니다. ('상대 프로세스가 죽을 경우 내 프로세스는 파이프가 깨졌다는 오류 메시지를 받는다'는 것이 매뉴얼 내용이었습니다.) 그런데 그 코드가 정말로 제대로 동작하는지는 확인을 하지 않았던 겁니다. '몇 줄'에 불과하고, '매뉴얼 대로' 구현했기 때문에, 거기 버그가 숨어들어갈 거라고는 생각을 못했던 것이죠.

이 문제를 '기계적'으로 해결하려면, 작은 수정을 가할 때 마다 그 수정이 정말로 올바른지 확인을 하고 넘어가야 했습니다. TDD 수준으로 보폭을 좁게 가져가는 것이 필요하다는 결론을 그 때 얻은 거죠. 이 결론을 실천해 볼 기회는 2년 뒤에 찾아왔습니다. 일단 모든 코드의 구현을 마친 뒤 (테스트 과정에서 설계가 변경될 수 있다는 가정은 일단 배재했기 때문에 그럴 수 있었습니다. 코드에 확신이 있기도 했고, 사실 무식할 때 가장 용감해지는 법이니까요), 시스템의 아주 작은 부분부터 차례로 테스트를 해 나기가 시작했습니다. 테스트를 마친 코드만을 조금씩 시스템에 포함시켜서 빌드를 해 나가기 시작했고, 그 부분이 제대로 시험되었다는 확신이 들 때메만 다음 코드로 넘어갔습니다. 이런 식으로 해서 결국 연동시험 때 발견된 버그 수를 0으로 낮출 수 있었습니다. 테스트에 CppUnit을 도입한 것, TDD를 공부한 것, '한 걸음을 뗄 때 마다 뒤돌아보기'에 대한 확신이 생긴 것 등이 그 시기에 했고 느꼈던 것들입니다. (지금 생각하면 '책 한 권만 잘 읽었어도 더 잘 할 수 있었을텐데' 하긴 합니다만.)

결국, '그 자그마한 버그 하나'가 저를 바꿔놓은 것이죠. 이 블로그도 그 덕에 생겼습니다. ^^;

많은 개발자들이 Continuous Integration이나 Issue Tracking의 필요성에 대해 공감은 하면서도 실제 도입을 망설이는 이면에는 '버그는 부끄러운 것'이라는 개발자적 자존심이 어느 정도 깔려 있다고 저는 생각합니다. 그런 부분을 해소할 수 있으려면, 버그 자체도 지식으로 대우하는 자세가 필요합니다. Bug Tracking이라는 말 대신 Issue Tracking이라는 다소 점잖은 용어가 널리 쓰이는 것도, 어쩌면 그래서일지도 모르겠어요.

버그가 나를 더 좋은 곳으로 데려갈 수 있다는 확신을 가지는 것은, 그런 의미에서 중요하다고 생각합니다. 여러분도 저처럼, '나를 바꾼 버그'를 하나씩 가지고 계신가요?

  1. reproduce하기 굉장히 난감한, 발현 시점을 도무지 정확히 알 수 없는 버그. [본문으로]
신고
Posted by 이병준

소중한 의견, 감사합니다. ^^

  1. 공감하고 갑니다. ^^

    2009.01.29 02:40 신고 [ ADDR : EDIT/ DEL : REPLY ]
    • 아. 안녕하세요? 제가 블로그 첨 열었을 때 A2님 블로그에서 X-note에 리눅스 설치하는 방법을 참고했던 기억이 나네요. 새해 복은 많이 받으셨는지? 올해도 건승하시길~

      2009.01.29 09:11 신고 [ ADDR : EDIT/ DEL ]
  2. 정말 공감가는 글입니다. 저는 아직 인생까지 걸어보진 못했지만 잡아내는 버그 한두개로 소프트웨어 자체를 fail 시켜야 한다는 점에서는 거의 매일 누구에겐가는 운명적인(?) 버그를 잡아낸다고 해야하나요. 하지만 더 열심히 한다면 언젠가는 저도 제 인생을 바꿀만한 버그를 잡아내는 날이 오겠죠? ^^; 어쨌든 이젠 돌다리를 두들겨만보고 건너는 버릇은 아예 없앴습니다. 뛰어보고 엎어보고 발로 차보고 긁어보고 맛도 본 후에나 건너게 되더군요.

    2009.03.26 13:00 신고 [ ADDR : EDIT/ DEL : REPLY ]

Extremely Agile/TDD2008.11.04 15:34
FindBugs라는 프로젝트가 있습니다. 코드의 정적 분석을 통해 코드에 내재된 버그를 찾는 솔루션을 만드는 프로젝트입니다.

많은 개발자들이 정적 분석을 통한 버그 탐색 방법을 도외시하는 경향이 있습니다만, 개발자들도 사람이니 '바보같은' 실수를 저지르게 되어 있기 마련이라는 점을 감안한다면, 짝 프로그래밍이나 코드 리뷰가 버그를 많이 줄여준다고 하더라도 그런 미련한 버그들이 코드에 뒤섞이는 것을 100% 방지할 수는 없습니다.

정적 분석 (static analysis) 방법이 그런 버그를 찾을 수 있게 도와준다면, 사용하지 않을 이유는 없어 보이는데요. 다행히 FindBugs 프로젝트는 Eclipse나 Netbeans 같은 IDE상에서도 사용할 수 있을 정도로 성숙되었고, 많은 분들이 쓰고 계십니다.



이 프로젝트 URL은 http://findbugs.sourceforge.net/ 입니다. 논문도 꽤 나온 것 같은데, 재미있어 보이네요. (아직 읽어보진 않았습니다.) Lesser GPL로 배포되고 있으니, 상업적 프로젝트에도 무리없이 적용 가능할 것 같습니다.

참고할만한 다른 링크들 :

http://benelog.egloos.com/2079841 - FindBugs + Maven 2 + Hudson
http://findbugs.blogspot.com/ - FindBugs 공식 블로그
http://findbugs.sourceforge.net/bugDescriptions.html - 버그 패턴 설명
http://www.ibm.com/developerworks/kr/library/tutorial/j-cq11207/index.html - 지속적 통합과 결함 발견
신고
Posted by 이병준

소중한 의견, 감사합니다. ^^

  1. 동영상 내용 많이 도움이 될 것 같네요. 제 블로그의 포스트에서도 이 포스트에 링크를 걸었습니다~ 잘 봤습니다.

    2009.01.24 07:09 신고 [ ADDR : EDIT/ DEL : REPLY ]

Languages/Erlang2008.04.23 14:06

Erlang 웹사이트에 가서 GS 사용자 가이드를 다운받아 GUI 관련 프로그래밍을 Erlang으로 해 보고 있었는데요. 이거 조금 문제가 있군요. ㅋㅋ Linux에서는 잘 되는 예제가 Windows에서는 좀 이상하게 실행됩니다. 이렇게 되면 Windows 환경에서 GS를 사용해서 프로그래밍하는 것이 좀 어려워 질 수도 있겠군요.

GS 사용자 가이드 chapter 1의 예제 15번입니다. 다음과 같은 GUI를 화면에 그리는 것이 목적입니다.

사용자 삽입 이미지


그런데 이 예제를 Windows에서 실행하면 제대로 되질 않습니다. 왜 그런가 봤더니, 텍스트의 Width와 Height가 전부 똑같이 계산되더군요. 다음과 같이 출력됩니다. Rectangle 크기가 전부 동일하게 계산되는 바람에, 글자 주변에 사각형을 제대로 그릴 수가 없네요. Windows 환경에서 실행되는 gs:read(name, {font_wh, {Font, Text}}) 함수에 버그가 있는 것 같습니다.

사용자 삽입 이미지

화면 캡처도 이상하게 되는군요. ㅋㅋ

신고
Posted by 이병준
TAG Erlang, gs, 버그

소중한 의견, 감사합니다. ^^

  1. 오.. 네트워크에 강한 erlang 공부하시는군요. 행복해 보입니다. 자기가 하고 싶은 것을 한다는 것 말이에요.

    2008.04.28 10:23 신고 [ ADDR : EDIT/ DEL : REPLY ]
    • 그렇게 봐 주시니 감사합니다. 그런데 제가 요령이 없어서 그런지 공부하기가 쉽지 않네요. ^^;

      2008.04.28 13:23 신고 [ ADDR : EDIT/ DEL ]