성공하는 개발자가 가져야할 7 가지 습관

1. 설계
2. 디자인
3. 디버깅
4. 테스트
5. 리팩토링
6. 문제해결
7. 프로젝트 파일 관리

  다음으로 중요한 내용은 바로 디자인이다. 실질적으로 프로그램을 사용할 사람들이 만족할만한 프로그램을 작성하기 위해서는 좋은 디자인이 필요하다. 많은 개발자들이 이러한 디자인에 대하여 등한시 하는 경우가 있다. 물론, 이 글을 읽는 독자들 가운데는 '프로그램 만들기도 바빠 죽겠는데 그림까지 그리란 소리냐?' 라고 말할 수도 잇겠다. 필자가 여기서 말하고자 하는 내용은 '예쁘게' 만드는 디자인이 아니라, '사용하기 쉽게' 만드는 디자인이다. 사실, '예쁘게' 의 디자인은 익숙해지기 나름이다. 특정 분야의 프로그램(예를 들면 게임)이 아니라면, 디자인은 다소 부차적인 존재이다. 왜냐하면 대부분의 프로그램은 그 사용자들이 기능을 필요로 하기 때문에 사용하는 것이기 때문이다. 물론 게임과 같이 그 자체가 엔터테인먼트적인 성격을 가지고 있다면, 이는 디자인이 무시될 수 없을 것이다. 하지만, 대부분의 오피스 프로그램이나, 유틸리티 프로그램등은 디자인도 물론 중요하지만, 그 기능이 더 중요한 위치를 차지하고 있다. 이런 프로그램들에 있어서 디자인은 마치 '별것 아닌 것' 이라는 인상을 줄 수 도 있지만, 사실은 그렇지 않다. 우리가 모르는 디자인에서 오는 많은 것들은 가끔은 개발자를 소름끼치게 하는 경우도 있다.

  디자인을 잘못하여 실패한 소프트웨어가 있을 수 있을까? 이렇게 부정적인 내용을 묻는 질문에는 '예' 라고 답하기보다는 '아니오' 로 답하기가 더 어렵다. 독자들도 예상했겠지만, 디자인을 잘못한 소프트웨어는 실패할 수 있다. 이제 그 자세한 이야기를 시작해보도록 하자.
  디자인은 가장 기본적으로 프로그램과 사용자의 의사소통을 의미한다. 잘못된 디자인은 사용자들과의 의사 소통에 실패를 가져다준다. 그런 결과로 발생되는 '너무 사용하기 어려운 프로그램' 은, 곧 실패로 이어진다. 실제로 윈도우에 있는 여러가지 기능들은 매우 사용하기 어렵다. 사용되는 단어가 그 기능이 정확하게 무엇을 하는지를 알기 어렵게 만들고, 그 기능이 어디 있는지를 찾는것이 어렵기 때문에, 사용자는 모든 기능을 설정할 수 있는 프로그램을 가지고도, 실제로는 아무 기능도 사용할 수 없다. 잘못된 디자인을 가진 프로그램은 아무 기능도 없는 프로그램보다는 0.1% 정도 좋긴 하지만, 사실상 별 다를바가 없는 프로그램이다. 이와 비슷한 예를 들자면, 개발을 할 수 없는 일반 사용자들에게, 개발 프로그램(Visual Studio, Delphi, C++ Builder)을 사용하도록 하면, 그들은 실제로는 아무일도 할 수 없을 것이다. 이렇게 사용하기 어려운 프로그램은, 사실상 기능이 없는 것과 별반 다를게 없는 프로그램이 되어 버린다.
  잘못된 디자인은 프로그램을 사용할 수 없게 만들어 버리기도 하지만, 사용하기 위험한 프로그램으로 만들기도 한다. 한 예를 들어보자. 수치를 입력하기 위해서는 여러가지 방법이 있다. 0 에서 100 까지의 값을 입력 받기 위해서는, 슬라이드 컨트롤을 사용할 수 도 있을 것이고, 에디트박스를 사용할 수 도 있다. 일반적으로 프로그래머들은 자신들의 입장에서 생각하기 때문에, 슬라이드 컨트롤보다 에디트박스를 선호한다. 하지만, 에디트 박스는 여러가지 위험을 내포한다. 가장 큰 위험은 바로 입력 할 수 있는 방법이 무궁무진하여 진다는 것이다. 에디트박스에는 문자가 들어갈 수 있는데, 실제로 프로그램이 얻고자 하는 데이터는 '숫자' 형태이다. 이런식으로 디자인된 프로그램은 사용하기도 불편할 뿐만 아니라, 프로그램의 안정성 자체를 디자인 단계에서 해치게 되는 문제를 낳게 된다. 많은 보안 관련 서적에 항상 나오는 말이지만, 사용자의 입력을 절대로 믿지 않는 것인 보안의 첫걸음이다. 디자인은 프로그램과 사용자가 만나는 창구이면서, 사용자가 실제로 값을 입력하는 프로그램의 최전선이다. 이 최전선에서의 방어는 안전한 프로그램을 만들기 위한 가장 중요한 부분 중 하나이다.

[필자 메모]--------------------------------------------------------------------
 어떤 일이든 문제가 한번 발생한 이후에, 그것을 처리하기 위한 비용은, 그 문제를 발생시키기 전의 비용보다 훨씬 크다. IBM 은 Microsoft 에 OS 시장을 빼앗긴 이후로 그 시장을 되찾기 위해서 어마어마한 비용을 들였지만, 결국 다시 뺴앗아오지 못하였다. 보안도 마찬가지이다. 사소한 실수로 인하여 보안의 허점이 발생한 프로그램은 어마어마한 피해를 불러일으킬 수 도 있다. 사실, 어떻게 프로그램을 만든다고 할 지라도, 크래커를 완전히 막을 수 는 없다. 크래커에게 바이너리 파일은 소스파일과 같기 때문에, 크래커에게 공격을 하는 것은, 프로그래머가 새로운 기능을 프로그램에 추가하는 것과 같다. 그렇기 때문에, 초기에 아무리 노력한다고 해서 완전히 안전한 프로그램을 만들 수 있는 것은 아니다. 하지만, 불가능하다고 손을 놓는 것이 아니라, 최대한 크래커에게 찾을 수 있는 방법을 없애는 것이 좀 더 안전하고 뛰어난 프로그램을 만드는 개발자가 해야 할 일이다.
[필자 메모]--------------------------------------------------------------------

  디자인에 대하여 좀 더 이야기해보도록 하자. 디자인은 단지 외형적으로 드러나는 모양에서만 그치지 않는다. 소스 내부의 인터페이스 조차 디자인이라고 할 수 있다. 사실 앞에서 말했던, 보안성이 높은 프로그램을 만들기 위한 디자인에 대한 이야기는 소스 내부의 인터페이스에서의 디자인에서 언급할 내용과 다소 유사한 면이 없지 않아 있다. 사용자가 직접 사용하는 프로그램 인터페이스에서 사용자의 악의적인 입력이나 잘못된 입력을 걸러낼 수 있어야 하는 것 처럼, 프로그램 내부적으로도 그러한 문제를 해결할 수 있는 인터페이스의 가이드 라인이 필요하다. 이는 앞에서 필자가 이미 언급했던 것 처럼, 프로그램의 코드를 사용하는 개발자도, 또 다른 사용자의 한 형태라고 볼 수 있기 때문이다. 자신이 만들었다고 해서 오랜 시간이 지난 이후에도 자신의 소스를 100% 확실하게 사용할 수 있다는 보장은 없다. 하물며, 다른 사람의 소스를 사용하는 개발자의 경우에는 이러한 현상이 더 심할 것이다. 그렇기 때문에, 프로그램 내부의 인터페이스 디자인에 신경을 쓰지 않게 되면, 스스로 모듈들을 통합하면서 버그를 만들어내는 모습을 보게 될 것이다. 필자가 항상 다른 사람들에게 인터페이스에 관련된 이야기를 하면서 예로 드는 코드가 있다. 바로 <리스트1> 과 <리스트 2> 의 코드이다.

[리스트 1]-----------------------------------------------------
CInfoDialog dlgInfo;
if(dlgInfo.DoModal()==IDOK){
  Data1 = dlgInfo.GetResult1();
  Data2 = dlgInfo.GetResult2();
  Data3 = dlgInfo.GetResult3();
}
----------------------------------------------------------
[리스트 2]-----------------------------------------------------
CInfoDialog dlgInfo;
if(dlgInfo.DoModal()==IDOK){
  dlgInfo.GetResult(Data1, Data2, Data3);
}
----------------------------------------------------------

 <리스트 1> 과 <리스트2> 의 코드는 모두 어떤 다이얼로그에서 입력된 값의 결과를 가져오는 코드이다. 이러한 내용은 간단히 소스코드의 단어들만 보아도 알 수 있을 것이다. 하지만, 두개의 코드는 목적은 같지만 형태는 다르다. 과연 어느것이 더 좋은것일까? 여러가지 의견이 있을 수 있겠지만, 필자의 생각으로는 <리스트 2>쪽의 코드가 더 좋다는 것에 손을 들어주고 싶다. 왜냐하면, 혹시라도 나중에 반환값이 하나 더 늘어났을 경우에, <리스트 1>의 경우에는 다이얼로그의 GetResult4() 함수를 추가 하였더라도, 실제로 호출하지 않는 경우가 발생할 수 있으며, 이 경우에 에러가 발생하지 않아서 프로그래머가 실수 할 수 있는 경우가 많아지지만, <리스트2> 의 경우에는, GetResult 함수의 파라메터를 수정하게 되면, 자동적으로 GetResult 를 호출하는 부분에서, 파라메터를 얻어오지 않을 경우에 에러가 발생하기 때문에, 실수를 할 확률이 더 줄어들게 되기 때문이다.
 또, 이러한 유사한 것으로 전달하는 데이터의 형태가 어떤것인지도 중요하다. 주로 많이 실수하는 것 중 하나는, String 데이터를 null 값 없이 전달한다거나, unsigned 데이터 형을 signed 데이터 형으로 입력 받는다거나 하는 것들이다. 이러한 것들은 아주 사소해 보이지만, 실제로는 큰 문제를 일으킬 수 있는 위험한 것들이다.

 [필자 메모]--------------------------------------------------------------------
 쉬어가는 의미에서 간단한 코드에 대한 이야기를 해 볼까 한다. 꽤 오래된 이야기인데, 아무 의미 없는 if 구문에 대한 내용이 이슈가 된 적이 있었다. 바로 ' if('^' == '^') { ' 로 시작하는 if 구문이었는데, 독자들도 이해하겠지만, 이 코드는 항상 TRUE 인 조건을 가지고 있기 때문에, if 구문안에 있는 것이 무조건 실행된다. 그렇다면 과연 이런 코드는 왜 있었을까? 그것은 바로 해당 코드안의 내용을 좀 더 강조하기 위한 것이다. 이러한 방법은 개발자마다 다소 다른 방법을 가지고 있다. 필자의 경우에는 #pragma message 를 주로 사용하는 편이다. 이것을 사용하여 혹시라도 다음 소스코드를 수정할 때, 실수할 만한 내용들을 소스 코드안에 넣어버린다. 이런식으로 소스 코드 안에 개발자들이 이해할 수 있는 어떤 기호들을 넣어두는 것은 참으로 유용하다. 물론 문서를 그때그때 찾아보면서 정확한 History 와 문제점을 파악하면서 꼼꼼히 개발하는 것이 가장 정석이겠지만, 이러한 탁상공론이야 굳이 말하지 않아도 불가능하다는 것을 독자들은 이미 알고있을 것이니까...
----------------------------------------------------------
 
 이렇게 디자인은, 간단하게 프로그램과 사용자의 의사소통의 장이 되면서, 실제로는 개발자와 개발자의 의사소통의 장이 되기도 한다. 의사소통에 실패한 프로젝트와 프로그램은 실제로 아무도 사용할 수 없는 애물단지가 되어버린다. 그 어떤 누구라도 자신이 애써서 개발한 프로그램이 자신이나 다른 누군가에게 이러한 취급을 받는 다는 것은 가슴아픈일일 것이라고 생각한다. 그렇기 때문에, 디자인은 어떻게든 완성될 프로그램에 있어서, 그 프로그램의 품질에 가장 큰 영향을 주는 것이라고 할 수 있다. 기능이 아무리 많고 잘 동작하는 프로그램이라고 할 지라도, 그 기능이 완전하지 못하고, 그 기능을 사용자가 실제로 사용할 수 없다면, 이것은 그림의 떡이 되어버릴 것이다. 이러한 이유가 필자가 디버깅과 같은 기타 내용보다도 디자인에 대한 내용을 좀 더 앞에 둔 이유이다. 디버깅은 프로그램 개발 프로세스에서 매우 중요한 내용이지만, 이것은 제품이 정상적으로 나오고 사용자들의 요구를 맞추었을 경우의 일이다. 아무도 사용할 수 도 없는 기능이 완벽히 동작한다고 과연 그것을 누가 알아줄수 있을까?

+ Recent posts