[프로그래밍 심리학 이야기/ 조상민]

직업 프로그래머로서 저는 가끔 자신에게 의심을 품곤 합니다. “나는 프로일까?”

여러분은 스스로 프로라고 자부하십니까?

프로 즉, professional의 정의가 뭘까요?
사전을 찾아보면 “직업인(직업 선수)”이라는 뜻풀이가 가장 먼저 나옵니다. 그러나 우리가 흔히 말하는 ‘프로’는 ‘전문가’에 가까운 뜻입니다. 그러니 질문을 좀 더 명확히 해보겠습니다.

 

“여러분은 프로그래밍에 숙련된 전문가십니까?”

프로그래밍에 대해 얼마나 전문적이냐는 참 평가하기 곤란한 문제입니다. 다양한 평가 기준이 있을 테니까요. 그중 하나의 기준이 될 수 있는 내용을 와인버그가 『프로그래밍 심리학』에 인용한 일화를 통해 소개하고자 합니다.

 

어떤 전산과 학부생이 물리학 교수로부터 주어진 행렬의 역행렬을 계산하는 프로그램 개발을 의뢰받았다. 행렬 데이터는 테이프에 저장되어 있었는데, 그는 입출력 프로그래밍을 해본 경험이 거의 없었기 때문에 뭔가를 배울 좋은 기회라 생각하며 여기저기 조언을 구하러 다녔다. 그러던 중 자기보다 경험이 많은 선배를 만나게 됐는데…

“테이프를 읽어서 입력 데이터를 버퍼링하려고 하는데요, 어떻게 해야 하죠?”

선배는 주인공보단 좀 더 프로에 가까웠으므로 질문에 바로 대답하는 대신 반문했다.

“왜 버퍼링이 필요한데?”
“그야 물론 시간을 줄이기 위해서죠.”
“버퍼링하면 시간이 얼마나 절약될지 계산해 봤어?”
“안 봐도 비디오에요. 꽤 클 거에요. 행렬 개수가 많거든요.”
“몇 갠데?”
“정확히는 몰라요. 아무튼 많아요.”
“대충이라도, 한 백 개쯤 돼?”
“네, 그 정도요.”
“좋아. 그럼, 행렬의 크기는?”
“10 x 10이요.”

선배가 종이에 간단한 계산을 해보곤 행렬 전체를 읽는 데 1분 정도가 걸릴 거라 말했더니, 주인공은 의기양양하게 대답했다.

“거 봐요. 1분이면 너무 길잖아요?”
“그래. 그런데 아닐 수도 있어. 그 프로그램을 몇 번이나 실행시킬 건데?”
“예? 무슨 뜻이에요?”
“그러니까, 네가 버퍼링 루틴을 작성한다면 그렇게 간단한 일이 아니기 때문에 디버깅이 필요할 텐데, 그에 드는 시간이 1분은 넘을 거란 말이지. 딱 한 번만 쓰고 말 프로그램이라면, 버퍼링은 필요 없을 것 같은데?”
“제 말 뜻을 이해하지 못하셨군요.”

흥미로운 새 분야를 공부할 기회를 놓치고 싶지 않았던 주인공은 이렇게 항변했다.

“이 프로그램은 효율적이어야 한다구요!”

선배는 그 반응에 낙담했으나 다시 설득해 보려 했다. 그러나 허사였고, 다음 학기에 다시 마주쳤을 때까지도 주인공은 버퍼링 루틴을 만드는 문제에 매달려 있었다. 일을 의뢰한 불쌍한 물리학 교수는 실상도 모른 채 그 프로그래밍 문제가 너무 복잡한가 보다며 그저 기다릴 수밖에 없었다.


이 일화에서 배울 수 있는 교훈은 프로그램을 개발할 때에는 그 용도에 따라(또는 개발 단계에 따라) 적절한 수준의 노력을 들여야 한다는 것입니다. 비슷한 맥락에서 쓰이는 용어로 ‘미진한 설계 vs. 과도한 설계’가 있죠.
와인버그는 이렇게 선언합니다.

적절한 수준 이상의 노력을 들이는 건 차라리 그 이하로 작업하는 것보다 더 프로답지 못하다. 프로그래머가 일을 잘하고 있는지 알려면 그가 주어진 문제에 대해 적절한 수준으로 작업하고 있는지를 보면 된다.

그러나 제 경험상 적당한 설계를 한 적은 거의 없었던 것 같습니다. 주로 과도한 편이 많았죠.
욕심이 많은 성격 탓일 수도 있습니다만, 대부분 요구사항이 명확하지 않았음을 핑계로 댈 수 있습니다. 외부로부터 온 요구사항은 프로그래머의 눈으로 봤을 때 구멍이 숭숭 뚫려있는 경우가 대부분이었습니다. 사소한 예외 처리를 명세하지 않은 것 정도는 애교 수준이죠.
프로그래밍 또는 소프트웨어에 대한 기초적인 이해 부족이 여실히 드러나는 요구사항이 많습니다. 그러나 정작 문제는 부실한 요구사항 정의 자체가 아닙니다. 프로그래머도 어떤 요구사항이 구멍이 큰 그물임을 바로 알지 못한다는 게 진짜 문제입니다.
와인버그도 이와 비슷한 말을 합니다.

프로그래머는 문제를 해결하고자 기울이는 노력의 수준을 적절히 조정하는 데 보통 실패한다. 풀어야 할 문제가 무엇인지를 모르기 때문이다. 다시 말해서, 구현 방법을 알고 있는 다른 문제나 바로 전 프로그래밍 업무에서 했던 일에 비추어 현재의 문제를 재단한다. 결국 일이 끝날 때까지 현재 해결 중인 문제를 제대로 파악하지 못한다.