[프로그래밍 심리학 이야기/ 조상민]
지금 필요한 건 뭐? 스피드?
좋은 소프트웨어란 무엇일까? 프로그래머들에게 이런 질문을 던진다면 어떤 대답을 할까요? 10년 전의 저였다면 이렇게 대답했을 겁니다. “가볍고 날라댕기는 놈이요.” 당시에는 메모리 적게 쓰고 속도 빠른 프로그램이 최고라고 생각했습니다. 저만 그랬던 건 아니었을 겁니다. 그리고 요즘도 효율성은 프로그래머의 주된 관심사 중 하나지요. 언제나 CPU와 메모리는 제한적이니까요. 그런데 제랄드 와인버그는 40년 전에 이미 다음의 사실을 깨닫고 있었습니다.
정확성에 비하면 효율성 등의 다른 조건은 부차적이다. 즉, 프로그램이 갖춰야 할 최고의 덕목은 요구명세를 만족시키는 것이다.
물론 아무리 요구명세를 정확히 구현한 프로그램도 속도가 너무 느린 등의 성능 문제가 있다면 사용하기 어려울 수도 있습니다. 그러나 쓸모없는 결과를 빠르게 생산해내는 프로그램은 또 무슨 소용이 있을까요? 『프로그래밍 심리학』에서 와인버그는 이와 관련된 일화를 소개하고 있습니다.
한 프로그래머가 어떤 자동차 회사에서 사용할 새 프로그램의 디버깅을 의뢰 받아 디트로이트로 출장을 가게 됐다. 그 프로그램은 천공 카드에 기록된 고객의 주문 요청 내역을 읽어, 그에 맞는 자동차를 만드는 데 필요한 부품 목록을 뽑아내는 것이었다. 즉, 차체의 다양한 옵션과 필요한 부품 간의 관계를 나타낸 명세를 구현하는 프로그램이었다. 예를 들어, ‘뒷좌석 커버’는 ‘디럭스냐 가죽이냐’는 해당 옵션과 함께 차체의 색상 및 스타일 그리고 에어컨 옵션 등에 따라 결정되는 것이다. 에어컨 옵션이 뒷좌석 커버와 무슨 상관이냐고? 에어컨을 설치하려면 배관 공간이 더 필요할 수도 있기 때문이다.
이는 이 문제에 내재된 복잡성을 보여 주는 좋은 예다. 부품 한 가지를 결정하는 것도 여러 옵션의 영향을 받는다. 따라서 주문형 생산에 필요한 부품 목록을 도출하는 작업은 딱 컴퓨터로 해야 할 일이었다.
그런데 주인공이 투입됐을 때는 이미 문제를 다룰 기본적인 접근법이 결정되어 있었다(형편없게). 각 옵션을 하나하나 개별적인 조건 분기문으로 구현했고, 따라서 프로그램은 5000여개의 가지를 드리운 거대한 의사결정나무가 됐다. 게다가 프로그래머 16명이 동시에 작업하고 있었기 때문에, 디버깅은 거의 불가능에 가까웠고 모든 경우의 수에 대해 테스트를 수행해야 했다. 주인공이 도착했을 때 프로그램의 상태는 이미 걷잡을 수 없게 되어, 평범한 옵션을 선택해도 “타이어 8개, 좌석 3개, 그리고 엔진은 없다”라는 명세 결과를 내고 있었다. 완전히 실패작이었던 것이다.
그러나 (항상 그렇듯이) 아무도 그 상황을 실패라고 말하지 않았다. 그 대신, 전 직원을 2교대로 나누어 강도 높은 디버깅 작업에 착수했고 인력도 증원했다(주인공도 이 과정에서 투입된 것이다). 당연히 상황은 더욱 혼란스러워졌고, 우리 주인공은 겨우 며칠 만에 프로젝트에 가망이 없음을 깨달아 주위의 비난을 감수하며 일을 그만두었다.
돌아가는 비행기에서 그는 일주일 만에 처음으로 조용히 사색할 여유를 가질 수 있었는데, 문득 현재의 접근법이 지닌 근본적인 문제점이 떠올랐고 작업을 두 단계로 분리하는 편이 훨씬 좋은 방법임을 직감했다. 바로, 모든 경우의 옵션 조합에 대해 원하는 결과를 미리 표로 만들어 놓고, 카드에 표시된 옵션 조합에 해당하는 경우를 그 표에서 찾아내 출력만 하면 되는 것이다. 이런 식으로 하면 최소한 ‘엔진도 없는데 타이어는 8개나 필요한’ 자동차를 만들 일은 없을 것이었다.
그 후 일주일 만에 아이디어를 프로그램으로 구현한 주인공은 전화로, 자신이 난국을 타개할 해결책을 찾았음을 회사 측에 알리고 곧장 디트로이트로 돌아갔다. 새 프로그램의 시연을 본 경영자들은 프로젝트의 회생 가능성을 발견했고, 다른 프로그래머들도 참석하는 설명회를 열도록 했다. 설명회에서 다른 프로그래머들은 냉담한 분위기를 풍기며 주인공의 설명을 듣기만 했다. 질문 하나 없이 설명이 끝나갈 즈음에 기존 프로그램의 원작자가 손을 들었다.
“당신 프로그램은 실행 시간이 얼마나 걸리나요?”
당신 프로그램이란 말을 강조하며 질문했다.
“입력에 따라 다르겠지만, 카드당 평균 10초 정도에요.” 주인공이 대답했다.
“에? 내 프로그램은 카드당 1초밖에 안 걸리는데요.” 의기양양해진 원작자가 말했다.
그때까지 뭔가 불만스러운 표정을 짓던 다른 프로그래머들이(모두 ‘1초 밖에’ 안 걸리는 프로그램 작성에 관여한 사람들이었다) 이 대화를 듣고 안도하는 듯했다. 그러나 아직 젊고 순진한 우리의 주인공은 기죽지 않고 차분하게 응수했다.
“하지만 그 프로그램은 작동하지 않잖아요. 프로그램이 작동하지 않아도 괜찮다면, 난 1000분의 1초에 카드 한 장을 처리하는 프로그램도 만들 수 있어요. 1000분의 1초면 카드 판독기에 기별이 가기도 전입니다.”
개인적으로 이 일화에서 느끼는 점이 꽤 많았습니다.
그러나 (항상 그렇듯이) 아무도 그 상황을 실패라고 말하지 않았다. 대신, 전 직원을 2교대로 나누어 강도 높은 디버깅 작업에 착수했고 인력도 증원했다.
우리는 이런 상황을 얼마나 자주 겪었거나 겪고 있습니까? 사장님은 우리가 시장을 잘못 판단했었노라고 말하지 않습니다. 시장이 우릴 몰라주고 있는 것입니다. 요구 사항을 모두 만족시키기엔 시간이 부족하다고 하면, 시간을 만들어주거나(릴리즈까지 야근 및 휴일특근 의무화) 사람을 더 쓰라고 답합니다. 답답한 노릇이 아닐 수 없죠. 그런데 어찌 보면 사장님 입장에서는 그리고 관리자의 입장에서는 달리 취할 수 있는 대책이 없을지도 모릅니다. 사실 더 큰 문제는 다음과 같은 우리 프로그래머들의 태도입니다.
그때까지 뭔가 불만스러운 표정을 짓던 다른 프로그래머들이(모두 ‘1초 밖에’ 안 걸리는 프로그램 작성에 관여한 사람들이었다) 이 대화를 듣고 안도하는 듯했다.
우리 스스로도 잘못에 대해 깨닫지 못하거나 반성하지 않거나 회피하려 하는데, 다른 누구를 탓할까요. 예전에(루키 시절에) 한 눈에 보기에도 너무 부정확하고 비효율적인 코드를 발견해 담당자(선배)를 찾아가 문제점을 지적하고 대안을 제시했더니, 바로 이런 대답이 돌아오더군요.
“그래? 그럼, 네가 직접 하세요.”
그 선배가 어떤 표정으로 저런 대답을 했는지는 여러분의 상상에 맡깁니다. 그런데 이 문장을 써놓고 보니, “지금의 난 어떤 선배일까?”라는 의문이 뇌리를 스치는군요.