프로그램을 만들다 보면 반드시 남이 만든 프로그램을 사용하게 되지요. 그리고 남이 만든 프로그램을 사용하면, 예상치 못한 일을 겪기도 합니다. 알 수 없는 오류로 프로그램이 다운되고, 저장했던 내용이 사라지기도 하죠. 심하게는 운영체제를 다운시키기도 합니다.
프로그래밍의 대가라고 할 수 있는 브라이언 커니핸과 롭 파이크조차도 당연히 비슷한 경험을 많이 했고, 이런 경험에서 배운 것들을 잘 다듬어 『프로그래밍 수련법』이라는 책으로 묶어냈다고 합니다.
저자들이 어떤 경험을 했는지 궁금하지 않으세요? 여기 그 ‘경험’을 소개합니다. 『프로그래밍 수련법』의 원서 홈페이지에 올라온 ‘무용담(A war story that didn’t appear in the book)’이라는 글을 브라이언 커니핸의 동의하에 김정민 님께서 번역해 주셨습니다.

ps. 인사이트 블로그를 방문하시는 분들도 『프로그래밍 수련법』을 읽으며 생각나신 무용담을 트랙백으로 남겨보는 건 어떠세요? 배운 점을 돌이켜보는 기회가 될 겁니다. (혹시 압니까? 옛말에 트랙백 잘 남기면 자다가도 떡이 생긴다고 하던데… ^^)

무용담(A war story that didn’t appear in the book)

이 글의 원전은 Addison-Wesley 출판사의 『Innovations』 잡지다.

프로그래머들이 사교활동을 할 때는 상대방을 즐겁게 하기 위해 ‘무용담(武勇談, A War Story)’, 즉 컴퓨터나 프로그램의 흥미로운 문제나 대실패에 관한 재미있는 비화를 얘기한다. 이런 이야기는 프로그래밍 분야에서 쌓여온 집단 지성의 일부이자, 소프트웨어에 적용하는 좋고 나쁜 엔지니어링의 교훈을 함축한 짧은 우화이기도 하다. 우리가 『프로그래밍 수련법』을 쓴 이유 중 하나는 이런 이야기들을 다시 언급하여, 거기에 담긴 경험을 전달하기 위해서였다.

여기에 책에 미처 넣지 못한 무용담을 하나 싣는다. 그리 오래지 않은 과거, 우리는 ‘단말 에뮬레이터’라는 상용 프로그램을 사용하고 있었다. 이 프로그램은 윈도 안에 명령 해석기나 텔넷(telnet) 세션을 띄울 수 있는 전통적인 단말기를 시뮬레이션 해준다. 기본적으로 이 에뮬레이터는 화면 위쪽으로 넘어가 버린 텍스트를 저장하지 않지만, 내버려두면 날아가는 이 텍스트를 저장해둘 수 있게 ‘버퍼’ 줄 길이를 지정하는 옵션 메뉴를 두었다. 그때 우리는 이 프로그램을 사용해 아주 큰 파일을 읽으려고 했다. 그래서 메뉴에 가서 버퍼 길이를 세 자리 필드에 들어가는 가장 큰 값인 999로 지정했다. 확인 버튼을 클릭한 순간, 윈도 창이 사라져버리고 제목표시줄만 남았다! 명백히 이 프로그램에는 버그가 있었다. 큰 값을 받아들이긴 했지만 제대로 처리하지 못한 것이다.

이 옵션 메뉴를 활성화할 수 있는 버튼 자체가 사라져 버렸기 때문에 버퍼 크기를 다시 고칠 수 있는 방법이 없었지만 우리는 윈도 창을 다시 보고 싶었다. 그래서 제목표시줄에 있는 닫기 버튼을 클릭해서 일단 윈도를 닫았다.

이런 사태가 있었지만 그래도 계속 써보려고 다시 프로그램을 기동했다. 아뿔싸, 이 프로그램은 영구적 저장소에 이 큰 버퍼 길이 값을 저장해버린 것이다. 그래서 새로 띄운 인스턴스도 제목표시줄만 나왔다. 그냥 파일 하나를 읽으려던 것이 이제 골치 아픈 디버깅 문제가 돼 버렸다. 어떻게 해야 프로그램을 다시 되돌릴 수 있을까?

버퍼 크기를 저장한 파일을 찾아서 리셋할 생각으로 파일의 위치를 찾는 데 많은 시간을 들였지만 결국 성공하지 못했다. 프로그램의 데이터에 접근하기 위해 매개변수에 대한 별도 인터페이스를 쓴다거나 하는 다른 방법을 찾아봤지만, 그것도 역시 소용없었다.

그때 깨달았다. 윈도 자체의 텍스트를 화면에 표시하는 코드가 문제일 가능성이 높기 때문에, 보이진 않더라도 찾아낼 수만 있다면 옵션 메뉴는 제대로 동작할지도 모른다. 그래서 신중하게, 체계적으로 제목표시줄 아래부터 시작해 마우스를 클릭해나갔다……. 아하! 드디어 옵션 메뉴가 떠올랐다. 그제야 버퍼 크기를 고칠 수 있었고, 프로그램은 바로 스크린에 떠올랐으며 우리는 일을 계속할 수 있게 되었다.

이 작은 모험을 겪고 나서 프로그램 매뉴얼을 읽어봤더니, 유효한 버퍼 크기가 최대 399줄까지라는 것을 알 수 있었다. 좀 더 실험을 해봤다. 이제 프로그램을 되돌릴 수 있는 방법을 아니까 말이다. 과연 399줄은 잘 동작한 반면, 400줄을 넣자 윈도가 사라져버렸다.

좋은 프로그래밍 무용담(programming war story)이 다 그렇듯이, 우리의 작은 모험에도 교훈이 있다.

이 바보 같은 버그를 우리가 찾아내는 데 걸린 시간에 비해, 고치는 데는 훨씬 적은 시간이 들었을 것이다. 다른 사용자들이 얼마나 많은 시간을 낭비해왔는지 그 누가 알겠는가? 유효한 입력값에 대한 단순한 검사를 넣는 정도의 훨씬 적은 노력만 들였어도 예방할 수 있는 문제였다. 소프트웨어를 올바르게 개발하는 것이야말로 문제를 방지하는 가장 좋은 방법이며, 올바르게 한다는 것의 가장 중요한 부분 중 하나는 잘못된 입력값에 대한 방어다.

게다가 이 프로그램은 철저하게 테스트되지도 않았다. 코드를 테스트하는 효과적인 방법 중 하나는 태생적 경계에서 실험하는 것이다. 이 프로그램의 제작자는 399와 400이 경계값임을 알고 있었을 게 틀림없다. 399는 가능한 버퍼값 중 가장 큰 값이고, 400은 유효하지 않은 값 중 가장 작은 값이니 말이다. 만약 프로그램에 문제가 생긴다면 이 값 중 하나나 0과 1 같은 작은 값에서 문제가 생길 가능성이 높다. 코드를 작성하는 도중에 이런 경우를 테스트해 보기는 쉬운 일이다.

하지만 소프트웨어에 버그가 있을 때, 그것을 찾아서 고치는 방법은 많다. 디버깅은 가능성을 좁혀가고, 문제를 발생시키는 중요한 입력값을 찾아내고, 그 문제와 관계없는 것들을 지워가는 과정이다. 각 디버깅 작업은 어떤 가설을 테스트하는 실험이다. 이 사례는 우리에게 소스코드가 없었고, 에러 증상이 바로 화면이 사라져버리는 증상이었기 때문에 해결이 어려웠던 것이다.

프로그램은 정상적으로 행동해야 하며, 그래서 일반적인 애플리케이션이라면 별도의 매뉴얼 없이도 사용할 수 있어야 한다. 이는 특히 그래픽 인터페이스가 있는 프로그램, 즉 아무도 도움말을 읽지 않는 프로그램에 잘 들어맞는 말이다. 이 프로그램은 버퍼 크기에 제한을 두지 않게 할 수도 있었고(제일 사용하기도 쉽고 매뉴얼도 필요하지 않다), 입력 필드 근처에 ‘최대 399까지’라는 안내문을 붙여놓을 수도 있었으며(필요한 순간에 매뉴얼을 볼 수 있게), 너무 큰 값은 최대값으로 자동 변환할 수도 있었고(조용히 한계값을 적용한다), 입력값을 검사해서 값이 유효하지 않을 때 대화상자를 띄울 수도 있었다(짜증은 나지만 어쨌건 잘 작동한다). 이 중 어떤 방법도 잘못된 입력을 갖고 그냥 진행시키는 것보다는 분명히 낫다.

우리는 모두 실수를 저지른다. 무용담은 그 실수에서 배우는 방법을 알려준다. 『프로그래밍 수련법』에서 세워둔 많은 원칙은 여기에서 설명한 것 같은 많은 프로그램들과의 전투에서 뽑아낸 것이다. 이 원칙들을 따른다면 다른 사람들의 경험을 더 나은 소프트웨어 개발에 활용할 수 있을 것이다.