성공하는 개발자가 가져야할 7 가지 습관
1. 설계
2. 디자인
3. 디버깅
4. 테스트
5. 리팩토링
6. 문제해결
7. 프로젝트 파일 관리
개발자는 단지 프로그램을 작성하기 위한 사람이 아니다. 개발자는 한 제품을 성공적으로 개발하기 위한 사람이다. 그렇기 때문에, 단순히 개별 모듈만을 작업하는 '코더' 와는 그 목표가 확연히 다르다. 가장 능력있는 개발자는 그가 개발하기 시작한 제품이 절대로 실패하지 않는 개발자이다. 물론, 이러한 성공률을 높이기 위해서 '아예 제품을 만들지 않는' 방법을 사용하지 않고 말이다.
여기까지만 읽은 독자들 중, 숨이 턱까지 찬 독자도 있을 것이다. 그럴수 있다. 앞에서 말한 제품 개발에 실패하지 않는 사람은 아무도 없기 때문이다. 개발자라면, 누구나 자신이 애써 만든 제품이 시장에 나가 성공하길 바랄 것이고, 그렇게 하기 위해서는 참으로 많은 난관이 존재한다. 제품을 하나 새롭게 만든다고 생각해보자. 가장 먼저 여러가지 제품들에 대한 벤치마킹을 한 후, 프로그램을 설계하고, 개발을 시작한다. 그리고, 개발된 제품을 디버깅하고, 데드라인에 맞추어 개발을 완료한다. 간단히 말로 적은 이 한줄이, 실제로 개발하는 사람의 입장에서는 피마르는 몇개월이된다. 아니, 사실 여기까지만이라도 정상적으로 완료가 되었다면, 이 프로젝트는 반은 성공한 프로젝트라고 할 수 있다. 하지만, 이 과정이 끝났더라도 더 많은 난관이 남아있다. 실제 제품이 시장에 나가서 성공하기 위해서는 시장에 배포된 이후의 사후처리도 매우 중요하다. 또한, 가장 중요한 시장에 수요와 요구에 맞게 변화하는 제품을 설계하는 것이 매우 중요한 일이다.
이러한 많은 난관을 잘 해쳐나가기 위해서, 개발자가 가져야할 덕목은 참으로 많다. 하지만, 필자가 본 많은 개발자들은 자신이 가진 습관과 일반적인 편견으로 많은 것들을 놓치고 있는 경우가 많았다. 물론, 필자도 그것들과 똑같은 실수를 하는 경우가 많이 있다. 무엇이든 자신이 알고 있는 것 보다는, 실제로 경험해보고 실패하면서 몸에 익힌 경험이 더 값진 법이기 때문이다. 이 글을 읽은 독자들이, 이 글에서 전하고자 하는 내용을 모두 체화시킬 수 는 없겠지만, 개발을 하면서 비슷한 문제에 봉착했을때, 이 글에 씌여진 필자와 많은 사람들의 경험이 도움이 되었으면 하는 바람이다.
개발자가 가져야할 7가지 습관 가운데 가장 중요한것은 설계이다. 설계 없는 프로그램은 사공이 많은 배가 되어, 산으로 올라갈 뿐이다. 물론, 프로젝트를 자신 혼자만 한다고 하면, 이 부분은 크게 문제가 되지 않는다. 어찌되었건 간에 사공이 물리적으로하는 한명이기 때문이다. 그렇다고 '난 혼자 개발하기 때문에 필요없어' 라고 말하는 개발자가 있다면, 잠깐 멈춰서서 글을 좀 더 읽어보기를 바란다. 물리적으로 단 한명은 개발자가 개발하는 프로젝트라고 할 지라도, 논리적으로는 여러명일 수 있다. 무슨 소리지? 라고 갸우뚱 하는 독자들을 위해서 좀 더 설명하자면, 사람은 시간이 지남에 따라서 참으로 많은 것이 바뀐다. 여러가지 경험에 따라서 생각도 바뀔 수 있고, 오늘 읽었던 책에 대한 기억이 오늘은 선명하겠지만, 내일은 더 흐릿해질 수 도 있는 것이다. 또한, 여러가지 외부 상황(개인적인 사정 등)에 따라서 더 안좋아질 수 도 있다. 이러한 많은 것들을 따져 보았을 때, 오늘 A 방향으로 만들자고 결정한 내용에 대하여, 다음날 갑자기 B 방향으로 가는게 더 좋아보일 수 도 있다는 것이다. 설계는 이러한 것을 방지하기 위한 일종의 확인과정이다.
설계를 철저하게 하면, 코드가 복잡해질 일 도 없고, 리팩토링도 하지 않아도 된다는 그러한 말도 있다. 필자가 말하고자 하는 설계는 그정도로 철저하게 하라는 것은 아니다. 물론, 설계를 완벽하게 한다면 코드가 복잡해질 일도, 리팩토링도 하지 않아도 된다. 설계서대로만 개발하게 되면, 더 이상 수정할 것도 없는 완벽한 프로젝트가 될 수 도 있다. 하지만, 이것이 가능하기 위해서는 실패한 설계가 필요하며, 설계가 실패하였다는 것을 증명하기 위해서는 사실상 실질적인 구현과정과 실패과정이 있어야 한다. 논리학적으로 어떤 명제가 잘못되었다는 것을 밝히기 위해서는 단지 그 명제가 맞지 않는 단 하나의 예시만 들면 되지만, 그 명제가 맞다는 것을 증명하는 것은 쉽지가 않다. 또한, 이에 대한 완벽한 프로세스가 존재하지 않기 때문에, 사실상 이것은 불가능하다고 할 수 있다. 그렇기 때문에, 설계를 완벽하게 하기 위해서는 일단 설계서대로 개발하는 과정을 여러번 겪어서 실패하는 수 밖에 없다는 것이다. 하지만, 사실상 이런식으로 소모적으로 설계 및 실패를 반복하는것은 불가능하다. 그에 따른 추가 비용이 너무 많이 들기 때문이다. 실패하는 프로젝트는 실제 제품으로 시장에 판매될 수 없기 때문에, 그 동안의 노력과 시간은 그대로 투자금액이 되어버린다. 이런 문제점을 해소하기 위해서 많은 개발자들이 조언하는 것은 단위별로 이러한 과정을 반복하라는 것이다. 단위테스트는 이러한 비용을 최소화시켜주며, 단위테스트가 된 각 모듈은 실제로 제품으로 합쳐졌을때 최소한의 문제를 발생시키도록 도와준다. 요즈음은 개발자들이 설계나 디버깅, 테스트 등에 많은 관심이 있어서 이러한 단위테스트들은 이미 익숙하고 잘 진행하고 있을거라고 생각하지만, 혹시라도 아직도 단위테스트를 하지 않고 있는 독자들이 있다면, 오늘부터라도 단위테스트를 하는 습관을 길러 보도록 하는게 좋을 것 같다.
설계는 코딩하지 않고 제품을 하나 만들어보는 행위이다. 물론, 실제로 코딩하지 않기 때문에, 실제 개발과정에서 겪는 많은 문제점들을 볼 수 없지만, 대략적인 제품 전체의 논리와 통합의 당위성등은 판단할 수 있다. 또한, 개발자의 입장에서 설계가 없는 프로그램은 어디로 갈 지 모르는 배에 탄 선원이 되는 것이지만, 설계가 있는 경우에는, 목적지가 뚜렷하게 정해진 배의 선원이 되는 것이므로, 자신이 하는 일에 대한 가치판단에서 자유로워 질 수 있다는 장점이 있다. 이 말이 다소 와닿지 않는 독자들을 위한 간단한 예를 들게 된다면, 설계를 하지 않고 프로그램을 작성하는 개발자는 새로운 버튼이 하나 추가될때마다, 이 버튼에 대한 기능을 트레이 아이콘 메뉴와 메인 메뉴, 그리고 다른 다이얼로그 박스의 버튼으로 추가해야할 것인지를 매번 고민해야 한다. 이는 매우 소소한 것처럼 보이지만, 이 소소한 것들에 대하여 매번 새로운 가치판단을 한다고 한다면, 프로그램의 일관성은 이미 없어져있을 것이다. 이러한 일관성이 없는 것의 대표적인 예는 '오픈소스' 프로그램이다. 필자는 개인적으로 오픈소스에 대한 정신은 찬성하지만, 서로 모르는 다수의 프로그래머가 추진하는 오픈소스 프로그램의 소스코드의 질(Quaility)에 대해서는 부정적인 입장이다. 서로 모르는 다수의 프로그래머는 서로 다른 가치판단을 내릴 수 밖에 없기 때문에, 프로그램이 일관성이 있게 진행되는 것이 여간 어려운 일이 아니다. 그러므로, 실제로 그러한 프로그램들의 소스 코드를 보면, A 소스코드와 B 소스코드가 완전히 다른 스타일로 작성되어 있어서 파악하기가 힘든 경우가 많다. 이런 경우가 여러번 반복되면 프로그램을 이어서 작성하는데 필요한 노력은 기하 급수적으로 증가한다. 곧, 얼마가지않아 그 프로그램은 더 이상 업데이트를 하는 것 보다 아예 처음부터 새로 만드는 것이 빠른 프로그램이 될 수 도 있다. 물론, 현실적으로 이러한 문제점을 가지고 있지만, 실제로 이러한 상태로 출시되는 제품도 많이 있다. 아마 현업에 종사하고 있는 많은 개발자들은 이 말에 깊은 공감을 느낄 것이다. 물론, 이러한 현실을 탓하고자 하는 것은 아니다. 이러한 현실을 알고 있는 개발자들은 이러한 일이 다시 발생하지 않도록, 최대한 노력하여야 한다는것이 필자의 생각이며, 이것은 누구를 위한 것도 아닌 바로 자기 자신을 위한 일이다. 또, 이러한 현실을 모르고 있던 개발자들은 이러한 것을 인정하고 나는 그러한 좋지 않은 관행을 되풀이 하지 않아야 겠다는 생각을 하여야 하겠다.
앞에서는 설계를 철저하게 하여야 한다는 말을 했는데, 사실 설계를 완벽하게 할 수 는 없다. 앞에서 말한 것 처럼, 이미 실제 제품을 만들어서 실패한 경우에는 그렇게 할 수 있지만, 사실상 업무에서는 '처음' 으로 설계하여, 그것을 성공으로 이끌어야 하기 때문에, 설계는 항상 성공하기 어려운 과제이다. 그렇기 때문에, 개발자는 설계에서 모든 것을 다 잡을 수 없으며, 그렇게 해서도 안된다. 즉, 설계는 완벽할 수 없기 때문에, 완벽하려는 욕심을 버리라는 것이다. '아니 앞에서는 설계가 무척 중요하다고 해놓고 이제와서 대충 하라는 말인가?' 라고 생각할 수 도 있겠다. 맞다. 하지만, 대충 하라는 말은 아니다. 설계는 완벽할 수록 좋지만, 모든 일에는 일을 처리할 수 있는 제한 시간이 있다. 그 제한 시간 안에 최대한 충실하게 하면 된다는 것이다. 다만, 독자들의 경험을 살려, 문제가 될 수 있는 부분만 정확하게 짚어가면서 설계를 하면 된다. 설계를 아무리 완벽하게 했더라도, 그 설계는 항상 바뀔 수 있다. 그 설계가 아무리 완벽할지라도, 실제로 제품을 사용하는 사용자의 요구사항이 바뀌게 된다면 설계도 바뀔 수 밖에 없기 때문이다. 그렇기 때문에 설계는 모든 조건을 다 만족시킬 수 없으며, 모든 문제를 해결할 수 없다. 단, 문제가 커지는 일을 방지할 수 있을 뿐이다. 그러한 이유로 개발자가 가져야할 7가지 습관 중 가장 먼저 나온것이 바로 이 '설계' 의 습관이다.
설계에 대한 또 다른 잘못된 생각을 하나 더 이야기 하자면, 설계를 중요하다고 생각하는 많은 사람들은, 설계를 하지 않고 코딩을 시작하는 프로그래머들을 다소 비하하곤 한다. 하지만, 필자의 생각은 다소 다르다. 설계는 물론 중요하고 프로젝트 시작전에 이루어져야 하지만, 아주 간단한 프로그램에까지 이러한 과정을 거치도록 강요하는 것은 올바르지 않다. 프로젝트의 미래를 예측할 수 있을 만큼 간단한 프로젝트에까지 무조건 설계를 할 필요는 없다. 예를 들면, 프로젝트에서 잠깐 필요한 디버깅용 소품 프로그램까지 설계를 해야 한다면, 이는 설계를 위한 설계가 될 것이다. 또한, 이렇게 작은 프로젝트가 아니더라도, 코딩 하는 것 자체가 설계와 위반되는 것은 아니다. 작은 단위의 프로젝트를 설계 이전에 직접 구현해 보는 것은, 좀 더 좋은 설계에 밑거름이 된다. 또한, 작은 실패는 큰 실패를 막을 수 있는 방패가 되어주고, 작은 성공을 쌓아가면서 큰 성공을 하게 해 주는 밑거름이 되어준다. 단위 테스트를 거친 작은 모듈들은 그것을 통합하더라도 큰 문제가 없기 때문이다. 이 내용이 실제로 와닿지 않는 독자들은 독자들이 사용하는 각종 플랫폼의 API 를 생각해보면 될 것이다. 대부분의 개발자들이 사용하는 API 들은 고도의 테스트를 거쳐서 릴리즈된다. 그렇기 때문에, 그것을 사용하여 만든 프로그램도 문제가 없이 동작하는 것이다. 혹자들은 특정 OS 에서 발생하는 블루스크린이나 시스템 실패(System Fault)를 가지고, 그 시스템 자체의 안정성을 의심하기도 하지만, 사실상 이것들은 시스템의 문제라기보다는 그 시스템에서 동작하는 수없이 많은 어플리케이션들의 문제이며, 이 어플리케이션은 안정성이 확보되지 않은 채로 시장에 출시되기 때문에 발생하는 문제이다. 이처럼, 단위 테스트를 철저하게 거친 모듈들은 그것을 다시 재 조합하더라도 문제가 발생하지 않는다. 이렇게 작은 단위로 나누어서 각 모듈의 안정성을 확보하고 그것을 전체 프로그램의 안정성으로 이어가는 방법은 적은 노력으로 큰 문제를 해결할 수 있게 하여 준다.
다소 장황한 이야기가 되었던 것 같다. 이야기를 정리해보자면, 설계는 꼭 필요하고 최대한 노력을 기울여야 하는 것이지만, 실질적으로 설계에 투자할 수 있는 시간은 무한정 주어지지 않는다. 그런 문제를 해결하기 위해서, 자신에게 주어진 시간에 최대한 설계를 철저하기 위한 계획을 만들어야 한다. 물론, 이 계획 조차도 바뀔 수 있다. 하지만 한가지 필자가 조언해주고 싶은 내용은, 예상보다 계획된 시간이 점점 줄어들고 있다면 실제 구현보다는 설계에 좀 더 많은 시간을 투자하는것이 좋다는 것이다. 또, 설계를 무조건 철저하게 하여야 한다는 생각으로, 무한정 설계에 시간을 투자하게 되면, 실제로는 구현할 수 없는, 너무 큰 프로그램이 될 수 도 있다. 이에 대한 것은 개발자 자신이 잘 조절하여야 하는데, 이것은 작은 모듈들에 대한 설계를 여러번 해 보는 것으로 익숙해질 수 있다.