대한민국 개발자로 산다는 것
에러는 유익하다. 왜냐하면 에러는 우리가 무슨 일이 일어났는지 연구하고 뭐가 잘못되었는지 이해하게 이끌어주며 이해하는 과정에서 고칠 수 있기 때문이다.
- 앤디 헌트 《실용주의 사고와 학습》 中
1947년 9월 9일, 최초의 버그(bug)가 발생한 이후로
지금까지 개발자들은 버그와 사투를 벌이고 있다.
당시 미 군함의 계산식 프로젝트를 맡아 하버드에서 마크II 컴퓨터를 담당하던 한 여성은 컴퓨터가 멈춘 원인을 찾던 도중 컴퓨터 패널의 릴레이 사이에서 나방을 발견했다. 그녀가 바로 최초로 컴퓨터 오류의 원인으로 벌레(bug)를 발견한 그레이스 호퍼(Grace Hopper)다. 코볼의 창안자이기도 한 호퍼는 릴레이 사이에서 벌레가 발견된 사실을 컴퓨터 로그 노트에 기록했다.
08:00 활동 시작
10:00 활동 중단, 릴레이를 교환하다.
11:00 코사인 테스트 시작
15:25 멀티 덧셈기 테스트하다.
15:45 70번 패널(나방) 릴레이, 최초의 실제 벌레(버그)를 발견했다.
이후 '버그'는 보편적인 컴퓨터 용어가 됐으며 프로그램 내의 오류, 즉 버그를 찾아내어 수정하는 작업을 디버깅(debugging)이라고 부르게 됐다. 개발자들에게 코딩만큼이나 친숙한 작업이 디버깅이다. 코딩을 하다 보면 결코 한 번에 완벽한 소스코드를 작성할 수 없음을 경험하게 된다. 결국 버그를 잡고 오류를 수정해나가는 끝없는 과정을 반복한다. 완성도 높은 프로그램이 얼마나 코딩을 잘했느냐가 아닌 얼마나 오류를 잡아냈느냐에 따라 결정되는 까닭은 바로 이 때문이다.
“손 코딩 눈 디버깅”이란 말이 있지만 나는 눈으로만 버그를 잡는 것을 선호하지 않는다. 내가 작성한 소스코드에 꼭꼭 숨어 아무리 눈으로 보아도 쉽게 발견하지 못하는 경험을 수없이 한 뒤로는 IDE에서 제공하는 디버깅 툴을 이용한다.
IDE에서 제공하는 디버깅 툴은 사용하기도 쉽다. 디버깅 모드로 실행하고 의심 가는 부분에 중단점(breakpoint)을 찍고 프로그램을 실행한다. 그런 다음 코드를 한줄 한줄 실행해 가면서 프로그램의 흐름에 위배되는 부분은 없는지, 변수에 잘못된 값이 들어가고 있지는 않은지, 논리 구조에 문제는 없는지 면밀히 살펴본다. 여기에선 프로그램 전체가 아닌 의심이 가는 부분을 선택해서 한 줄씩 본다는 것이 핵심이다. 이렇게 보다 보면 코드는 손에 잡힐 듯 정리가 되고 대부분의 문제는 겉으로 드러나게 된다. 그래서 나는 디버깅을 해보기 전에는 문제가 뭐라고 단정지어 말하지 않는 편이다. 이 과정은 마치 컴퓨터와 대화하는 것처럼 내가 의사가 되어 코드를 진단한다.
이렇게 디버깅을 하다 보면 버그가 하나 둘 해결돼가듯 우리 인생의 문제도 디버깅된다면 얼마나 좋을까 생각해보게 된다. 이미 고착화돼 삶의 일부가 돼버린 묵은 버그까지도 디버깅을 통해 찾아낼 수만 있다면 좋겠다는 생각을 하게 된다.
간혹 디버깅하다 보면 도저히 문제가 없어 보이는데 원하지 않는 결과가 나오는 경우가 있다. 디버깅에서도 오류의 원인이 나타나지 않는다면 여간 곤혹스러운 일이 아니다. 많은 시간을 쏟아붓고도 문제가 해결되지 않으면 문제의 원인을 외부의 탓으로 돌리기도 한다.
"이건 서버 쪽 문제일 거야", "데이터베이스에 문제가 있는 게 틀림없어", "라이브러리가 잘못됐나?"
하지만 결국 틀린 건 바로 자신이라는 것을 확인할 뿐이다. 컴퓨터가 쏟아낸 오류는 결국 다른 사람이 아닌 내가 코딩해서 만들어 낸 결과다. 그래서 디버깅도 버그를 만들어 낸 당사자가 한다. 개발된 프로그램에 버그가 많다는 것은 기획자, 설계자, 디자이너의 책임이 아닌 실제로 해당 프로그램을 개발한 개발자의 책임으로 돌아온다.
어느 순간부터 개발자들은 버그가 만들어지는 수많은 경우를 다른 개발자들과 공유하기 시작했다. 이로 인해 문제 해결을 위해 소모하던 시간은 줄어들고, 해결되지 않는 버그는 인터넷상에서 토론할 수 있게 됐다. 얼핏 보기에 우리는 버그를 정복해가는 듯 보인다. 하지만 그제야 정작 중요한 우리 자신의 버그는 어찌해야 할지 들여다보게 된다. 수많은 버그를 잡기 위해 야근을 해야 하고, 삶의 만족도를 떨어뜨리는 문제가 득실거릴 때 우리 삶에도 디버깅이 필요해 보인다. 디버깅을 통해 버그를 하나씩 잡고 시스템이 안정적으로 동작할수록 개발자의 삶에서도 이런 갈망이 더해진다.
하지만 우리 삶의 문제는 더욱 복잡해 보인다. 풀리지 않는 실타래처럼 얽혀 있으니 그것을 풀어가는 과정을 '인생을 살아간다'는 말로 표현한다. 인생의 문제는 명확한 해법이 없기에 답답한 것이다. 가끔은 다른 개발자들에게 해결하지 못한 소스코드의 버그에 대한 의견을 구하듯 다른 사람의 의견을 묻고 싶을 때도 있다. 하지만 민감한 개인의 문제는 타인과 공유하기 꺼려지고, 실존하는 삶의 문제는 다양한 현실적 상황들과 맞물려 조언만으론 해결하기가 어려울 때가 많다.
결국 삶은 기본적으로 스스로 디버깅을 통해 문제를 해결하거나, 같은 오류를 반복하며 살아갈 수밖에 없는 운명적인 것이다.
버그 없는 프로그램은 존재하지 않듯이
아무런 문제 없이 유지되는 삶은 존재하지 않는다.
인간은 탄생과 함께 생태적 위험 속에 놓인다. 인생을 살아가면서 피치 못해 겪게 되는 수많은 문제를 해결하지 않고 묵혀두면 그것이 쌓이고 쌓여 결국 더 크게 돌아온다는 사실을 깨닫게 된다. 그래서 우리는 문제를 회피하기보다 직시해야 한다. 그렇지 않으면 문제를 안은 채 살아온 대로 살아갈 수밖에 없다.
오스트리아 태생인 영국의 철학자 카를 포퍼(Karl Popper)는 "삶은 문제 해결의 연속이다"라고 말했다. 실제로 우리는 삶의 문제를 놓고 해결하기 위해 사투를 벌이며 살아간다. 삶에 있어 디버깅은 끊임없는 자기성찰이다. 내가 어디쯤 도달해 있는지, 목적지는 어디인지, 현재의 삶에 만족하고 있는지 가끔은 바쁜 걸음을 멈추고 돌아보자. '오류를 반복할 것인가, 아니면 한 번쯤 디버깅을 하고 오류를 제거하고 갈 것인가'는 우리가 선택할 수 있는 서로 다른 갈림길이다.
어느 쪽 길로 들어설지는 스스로 결정하겠지만, 결과는 명확하다. 오류가 제거되면 성장의 발판이 마련될 것이다. 생명체는 잘못된 부분을 수정해가며 끊임없이 진화를 거듭해왔다는 점이 이를 뒷받침한다. 진화하지 못한 생물체는 자연스럽게 도태되고, 진화에 성공한 생명체는 살아남는다. 그것이 냉혹한 생존법칙이다. 결국 우리는 인생의 디버깅을 선택이 아닌 필수 요소로 인식해야 한다. 사람은 문제를 인식하고 해결하며 진화해간다.
"자신이 진정 사랑에 빠질 수 있고 자신의 인생을 기꺼이 바칠 수 있는 멋진 문제 하나를 찾아보라고 권하고 싶다."
카를 포퍼의 말처럼 문제는 자신의 인생을 사랑하는 관심의 표현이다. 인생 전부를 걸고 그 문제를 풀기 위해 평생을 노력하는 사람을 누가 당해낼 수 있을까? 그런 의미에서 현재의 삶이 만족스럽지 않다면 우리는 문제를 회피하고 있는 것이다. 지금이라도 현재 내가 가진 가장 큰 문제를 찾기 위해 깊이 있게 들여다보고 자신에게 물어보자.
나는 삶을 디버깅하려는 적극성을 가지고 있는가? 그리고 나를 돌아볼 준비가 돼 있는가?
우리는 인생이 아무리 힘들어도 도망칠 수 없고 삶의 문제를 회피할 수 없다. 결국 삶은, 문제를 떼어 놓고는 설명할 수 없으며, 문제 해결을 위해 산다는 것을 직시하자. 세상이 급격히 변하면서 우리가 다루는 소프트웨어는 점점 복잡해지고, 우리가 풀어야 할 삶의 문제 또한 까다로워 보인다. 이제는 정말 눈으로 대충 문제를 짐작할 수 있는 시기는 지난 듯싶다. 짐작과 가정이 아닌 우리 몸으로 직접 확인한 실체만이 진짜임을 잊지 말고, 우리 인생도 적극적으로 디버깅을 해보자. 언제나 그렇듯이 개발자에게 눈에 보이는 벌레(bug)는 두려움의 대상이 아니었다.