천객만래 [千客萬來] (It has an interminable succession of visitors)

SW 개발자의 길, 아니다 싶으면 포기하라


20일 오전에 MS가 주관하는 ‘2007 데브데이’ 행사에 참석했다. IT업계에 종사하는 사람이라면, 아마도 한번쯤은 MS의 독점성과 라이선스 정책 등에 대해 불만을 품어봤을 만하다. 그럼에도 불구하고 SW 개발자들의, MS에 대한, 관심은 어느 행사보다 뜨거움을 느낄 수 있었다.

기자는 오전 행사 중 한국MS의 최고기술임원인 김명호 박사(혹은 이사, 왠지 모르지만 박사라는 호칭이 더 어울린다)의 기조연설만 듣고 나서 김박사와의 짧은 인터뷰를 진행할 수 있었다. 그는 기조연설과 인터뷰를 통해 ‘한국에서 SW 개발자가 가야 할 길’에 대해 <희망차고도 암울한> 사회적 딜레마를 이야기해 주었다.

아래의 글은 김명호 박사를 통해 들을 이야기를 바탕으로 작성해 보았다.

[明, SW 개발자여 전문인으로 거듭나자!]
ZDNet Korea의 컬럼니스트 중 한명인 류한석 소장은 얼마 전 자신의 컬럼에 ‘한국에서 SW 개발자가 성공하지 못하는 세가지 이유’를 통해 어려운 사회적 현실을 이야기 했다. 그러한 이유가 아니더라도, SW 개발자로 성공한다는 것 자체는 다른 어떠한 직업과 견주어도 결코 쉬운 것만은 아닐 것이다.

한국 자바 개발자의 1세대라 할 수 있는 김명호 박사 역시 개발자 출신으로 성공의 길을 걷고 있다고 할 수 있지만 “이 길이 아니다 싶으면 차라리 다른 일을 하라”는 말을 서슴지 않고 내던지고 있다. 요즘 시대에 개발자는 한국이라는 좁은 시장에서가 아니라 전세계적으로 통할 수 있는 전문성을 가져야 하는데, 이를 달성하는 것은 결코 쉬운 일이 아니기 때문이다.

SW 개발자로 성공하려면, 단기간 학원 교육을 통해, 누구나 습득할 수 있는 주류 기술 몇 가지만 배워서는 안 된다. 코딩, 테스트, 디버깅, 이식, 성능, 설계, 스타일 등 다양한 소양을 갖춘 전문인이 진정한 개발자라고 할 수 있다. 단순히 코딩만을 할 줄 안다고 해서 전문인으로써의 ‘정신과 혼’을 담지 않고 있다면 ‘하급 노동자’에 지나지 않는다는 것이다.

개발자와 아키텍트는 다르다
한국의 개발자들은 마치 개발자가 아키텍트로 가는 중간 단계로, 한번쯤 거쳐야 할 과정쯤으로 여기는 경향이 있다. 그러나 아키텍트와 개발자는 엄연히 다른 직업이다. 아키텍트가 되기 위해 개발자 경험이 있는 것은 좋지만, 막연하게 개발자를 거쳐 아키텍트가 된다고 생각하는 것은 옳지 않다는 것이 김박사의 설명이다.

그는 “아키텍트가 될 자질을 갖추는 것은 개인의 소양에 따라 다르다. 이를 건설에 비유하자면, 개발자는 건설현장에서 일하는 인부고 아키텍트는 건축설계사라고 볼 수 있다. 미적, 공학적인 요소를 갖추었을 때 건축설계사가 되는 것처럼, 현장 인부가 자신의 경력을 통해서만 될 수는 없는 것이다”라며 “대신 그들은 미장이나 도색 전문가 혹은 작업반장이 될 수 있다. 즉, 해달 분야의 전문가로 훌륭히 성공할 수 있는 것이다”라고 말했다.

그렇다고 벽돌을 나르는 수준의 초급 개발자가 10년 후 작업반장 수준의 상급 개발자가 되는 것은 아니다. 먹고 살기 위해서 개발을 한다면 행복해 질 수 없을 테고, 당연히 훌륭한 개발자가 될 수도 없다. 때문에 개발자들이 당면한 과제는 어떻게 하면 훌륭한 개발자가 될 수 있냐는 올바른 방법론이 필요하다.

이에 대해 김명호 박사는 몇 가지 지침을 가르쳐 준다.

훌륭한 개발자가 되려면?
1) 기본에 충실해야 한다.
여기서 말하는 기본과 초급은 분명 다르다. 개발자라면 알고 있어야 할 프로그래밍의 기본 구조나 알고리즘 등의 기본에 충실하지 못하다면, 10년이 지나도 불행하기는 마찬가지일 것이다. 만약 개발자인 당신이 먹고 살기에 급급해서 수박 겉핥기로 몇몇 기술만 습득했다면 지금이라도 당장 시작하는 것이 중요하다. ‘언젠가는 적용해야 할 핵심기술’을 습득하는 것이 중요하다.

2) 지식의 포트폴리오를 유지하라.
재테크에서의 교훈에 따라 ‘달걀을 한 바구니에 담지 마라’는 것을 생각하자. 즉, 개발자는 어느 한 분야에 올인하지 말고 ‘남들도 다 아는’ 주류 기술과 ‘남들은 모르는’ 전문 기술로 분산 투자해야 한다는 것이다.

3) 분야 전문가나 해박한 지식을 갖춰라.
앞서 언급한 대로 건설현장에서 미장이나 도색 전문가, 작업반장이 될 수 있는 분야별 전문가가 된다면 어디서든 존중 받을 수 있다. 그러나 여기서 중요한 것은 과도한 욕심을 부려서는 안 된다는 것이다. 분야의 전문가인 동시에 해박한 지식을 갖추고 있다면 그야말로 ‘천재’라고 할 수 있지만, 이 둘 중 한가지만 갖춰도 충분하다는 것이다. 모든 분야에 대해 피상적인 지식만을 갖추고 있다거나, 사장된 기술에 매달린다거나, 자아도취에 빠져 자신만의 방법이 옳다고 여기는 오류를 범할 수 있기 때문이다.

4) 학습을 두려워 마라.
이것이 김박사가 가장 강조하는 부분으로, 충분한 기본지식을 갖추고 있다면 새로운 지식을 습득하는 것에 두려움이 없으며 새로운 기술을 습득하고 끊임없이 발전해 나가는 것이야 말로 행복한 개발자가 되는 최우선 요소다. 만약 새로운 기술을 습득하는데 더디다고 느낀다면 그것은 기본이 부족하기 때문이며, 지금이라도 기본을 습득해 나간다면 신기술 습득에 대한 두려움은 사라진다.

이러한 개발자를 위한 성공 방법론이 제시됐음에도 불구하고, 개발자가 선택할 수 있는 최악의 길은 ‘다른 길을 찾아가는 것’이다. 개발자가 뭐 그리 대단한 것인가? SW 개발자가 아니더라도 얼마든지 다른 분야에서 전문인이 될 수는 있는 것이다. 자신이 택했지만 SW 개발자로의 미래가 안 보인다고 생각된다면, 과감히 다른 길을 선택하라.

개발자야 말로 ‘파레토의 80대 20의 법칙’이 가장 확실하게 적용되는 분야다. 20%의 능력 있는 개발자만이 훌륭하게 80%의 개발을 수행할 수 있다.

[暗, 과연 한국에서 SW 개발자가 성공할 수 있나?>
김명호 박사는 SW산업에서 이러한 파레토의 법칙이 중요하다고 말한다. 뛰어난 소수의 전문인력이 SW산업을 발전시킬 수 있고, 이러한 인재를 정책적인 지원 하에 키워내야 한다는 것이다.

그러나 현실은 그다지 밝지 않아 보인다. 정부의 정책이라는 것이 ‘노동정책’에 가깝기 때문이다. 즉, 대학과 같은 전문교육기관에 의한 전문가를 양성한다기 보다 실업자를 줄이기 위해 하급 개발자를 배출해 내는데 급급하고 있다는 지적이다.

막상 현재 대학의 교육 현실은 어떠한가? 학부제를 도입한 이후, 학생들은 어려운 과목은 제외하고 쉽거나 학점을 잘 받을 수 있는 과목을 수강할 수 있게 된 상태다. 숙명여대 전산관련 학과의 한 교수는 “요즘 학생들은 알고리즘과 같이 기본을 다질 수 있는 과목은 어렵다고 회피한다. 그저 취업을 위한 학점 챙기기나 가벼운 프로그래밍 기술에 몰린다”고 안타까워한다.

이럴 바에는, 오히려 비전공자가 낫다는 의견도 있다. 기본에 충실하지 않은 전공자들보다 학원에서 5~6개월 집중적으로 배우고, 취직해서 급여를 받는 이들이 더욱 충실도가 높고 급여도 적게 든다는 것에 SI업체들이 매력을 느낄 수도 있다는 것이다.

실패 거듭하는 ‘SW 정책’
실제 이렇게 부실한(기본에 충실하지 못하다는 의미로, 이들이 모두 부실하다는 것은 아니다) 개발자들을 고용한 SI업체를 통해 프로젝트가 실패한 경우, 그 책임소재의 표적은 SI가 아닌 HW로 돌리는 경향이 있기도 하다. 어떻게 보면 이것이 ‘SW 분리발주 정책’을 창출한 계기 중 하나이며, 개발자의 ‘표준공임단가’를 책정하게 된 이유가 될 것이다.

특히 개발자에 대해 표준공임단가를 두어 금전적 보상에 제한을 두어서는 안 된다. 이는 능력 있는 전문가가 되고자 하는 이들의 의지를 꺾을 수 있기 때문이다. 핀란드의 한 대학에서 내놓은 조사자료에 의하면 ‘SW 개발생산성에 있어 훌륭한 개발자 1명의 개발생산성이 하급 개발자에 비해 20배 가량 높다’는 결과가 있다. 이는 급여 측면에서 볼 때에도 그 이상의 가치가 있는 것이다.

현재 정부의 실업정책에 가까운 SW 정책은 이러한 측면에서 많이 부족하다는 지적이다. 즉, 표준공임단가에 묶여 있기 때문에 국내에서는 아무리 뛰어나다고 해도 인정받지 못하는 토양이 굳어져 가고 있으며, 이는 마찬가지로 기업 내부에서도 개발자에게 인색할 수 밖에 없다.

또한 전문인을 양성하기 위해 수년의 기간이 필요하지만, 단기간 성과를 내야만 하는 국내의 프로젝트 특성도 개발자를 힘들게 하는 악순환에 한 몫 거들고 있다.

소수의 전문인 중심 체계 필요
김명호 박사는 “정책적으로 획기적인 변화가 있어야 한다. 노동집약적 산업이 아닌 지식집약적 산업으로 바꾸기 위한 정책이 필요하다. 물론 교육도 마찬가지다. 전산 관련 대학 정원을 줄여서 의욕이 있는 전문가를 양성해 내고 이들을 대상으로 SW정책을 만들어 가야 할 것이다”라고 말했다.

그는 또 “16만 명에 달하는 국내 개발자들 모두에게는 미안한 말이지만, 누구나 다 성공할 수는 없다. 끊임없이 노력할 수 있고 자기를 발전시킬 수 있는 소수 개발자들만이 성공할 수 있으며, SW 정책도 이들에게 마음 놓고 일할 수 있는 환경을 만들어 주는 산업으로 만들어야 정부차원의 ‘미래의 먹거리’ 산업으로 성장할 수 있을 것이다”라고 주장했다

Posted by SB패밀리

The Joel Test: 나은 코딩을 위한 12단계


글 : Joel Spolsky
번역 : B.K. Chung 정봉겸
감수 : Jang Han Goo 구장한
2000년 8월 9일

SEMA에 대해서 들어보신 적이 있습니까? 소프트웨어 팀이 얼마나 잘하는지를 재는 나름대로 복잡한 시스템입니다. 앗, 아니! 그 링크를 누르지 마세요. SEMA를 "이해"만 하는데 아마 6년정도가 걸릴것입니다. 그래서 소프트웨어 팀이 얼마나 좋은지 등급을 매길 수 있는 - 좀 무책임하고 되는대로의 - 자체적인 버젼의 테스트를 만들었습니다. 이 테스트의 장점은 3분정도밖에 걸리지 않는다는 것입니다. 절약되는 시간으로 의대에 가서 공부할 수도 있을 것입니다.

The Joel Test

  1. Source Control(소스 컨트롤)을 사용하십니까?
  2. 한번에 빌드를 만들어낼 수 있습니까?
  3. daily build(일별 빌드)를 만드십니까?
  4. 버그 데이타베이스를 가지고 있습니까?
  5. 새로운 코드를 작성하기 전에 버그들을 잡습니까?
  6. up-to-date(최신) 스케줄을 가지고 있습니까?
  7. spec(설계서)를 가지고 있습니까?
  8. 프로그래머들이 조용한 작업환경을 가지고 있습니까?
  9. 돈이 허락하는 한도내의 최고의 툴들을 사용하고 있습니까?
  10. 테스터들을 고용하고 있습니까?
  11. 신입사원들은 면접때 코드를 직접 짜는 실기시험을 봅니까?
  12. hallway usability testing(무작위 사용성 테스팅)을 하십니까?

Joel Test이 특별한 점은 각 직문에 예/아니오로 바로 대답할 수 있다는 것이다. lines-of-code-per-day(하루동안 산출되는 코드의 줄수)나 average-bugs-per-inflection-point(산출 시점의 평균 버그수) 같은 것은 알 필요가 없습니다. "예"에 해당 하는 질문에 1점씬 가산됩니다. 하지만 이 테스트는 핵 원자로에 사용하는 소프트웨어가 안전한지를 검사하는등 에는 사용하지 말아주십시오.

12점은 완벽, 11은 충분한 점수이지만 10점이나 그 이하는 심각한 문제가 있다는 신호입니다. 사실은 대개의 소프트웨어 회사 들이 2~3점을 받고 있고, 심각한 도움을 필요로 하고 있습니다. Microsoft같은 회사는 12점 만점을 받고 있습니다.

당연한 이야기지만 이것들만으로 성공과 실패를 가를 수는 없습니다. 특히, 아무도 필요없는 제품을 굉장히 훌륭한 소프트웨어 팀이 만들고 있다면, 역시나 아무도 원하지 않을 것입니다. 반대로 이런 방식을 따르지 않는 명인들이 세상을 바꾸는 소프트웨어 를 만드는 경우로 생각할 수 있겠습니다. 그러나, 이 12가지 이외의 요소를 모두 동등하게 놓고 본다면, 이들만 제대로 한다면 지속적으로 좋은 결과를 내는 잘 훈련된 팀이 될 것입니다.

1. Source Control(소스 컨트롤)을 사용하십니까?

상용 소스 컨트롤 패키지들도 사용해보았고, 무료로 사용할 수 있는 CVS도 사용해보았습니다. CVS는 무료이기는 하지만 충분합니다. 그렇지만 소스 컨트롤이 없다면 프로그래머들을 조율하는 일이 상당히 피곤할 것입니다. 프로그래머들은 다른 사람들이 어떤 것을 했는지 알 수 있는 방법이 없습니다. 이를 사용하면 실수를 쉽게 롤백할 수 있습니다. 소스 컨트롤의 다른 장점은 소스코드 자체가 모든 프로그래머의 하드디스크에 체크아웃(check out)되어 있다는 것입니다. 소스 컨트롤을 사용하는 프로젝트에서 코드를 날렸다는 이야기를 들어본 적이 없습니다.

2. 한번에 빌드를 만들어낼 수 있습니까?

"최신의 소스로부터 몇단계를 거쳐서 완제품(shipping build)을 만들 수 있습니까?"라는 의미의 질문입니다. 잘 되어있는 팀인 경우라면 하나의 스크립트로 checkout부터 시작하여 각 소스를 리빌드(rebuild)하고 각 버젼, 언어, #ifdef같은 조건별로 실행파일을 만들어내어 마지막 CDROM 레이아웃, 다운로드할 수 있는 웹사이트를 만들어 내는 정도까지 되어 있을 수 있겠습니다.

만일 이 과정이 하나의 단계 이상을 거친다면, 여기서부터 에러가 발생할 확률이 생깁니다. 정해진 기일이 가까워질수록 "마지막" 버그를 수정하고 실행파일을 만드는 등을 위해 빠른 사이클을 필요로 할 것입니다. 코드를 컴파일하고 설치파일을 구성하는데에 20단계가 필요하다면 급박한 시간때문에 사소한 실수를 저지르게 될 것입니다.

필자가 마지막으로 근무했던 회사에서는 이런 이유로 WISE를 InstallShield(역자주 : 두 제품 모두 설치본을 만들기위한 도구 입니다.)로 교체하였습니다. 설치 과정을 스크립트를 통해서 NT 스케줄러로 밤새에 자동으로 실행하도록 하고자 하였는데, WISE는 스케줄러로 실행할 수 없던 이유입니다. (WISE의 친절한 분들이 최신 버젼에는 이것이 가능하다고 알려왔습니다.)

3. daily build(일별 빌드)를 만드십니까?

소스 컨트롤을 사용하다 보면 누군가가 빌드를 실패하게 만드는 코드를 체크인 할 수 있습니다. 예를 들면, 새로운 소스파일을 추가해서 그 사람의 컴퓨터에서는 잘 컴파일되지만, 이를 코드 레파지토리(repository)에는 추가를 하지 않았을 수 있습니다. 이 사람은 이를 잊고 만족한 상태에서 컴퓨터를 잠그고 집에 돌아갑니다. 그렇지만 이로 인해 다른사람들은 작업을 할 수 없게 되고 결국 찝찝하지만 결과없이 집으로 돌아갈 수 밖에 없습니다.

모르는 사이에 빌드를 실패하는 이런 컴파일 오류가 나지 않도록 daily build를 만들게 됩니다. 큰 팀에서는 이런 경우를 위해서 daily build를 매일 오후 - 점심시간등 - 에 합니다. 사람들은 점심시간 이전에 될 수 있는 한 많이 체크인을 합니다. 점심을 먹으로 갔다가 다시 돌아오면 빌드는 이루어져 있습니다. 빌드가 실패하면, 사람들은 빌드가 성공한 이전 소스로 작업을 하면 됩니다.

엑셀팀에서는 누군가 빌드를 깨면 벌칙으로 다른 사람이 다시 깰때까지 빌드를 관리하도록 벌칙을 주었습니다. 이는 빌드를 깨면 받는 벌칙으로써 뿐만 아니라 모든 이들이 돌아가면서 빌드를 관리할 수 있게하여, 어떻게 돌아가는 지를 익히게 하는 방법으로써도 좋았습니다.

daily build에 관해 더 자세히 아시려면 저의 기사 daily builds are your friend를 읽으십시오.

4. 버그 데이타베이스를 가지고 있습니까?

뭐라고 반박하셔도 확신합니다. 코드를 짜고 있다면 설령 혼자 짜더라도 정리된 버그 명세 데이타베이스를 가지고 있지 않다면 낮은 질의 코드로 제품을 출시할 것입니다. 많은 프로그래머들이 머리로 버그들을 모두 기억할 것이라고 생각합니다. 말도 안되는 이야기입니다. 제 경우에는 한번에 2~3개의 버그밖에 기억을 못하고, 다음날이 되거나 출시를 위해 급해지면 전부 잊어버리게 됩니다. 버그를 제대로 트래킹해야합니다.

버그 데이타베이스는 복잡할 수도 있고, 간단할 수도 있습니다. 최소한으로 갖추어야할 요소는 다음과 같습니다:

  • 버그를 완벽하게 재현할 수 있는 과정
  • 버그가 없었다면 이루어졌어야할 결과(동작)
  • 버그로 인하여 생긴 결과(동작)
  • 누가 이 버그에 할당되어 있는지
  • 고쳐진 버그인지 아닌지

버그 데이타베이스를 사용하지 않는 이유가 제품들이 너무 복잡해서라면, 이것들을 포함한 5컬럼의 테이블을 만들어서 사용하기 시작하세요.

버그 트래킹에 관해 더 읽으려면, Painless Bug Tracking을 읽으세요.

5. 새로운 코드를 작성하기 전에 버그들을 잡습니까?

마이크로소프트 Windows용 Word의 첫 버젼은 죽음의 프로젝트였습니다. 끝이 없었습니다. 계속해서 스케줄을 펑크냈습니다. 팀 전체는 말도 안되는 시간동안 일했고, 계속해서 연기되고 또 연기되었습니다. 그 스트레스는 엄청났습니다. 빌어먹을 제품이 몇년 후에 출시되었을때, 마이크로소프트는 팀 전원을 Cancun으로 휴가보내고, 이 원인을 분석하기 시작했습니다.

그들이 깨닫게 된 것은 프로젝트 매니저들이 스케줄을 너무 강요하였기 때문에 프로그래머들은 코딩을 빨리 할 수 밖에 없었습니다. 게다가 버그를 고치는 단계는 스케줄에 아예 존재하지 않았습니다. 결과적으로 질이 아주 나쁜 코드를 만들게 되었습니다. 버그 갯수를 줄이려는 노력은 전혀 하지 않았습니다. 한 프로그래머는 텍스트의 높이를 계산하는 루틴 대신에 "return 12;"로 대체하여 버그 리포트로부터 이 값이 어떤 영향을 주었는지를 알고자 했습니다. 스케줄은 단지 버그일 수 밖에 없는 기능들을 모아 놓은 체크리스트였습니다. 나중에 이 상황을 "무한 결함 방식(infinite defects methodology)"이라고 이름지었습니다.

문제를 해결하기 위해서 마이크로소프트는 반대의 "무결함 방식(zero defects methodology)"라는 방식을 체택했습니다. 많은 프로그래머들은 경영진들의 명령에 의해서 버그 갯수를 줄일 수 있다고 생각했음직한 이 방식의 이름 탓에 이를 비웃었습니다. 하지만 실제로는 "무결함(zero defects)"이라는 이름은 주어진 시간에 가장 우선순위가 높은 것은 코딩하기전에 버그를 잡는 것이란 사실을 지칭하는 말이었습니다. 이유는 다음과 같습니다.

일반적으로 버그를 고치지 않고 방치하는 시간이 길어지면 길어질수록 고치는데 더 많은 시간과 금전이 요구된다는 것입니다.

예를 들면, 오타나 문법오류등은 컴파일러가 쉽게 잡아서 고치는데도 별로 문제가 되지 않습니다.

만일 버그가 처음 실행시에 발생하여 보이게 되면, 모든 코드가 머릿속게 생생하게 존재하기에 바로 고칠 수 있을 것입니다.

며칠전에 작성한 코드에서 버그를 찾게 되면 이를 고치기 위해 조금 시간이 더 걸릴 것입니다. 아마도 코드를 다시 보게 되면 대부분의 내용이 기억나고 적정한 시간내에 버그를 고칠 수 있을 것입니다.

하지만 몇달전에 작성한 코드에서 버그가 발견된다면 이미 그 코드에 관해서 많은 것이 이미 생각나지 않을 것이고, 고치기도 상대적으로 힘들 것입니다. 그때쯤 되면 다른 사람의 코드를 수정하고 있는 와중일지도 모르고, 그사람은 Aruba로 휴가를 떠나있을지도 모릅니다. 이렇게 된다면 버그를 고치는 것은 기술을 익히는 것같이 되어버릴 것입니다. 천천히 꼼꼼하게 그리고 주의 깊게 코드를 살펴봐야 하고, 물론 문제를 해결하는데에 얼마나 걸릴지 정확하게 판단하기 힘든 상황이 될 것입니다.

게다가 이미 출하된 코드에서 버그를 발견한다면, 이를 고치는데에 큰 대가를 치뤄야할지도 모를 것입니다.

이렇게 시간이 적게 들기 때문이라는 이유가 하나의 이유가 됩니다. 또다른 이유는 버그를 수정하는데 걸리는 시간을 예상하는 것보다는 새로운 코드를 작성하는데 걸리는 시간을 예상하기가 훨씬 쉽기 때문입니다. 예를 들면, 내가 당신에게 리스트를 소트하는 코드를 만드는데 얼마나 걸리냐고 물어본다면, 꽤 정확한 대답을 할 수 있을 것입니다. 그렇지만, 질문을 바꿔서 당신의 코드가 Internet Explorer 5.5만 설치되어있으면 동작하지 않는 버그를 고치는데 걸리는 시간을 묻는다면, 문제가 무엇인지도 모르는 상황이기 때문에 얼마나 걸릴지 추측하지도 못할 것입니다. 3일이 걸릴 수도 있을 것이고, 운좋으면 2분이 걸릴 수도 있을 것입니다.

이것이 의미하는 바는 고쳐야할 버그가 많이 존재하는 상태의 스케줄이라면 그 스케줄은 정확할 수가 없다는 것입니다. 그렇지만 이미 알고있는 버그들은 모두 고친 상태라면 그 스케줄은 상대적으로 상당히 정확하게 지킬 수 있는 스케줄일 것입니다.

버그 갯수를 0에 가깝게 하는 또하나의 좋은 점은 경쟁에서 훨씬 빠르게 대응할 수 있다는 것입니다. 어떤 프로그래머들은 이를 두고 제품을 바로 출하할 수 있는 항상 유지하는 것이라고 이야기합니다. 경쟁자가 고객들을 가로채갈만한 굉장히 좋은 기능을 새로 만들었다면 축척된 많은 버그를 수정할 필요없이 바로 이 기능을 추가할 수 있을 것입니다.

6. up-to-date(최신) 스케줄을 가지고 있습니까?

비즈니스에 당신의 코드가 조금이라도 중요한 부분이라면, 코드가 언제쯤 완성될 수 있는지를 아는 것 또한 중요하다는 것은 당연할 것입니다. 프로그래머들은 엉터리 스케줄을 만드는데 악명이 높습니다. "언젠가는 될꺼야!"하고 외칩니다.

불행하게도 그런 식으로는 해결할 수 있는것은 없습니다. 비즈니스에는 코드를 출하하기 전에 데모, 전시회, 광고등등 미리 많은 것들을 판단하여 결정해야합니다. 이를 할 수 있는 단 한가지 방법은 스케줄을 가지고 이를 계속해서 현실적으로 최신내용으로 유지하는 것입니다.

스케줄을 가져야하는 또다른 중요한 이유는 이를 통해서 어떤 기능이 필요한지를 결정하게끔 만들어준다는 것입니다. 때문에 어떤 기능이 덜 중요한지 결정해야하고 featuris 가 되기 전에 이들을 포기하도록 합니다.

스케줄을 관리하는 것이 어려울 필요는 없습니다. 제 글Painless Software Schedules 에 좋은 스케줄을 만드는 간단한 방법을 설명하였습니다.

7. spec(설계서)를 가지고 있습니까?

스펙을 만드는 것은 이빨을 쑤시는것과 같습니다: 모든 사람들이 좋다고 인정하지만, 아무도 하지 않습니다.

왜 그런 현상이 일어나는지는 정확히 모르겠습니다만, 아마도 프로그래머들이 문서를 만드는 것을 굉장히 싫어하는데에 기인하는 것 같습니다. 그 결과로, 프로그래머밖에 없는 집단에서 한가지 문제를 해결하고자 하면, 이들은 문서를 만들기 보다는 코드로 자신들의 의견을 표명하려 합니다. 스펙을 먼저 만들기보다는 차라리 코드를 짜서 보여주는 것을 택한다는 것입니다.

설계 단계에서 문제를 발견하면 몇줄을 고쳐서 이를 수정할 수 있습니다. 그렇지만 코드가 짜여진 상황이라면 이 문제를 수정하는 댓가는 감정적으로나(코드를 그냥 버리는 것을 좋아하는 사람은 없습니다) 시간적으로나 훨씬 높게 되고 더 힘든 작업이 되어버립니다. 스펙을 통해서 만들어지지 않은 소프트웨어는 대개 설계가 잘못되어 스케줄을 엉망으로 만들어놓습니다. Netscape에서도 이런 문제로 인해 브라우저의 초기 네개의 버젼이 너무 엉망이 되어 결국 관리자들이 멍청하게도 코드를 전부 버리고 다시 짜도록한 결정을 내려버리게 되는 상황이 벌어졌습니다. 거기다 한술 더 떠서 Mozilla에서 이런 실수를 다시 반복하여 겨우 Alpha 단계에 가는데 몇년이라는 시간이 걸리게 되었습니다.

필자의 지론은 이 문제는 프로그래머들이 문서를 작성하는데 거부감이 없도록 작문 강의를 듣도록 보내는 것으로 해결할 수 있다는 것입니다. 다른 해결책이라면 스펙같은 문서 작성에 능숙한 관리자를 두는 것입니다. 두 경우 모두 "스펙없는 코드는 금물"이라는 간단한 규칙을 따라야 할 것입니다.

저의 4부짜리 글에 스펙 작성하는 요령에 대해 이야기했습니다.

8. 프로그래머들이 조용한 작업환경을 가지고 있습니까?

지식 근로자에게 공간, 조용함, 프라이버시를 줌으로해서 많은 생산성 향상을 얻는다는 것은 이미 증명된 사실입니다. 소프트웨어 관리의 고전인 Peopleware에서는 이 생산성 향상에 대해 자세히 기술합니다.

문제는 여기에 있습니다. 지식 근로자는 "in the zone"상태라고도 하는 "flow"상태에 들어섬으로써 가장 최상의 상태가 되어 일에 완벽히 집중하고 외부에 개의치 않게 됩니다. 완벽한 집중으로 시간 가는 것을 잊고 좋은 결과를 내게 됩니다. 이때에 바로 대부분의 생산적인 일들을 처리하게 됩니다. 작가, 프로그래머, 과학자 그리고 심지어 농구선수들까지도 "in the zone"상태가 있음을 이야기할 것입니다.

문제는 "zone"으로 들어가는 것이 쉽지 않다는 것입니다. 측정해보면, 최상의 생산성으로 일을 하기 위해서는 평균 15분이 걸립니다. 하지만 어떤 경우에는 피곤하고 이미 많은 일을 한 상태에서 "zone"상태에 들어가지 못하고 다른 일을 하거나 웹서핑이나 테트리스로 시간을 허비하게 될 수도 있습니다.

또다른 문제는 "zone"상태에서 빠져나가는 것이 매우 쉽다는 것입니다. 잡음, 전화소리, 점심식사, 잠시 스타벅스에 5분간 갔다오는 것 그리고 특히 동료에 의한 방해등에 의해 바로 "zone"에서 빠져나가게 됩니다. 동료가 1분이라는 짧은 시간 동안이라도 질문을 하여 "zone"상태에서 빠져나간다면 다시 되돌아가기 위해서 30분이 넘는 시간이 걸려 전체 효율에 치명적인 영향을 미칠 수 있습니다. 카페인 가득한 닷컴 회사들이 좋아하는 합숙소같은 곳에 옆의 마케팅 부서에서 계속해서 오는 전화에 대고 소리지르는 그런 시끄러운 환경이라면 계속된 방해로 지식 근로자들의 생산성은 추락하여 "zone"상태에 절대 이르지 못할 수도 있습니다.

프로그래머들에게 있어서 특히 어렵습니다. 생산성은 단기적인 기억력으로 한번에 얼마나 많은 작은 세부사항들을 다루느냐에 달려있습니다. 어떠한 방해도 이런 세부사항들을 잊어버리게 할 수 있습니다. 일을 다시 재개하면 그것들을 다시 기억하지 못하여 (사용하던 지역변수나 검색 알고리즘을 만들던 중에 어디에서 멈줬었는지등) 다시 찾아보게 되고, 이로 인해 다시 속도가 붙을때까지 느려지게 됩니다.

직관적으로 계산해보면 다음과 같습니다. 만일 프로그래머가 단 1분이라도 방해를 받아서(명백한 근거에 의해) 15분의 생산성을 날려버린다고 합시다. 철수와 영희 두 프로그래머가 낮은 칸막이로 주욱 늘어선(a standard Dilbert veal-fattening farm) 열린 사각 파티션 옆자리에 앉아 있다고 합시다. 영희가 strcpy함수의 유니코드 버젼 이름을 잊었습니다. 30초면 찾아볼 수 있겠지만, 철수한테 물어보면 15초가 걸립니다. 그래서 바로 옆에 앉아 있는 철수에게 묻습니다. 철수는 산만해지고 - 영희의 15초를 아끼기 위해 - 15분을 낭비하게 됩니다.

이번에는 벽과 문으로 나뉘어진 별도의 사무실로 가정을 합시다. 여전히 영희는 함수를 기억하지 못합니다. 다시 찾아보는 것으로 30초를 보낼 수 있을 것이고 옆 방에 있는 철수에게 물어보기 위해서 (일반적인 프로그래머의 평균 물리적인 건강상태를 봐서는 쉽지 않은) 일어나서 걷는 것을 포함한 45초를 보낼 수 있을 것입니다. 결국 찾아보는 것을 선택하여 30초를 보내게 되지만 철수의 15분을 벌어주게 됩니다. 대단하죠!

9. 돈이 허락하는 한도내의 최고의 툴들을 사용하고 있습니까?

컴파일 되는 언어로 코드를 작성하는 것은 여전히 아무 PC에서 할 수 없는 것 중의 하나입니다. 컴파일을 하는데 몇초 이상 걸린다면 최상의 기종을 사용함으로써 시간을 절약할 수 있을 것입니다. 15초 이상 걸린다면 지루해서 그 시간동안 The Onion을 읽게 될 것이고 너무 재미있는 관계로 거기에 빠져 수시간의 생산성을 날려버릴 것입니다.

모니터 하나로 GUI코드를 디버깅한 것은 불가능하지는 않지만 고통스러운 작업입니다. GUI코드를 작성하고 있다면, 2대의 모니터로 훨씬 쉬운 작업을 할 수 있을 것입니다.

대개의 프로그래머들은 아이콘이나 툴바를 위해 비트맵을 수정해야하고 대부분의 프로그래머 역시 좋은 비트맵 에디터를 가지고 있지 않습니다. 마이크로소프트에서 기본적으로 제공하는 Paint 프로그램으로 비트맵을 수정하는 것은 웃긴 일이지만 대부분 이렇게 하고 있습니다.

필자의 가장 최근 직장에서 시스템 관리자가 계속해서 자동적으로 스팸을 보냈습니다. 이유인 즉슨 220MB이상의 하드드라이브를 사용하고 있다는 것이었습니다. 필자는 요즘 HD가격을 본다면 이 공간의 환산된 가격은 내가 이용하는 화장실 휴지보다 싸다는 것을 지적했습니다. 디렉토리를 정리하기 위해 10분을 허비하는 정도로도 큰 생산성 저하일 것입니다.

"최고의 개발팀은 절대 그들의 프로그래머들을 고문하지 않습니다!" 후진 제품으로 인한 작은 불편함이 쌓여서 프로그래머들이 불만에 찰 수도 있습니다. 그리고 그로 인한 불만에 찬 프로그래머는 비생산적인 프로그래머이기 쉬울 것입니다.

이런 것들을 모두 종합하면 프로그래머들은 최고/최신의 것들로 쉽게 매수된다는 뜻이 됩니다. 이는 높은 연봉을 주는 것보다는 훨씬 싼 방법일 것입니다!

10. 테스터들을 고용하고 있습니까?

팀이 최소한 2~3명의 프로그래머에게 테스팅만 전담하는 테스터가 할당되어 있지 않다면, 버그가 많은 제품을 출하하고 있거나 시간당 $100짜리 프로그래머에게 시간당 $30의 일을 시키는 낭비를 하고 있는 것입니다. 테스터를 고용하는 것이 낭비로 생각하는 것은 정말 잘못된 계산을 하고 있는 것이며, 많은 사람들이 이를 깨닫지 못하고 있는데에 놀랍니다.

이에 관해 더 자세히 알고자 한다면 Top Five (Wrong) Reasons You Don't Have Testers 를 읽으십시오.

11. 신입사원들은 면접때 코드를 직접 짜는 실기시험을 봅니까?

마법사를 고용하는데 그의 마법을 보지 않고 고용하시겠습니까? 당연히 그렇지 않겠죠.

결혼식에 요리사를 고용하는데 요리사가 만든 요리의 맛도 모르고 고용하시겠습니까? 그렇지 않을것입니다.(역자주: 실제로 결혼식장 요리사의 맛을 보는 비유는 우리나라에 맞지 않을 것 같네요. 이 문구의 뜻만 이해하세요)

하지만 현실에서는 매일 인상적인 이력서나 면접에서 맘에 든 이유로 고용하는 일들이 일어납니다. 혹은 ("CreateDialog()와 DialogBox()의 차이점은 무엇입니까")등의 문서만 보면 알 수 있는 사소한 질문으로 채용하기도 합니다. 프로그래머를 채용하는데 있어서 중요한 것은 그런 사소한 것들을 얼마나 많이 외웠느냐가 아니고 코드를 잘 작성할 수 있느냐입니다. 혹은 "아하!"류의 질문으로 채용하기도 합니다. "아하!"류의 질문이란 답을 알면 간단하지만 모르는 경우에는 절대 맞출 수 없는 질문을 이야기합니다.

제발 이런 방식을 그만 두십시오. 면접때 무얼해도 상관없지만 반드시 코드를 작성하도록 해야합니다.(더 많은 것을 알고 싶다면 Guerrilla Guide to Interviewing를 읽으십시오)

12. hallway usability testing(무작위 사용성 테스팅)을 하십니까?

무작위 사용성 테스트(hallway usability test)는 복도를 지나가는 다음 사람을 붙잡고 방금 짠 코드를 사용하게 하는 방식입니다. 5명에게 이 테스트를 한다면 95%의 사용성 문제에 대해 배울 수 있을 것입니다.

좋은 사용자 인터페이스 설계는 생각처럼 어려운 것이 아니고 사용자들이 당신의 제품을 구입하고 사용하게 하는데 있어서 절대적으로 중요합니다. 짧은 프로그래머 입문서로 UI 설계에 관해 필자가 쓴 무료 온라인 책을 읽어보실 수 있습니다.

하지만 사용자 인터페이스에서 제일 중요한 것은 많은 사람들에게 당신의 프로그램을 보여주면(5~6명이면 충분합니다) 제일 큰 문제점을 빠른 시간에 발견할 수 있다는 것입니다. Jakob Nielsen의 글에서 그 이유에 대한 설명을 찾을 수 있습니다. UI 설계 경험이 별로 없다고 하더라도 - 비용이 전혀 들지 않는 - 무작위 사용성 테스트를 한다면 당신의 UI는 훨씬 좋아질 것입니다.

Joel Test를 사용하는 4가지 방식

  1. 자신이 속한 소프트웨어 팀의 점수를 매기고 그것에 대해 언급할 수 있도록 결과에 대한 이유를 필자에게 알려주십시오.
  2. 프로그래머 팀의 관리자라면, 당신의 팀이 최대한 잘 운영될 수 있는지 확인할 수 있는 지표로 사용하십시오. 12점을 받기 시작하면 프로그래머들을 간섭없이 그냥 두고 비즈니스쪽 사람들이 그들을 간섭하지 못하게 하는데에 모든 시간을 할 수 있습니다.
  3. 프로그래머 일을 맡을지를 결정해야하는 상황이라면 그 팀의 친한 사람에게 이 테스트 결과가 어떤지를 물어보십시오. 결과 점수가 너무 낮다면 이를 고칠 수 있는 권한을 받을 것인지를 확인하십시오. 그렇지 않으면 불만과 스트레스에 빠질 것입니다.
  4. 프로그래밍 팀을 평가하여야 하는 투자자이거나 당신의 회사가 다른 소프트웨어 회사와 합병을 한다면 이 평가가 급한대로 괜찮은 지표가 될 것입니다.


이 기사는 영어로 The Joel Test: 12 Steps to Better Code 라는 이름의 기사가 원본입니다.
Posted by SB패밀리

1. 자신의 기술(cratf)에 관심과 애정을 가져라.
 : 소프트웨어 개발을 잘 해보려는 생각이 없다면 왜 인생을 그 일을 하면서 보내는가?

2. 자신의 일에 대해 생각하면서 일하라!
 : 자동 조종 장치를 끄고 직접 조종하라. 스스로의 작업을 지속적으로 비판하고 평가하라.

3. 어설픈 변명을 만들지 말고 대안을 제시하라.
 : 변병하는 대신 대안을 제시하라. 그 일은 할 수 없다고 말하지 말고, 무엇을 할 수 있는지
   에 대해 설명하라.

 4. 깨진 창문을 내버려두지 말라.
 : 눈에 뜨일 때마다 나쁜 설계, 잘못된 결정, 좋지 않은 코드를 고쳐라.

 5. 변화의 촉매가 되라.
 : 사람들에게 변화를 강요할 수는 없다. 대신, 미래가 어떤 모습일지 그들에게 보여주고 미래를 만드는 일에 그들이 참여하도록 도우라.

 6. 큰 그림을 기억하라.
 : 주변에 무슨 일이 일어나는지 점검하는 일을 잊어버릴 정도로 세부사항에 빠지지 말라.

 7. 품질을 요구사항으로 만들어라.
 : 프로젝트의 진짜 품질 요구사항을 결정하는 자리에 사용자를 참여시켜라.

 8. 지식 포트폴리오에 주기적으로 투자하라.
 : 학습을 습관으로 만들어라.

 9. 읽고 듣는 것을 비판적으로 분석하라.
 : 벤더, 매체들의 야단법석, 도그마에 흔들리지 말라.

   여러분과 여러분 프로젝트의 관점에서 정보를 분석하라.

 10. 무엇을 말하는가와 어떻게 말하는가 모두 중요하다.
 : 효과적으로 전달하지 못한다면 좋은 생각이 있어봐야 소용없다.

 11. DRY - 반복하지 마라(Don't Repeat Yourself)
 : 어떤 지식 한 조각도 하나의 시스템 안에서는 모호하지 않고, 귄위 있고, 단 하나뿐인 표현을 가져야 한다.

 12. 재사용하기 쉽게 만들라.
 : 재사용하기 쉽다면, 사람들이 재사용할 것이다. 재사용을 촉진하는 환경을 만들라.

 13. 관련 없는 것들 간에 서로 영향이 없도록 하라.
 : 컴포넌트를 자족적이고, 독립적이며, 단 하나의 잘 정의된 목적만 갖도록 설계하라.

 14. 최종 결정이란 없다.
 : 돌에 새겨진 것처럼 불변하는 결정은 없다.
   그렇게 생각하는 대신, 모든 결정이 해변의 백사장 위에 쓴 글자와 같다고 생각하고 변화에 대비하라.

 15. 목표물을 찾기 위해 예광탄을 써라.
 : 예광탄은 이것저것을 시도해보고 그것들이 목표와 얼마나 가까운 데 떨어지는지 보는 방법으로 목표를 정확히 맞추게 해준다.

 16. 프로토타입을 통해 학습하라.
 : 프로토타이핑은 배움의 경험이다. 프로토타이핑의 가치는 만들어낸 코드에 있지 않고,
   여러분이 배운 교훈에 있다.

 17. 문제 도메인에 가깝게 프로그래밍하라.
 : 사용자의 언어를 사용해서 설계와 코딩을 하라.


18. 추정을 통해 놀람을 피하라.
 : 시작하기 전에 추정부터 하라. 잠재적인 문 제점들을 미리 찾아내게 될 것이다.

 19. 코드와 함께 일정도 반복하며 조정하라.
 : 구현하면서 얻는 경험을 이용해서 프로젝트의 시간 척도를 세밀히 조정하라.

 20. 지식을 일반 텍스트로 저장하라.

 : 일반 텍스트 형식은 시일이 지났다고 못쓰게 되는 일이 없다.

   일반 텍스트 형식은 여러분의 작업을 활용하고 디버깅과 테스팅을 쉽게 만드는 데 도움이 된다.

 21. 명령어 셸의 힘을 사용하라.
 : 그래픽 사용자 인터페이스로는 할 수 없는 일에 셸을 이용하라.

 22. 하나의 에디터를 잘 사용하라.
 : 에디터를 마치 손의 연장으로 자유자재로 다루어야 한다.

   여러분이 사용하는 에디터는 설정를 바꿀 수 있고, 확장가능하고, 프로그램 가능해야 한다.

 23. 언제나 소스코드 관리 시스템을 사용하라.
 : 소스코드 관리는 여러분 작업을 위한 타임머신이다. 언제라도 과거로 돌아갈 수 있게 해준다.

 24. 비난 대신 문제를 해결하라.
 : 버그가 여려분 잘못인지 다른 사람 잘못인지는 별로 중요하지 않다.

   그것은 여전히 여러분의 문제이며, 여전히 고쳐야 할 필요가 있다.

 25. 디버깅을 할 때 당황하지 마라.
 : 숨을 깊게 들이 쉬고, 무엇이 버그를 일으키는지 '생각하라!'

 26. 'select'는 망가지지 않았다.
 : OS나 컴파일어의 버그를 발견하는 일은 정말 드물게 일어나며, 심지어 써드파티 제품이나 라이브러리 일지라도 드문 일이다. 버그는 애플리케이션에 있을 가능성이 가장  크다.

 27. 가정하지 마라. 증명하라.
 : 진짜 데이터와 경계 조건이 있는 실제 환경에서 여러분이 내렸던 가정들을 증명하라.

 28. 텍스트 처리 언어를 하나 익혀라.
 : 여러분은 하루 가운데 많은 시간을 텍스트와 씨름하며 보낸다. 왜 여러분 대신 컴퓨터
   가 그 일의 일부를 하게끔 만들지 않는가?

 29. 코드를 작성하는 코드를 작성하라.
 : 코드 생성기는 생산성을 증가시키며 중복을 막는 일에도 도움이 된다.  

 30. 완벽한 소프트웨어는 만들 수 없다.
 : 소프트웨어는 완벽할 수 없다. 피할 수 없이 나타나는 에러로부터 여러분의 코드와 사용자
   들을 보호하라.

 31. 계약에 따른 설계를 하라.
 : 코드가 실제로 하기로 한 것을 문서화하고 검증하기 위해 계약을 사용해라.

 32. 일찍 작동을 멈추게 하라.
 : 보통은 죽은 프로그램이 절름발이 프로그램 보다 해를 훨씬 덜 끼친다.

 33. 단정문을 사용해서 불가능한 상황을 예방하라.
 :  단정은 여러분이 세운 가정을 검증해준다.
    확실한 것이 없는 세상에서 여러분의 코드를 보호하려면 단정문을 사용하라.

 34. 예외는 예외적인 문제에 사용하라.
 : 예외를 잘못 쓰면 고전적 스파게티 코드의 모든 가독성과 유지보수 문제를 그대로 겪을지도 모른다. 예외는 예외적인 일들만을 위해 남겨두어라.

 35. 시작한 것은 끝내라.
 : 가능하다면, 리소스를 할당한 루틴이나 객 체가 해제도 책임져야 한다.

 36. 모듈간의 결합도를 최소화하라.
 : 디미터 법칙을 적용하고 '부끄럼 타는(shy)' 코드를 작성해서 결함이 생기는 일을 피하라.

 37. 통합하지 말고 설정하라.
 : 애플리케이션에서 기술 선택을 설정 옵션으로 구현하고, 통합하거나 만들어 넣지 말라.

 38. 코드에는 추상화를, 메타데이터에는 세부 내용을.
 : 프로그램은 최대한 일반화해서 만들고, 세부사항들을 가능하면 컴파일된 코드 기반 바깥으로 빼라.

 39. 작업흐름 분석을 통해 동시성을 개선하라.
 : 사용자의 작업흐름이 허용하는 동시성을 최대한 활용하라.

 40. 서비스를 사용해서 설계하라.
 : 서비스, 곧 잘 정의되고 일관성 있는 인터페이스를 통해 의사소통하는 독립적이고 동시성 있는 객체들의 관점에서 설계하라.

 41. 언제나 동시성을 고려해 설계하라.
 : 동시성이 가능하도록 설계하면, 더 적은 가정만 내리고서도 더 깔끔한 설계를 할 수 있다.

 42. 모델에서 뷰를 분리하라.
 : 애플리케이션을 모델과 뷰의 관점으로 설계 해서 적은 비용만 들이고도 유연함을 얻어 내라.

 43. 칠판을 사용해 작업흐름을 조율하라.
 : 참여하는 요소들의 독립성(independence)과 고립성(isolation)을 유지하면서도 개별적인 사실과 에이전트를 잘 조율하려면 칠판을 사용하라.

 44. 우연에 맡기는 프로그래밍을 하지 말라.
 : 정말 믿을 만한 것만 믿어야 한다. 우발적인 복잡함을 조심하고, 우연한 행운을 목적 의식을 가지고 만든 계획과 착각하지 말라.

 45. 여러분의 알고리즘의 차수를 추정하라.
 : 코드를 작성하기 전에, 실행 시간이 대략 얼마나 걸릴지 감을 잡아 놓아라.

 46. 여러분의 추정을 테스트하라.
 : 알고리즘의 수학적 분석이 모든 것을 다 알려주지는 않는다.

   실제 대상 환경에서 코드의 수행 시간을 측정해보라.

 47. 일찍 리팩터링하고, 자주 리팩터링하라.
 : 정원의 잡초를 뽑고 식물 배치를 조정하는 것과 똑같이, 코드도 필요할 때면 언제라도 다시 작성하고 다시 작업하고 다시 아키텍처를 만들라. 문제의 근원을 해결하라.

 48. 테스트를 염두에 두고 설계하라.
 : 코드를 한 줄이라도 쓰기 전에 테스팅에 대해 생각하기 시작해야 한다.

 49. 소프트웨어를 테스트하라. 그렇지 않으면 사용자가 테스하게 될 것이다.
 : 가차 없이 테스트하라. 사용자가 여러분을 위해 버그를 찾게 만들지 말라.

 50. 자신이 이해하지 못하는, 마법사가 만들어준 코드는 사용하지 말라.
 : 마법사는 엄청난 양의 코드를 만들 수 있다.
   그것들을 프로젝트에 통합해 넣기 전에 그 코드 내용을 전부 이해하는지 확실히 해놓도록 하라.

 51. 요구사항을 수집하지 말고 채굴하라.
 : 요구사항이 지면에 놓여져 있는 경우는 퍽 드물다. 보통은 가정과 오해, 정치의 지층들 속 깊이 묻혀 있다.

 52. 사용자처럼 생각하기 위해 사용자와 함께 일하라.
 : 시스템이 정말로 어떻게 사용될 지 통찰력을 얻을 수 있는 가장 좋은 방법이다.

 53. 구체적인 것보다 추상적인 것이 더 오래간다.
 : 구현 말고 추상에 투자하라. 추상은 서로 다른 구현이나 새로운 기술의 출현 때문에 빗발치듯 생기는 변화를 견뎌내고 살아남을 수 있다.

 54. 프로젝트 용어사전을 사용하라.
 : 프로젝트에서 쓰이는 특정 용어와 어휘들의 유일한 출처를 만들고 유지하라.

 55. 생각의 틀을 벗어나지 말고, 틀을 찾아라.
 : 해결이 불가능해 보이는 문제와 마주쳤을 때, 진짜 제약 조건을 찾아라.

   스스로에게 이렇게 물어보라. '정말로 반드시 이런 방식으로 해야 하는 일인가?

   꼭 해야만 하는 일이긴 한 건가?

 56. 준비가 되었을 때 시작하라.
 : 여러분은 살아오면서 경험을 쌓아왔다. 자꾸 거슬리는 의혹을 무시하지 말라.

 57. 어떤 일들은 설명하기보다 실제로 하는 것이 더 쉽다.
 : 명세의 나선에 빠지지 말라. 언젠가는 코딩을 시작해야 한다.

 58. 형식적 방법의 노예가 되지 마라.
 : 여러분의 개발 실천방법과 개발 능력의 맥락 안에 넣어보지 않고, 맹목적으로 어떤 기법을 채택하지 말라.

 59. 비싼 도구가 더 좋은 설계를 낳지는 않는다.
 : 벤더들의 과장, 어떤 분야의 도그마 그리고 가격표의 휘광에 넘어가지 말라.

   도구 자체의 장점만 갖고 판단하라.

 60. 팀을 기능 중심으로 조직하라.
 : 설계자와 코더를, 테스트 담장자와 데이터 모델 담장자를 분리시키지 말라.

   코드를 만드는 방식에 맞춰 팀을 만들어라.

 61. 수작업 절차를 사용하지 말라.
 : 셸 스크립트나 배치 파일은 똑같은 명령을, 똑같은 순서로, 어느 때라도 반복해서 실행 해준다.

 62. 일찍 테스트하고, 자주 테스트하라. 자동으로 테스트하라.
 : 매번 빌드할 때마다 실행되는 테스트가 책꽂이의 테스트 계획보다 훨씬 효과적이다.

 63. 모든 테스트가 통과하기 전에 코딩이 다 된 게 아니다.
 : 뭐 더 할 말 있나?

 64. 파괴자를 써서 테스트를 테스트하라.
 : 코드의 별도 복사본을 만들고, 그 복사본에 고의로 버그를 넣은 다음 테스트가 잡아내는지 검증하라.

 65. 코드 커버리지보다 상태 커버리지를 테스트하라.
 : 중요한 프로그램 상태들을 파악해서 테스트하라.

   단지 많은 코드 줄 수를 테스트 범위 안에 넣는 것만으로는 충분하지 않다.

 66. 버그는 한 번만 잡아라.
 : 인간 테스터가 버그를 찾아내면, 그 때가 인간 테스터가 그 버그를 찾는 마지막 순간이 되어야 한다. 그 순간 이후부터는 자동화된 테스트가 그 버그를 담당하도록 만들라.

 67. 한국어도 하나의 프로그래밍 언어인 것처럼 다루라.
 : 코드를 작성하는 것처럼 문서도 작성하라.
   DRY 원칙을 존중하고, 메타데이터를 사용 하고, MVC 모델을 쓰고, 자동 생성을 이용 하고 등등.

 68. 문서(document)가 애초부터 전체의 일부가 되게하고, 나중에 집어넣으려고 하지 말라.
 : 코드와 떨어져서 만든 문서가 정확하거나 최신 정보를 반영하기는 더 힘들다.

 69. 사용자의 기대를 부드럽게 넘어서라.
 : 사용자들이 무엇을 기대하는지 이해한 다음, 그것보다 약간 더 좋은 것을 제공하라.

 70. 자신의 작품에 서명하라.
 : 옛날 장인들은 자신의 작업 결과물에 서명 하는 일을 자랑스럽게 여겼다. 여러분도 마찬가지여야 한다.

 

<출처 : 실용주의 프로그래머>

Posted by SB패밀리

http://www.zdnet.co.kr/builder/system/etc/0,39031682,39147115,00.htm

 

 

버그 없는 프로그램은 없다

최진호 (한국 IBM 소프트웨어)   2006/05/04
때는 바야흐로 거미줄력 12년, 버너스 경이 웹과 브라우저를 만들고 웹의 지배 아래 세상이 마우스 클릭질로 시끄럽기 그지없던 시절이었다. 초기의 웹은 그저 집 없는 개인 사용자의 한풀이용으로 홈페이지 제작 기술을 위해 쓰이던 것이었지만 점차 그 허접하던 초기 기술적인 한계를 극복하고 수많은 천재들과 박사들의 컨설팅, 아키텍팅 그리고‘노가다’를 바탕으로 이제는 꽤나 위험할 듯 하고 시스템이 중지되어 버리면 범국가적 위기 상황으로 번질 만한 부분에도 웹이 야금야금 지배하기 시작했다. 바야흐로 전 세계가 거미줄에 대롱대롱 매달려서 살아가고 있는 것이다.

웹은 편하고 단순하고 빠르다. 게다가 돈도 별로 들지 않는다. 이렇게 너도 나도 다 웹 동네에서 살다보니‘가지 많은 나무 바람 잘 날 없다’고 웹 시민들을 끊임없이 괴롭히는 존재가 있었으니 바로 버그라는 놈이었다. 웹 버그는 웹 초기에는 단순히 소스코드 상에서만 숨어있어서 웹 개발자들이 쉽게 끄집어내어 처리하는 것이 가능했으나 점차 웹의 세계가 복잡해지면서 단순히 개발자가 처리할 수 있는 수준을 넘어서게 되었고 이 버그를 해결하는 데 수많은 인력이 투입되기 시작한다. 범기업적, 범국가적, 범세계적으로 문제를 일으킬만한 버그들이 하나 둘 씩 모습을 드러내면서 웹 시민들은 더 이상 이 웹을 좌시할 수 없게 되었으니 이것이 바로 버그 사냥꾼이라는 직업이 태어나게 된 계기가 되었다.

버그 사냥꾼이란?
그렇다면 버그 사냥꾼은 어떤 사람들이며 무슨 일을 하는가? 앞에서도 말을 했지만 웹이 주체할 수 없을 만큼 거대하고 복잡해져 버렸다. 우리가 웹 기반 하에서 서비스를 개발하면 과거에는 해당 서비스를 위해 필요한 다양한 아키텍처적인 요소들을 고려해서 해당 요소들을 거의 모두 개발해야만 했다. 왜냐? 기반이 없었으니까. 즉 보안이나 신뢰성, 성능, 데이터 정합성, 트랜잭션, 확장성 등 거의 모든 부분에서 개발자와 아키텍트들은 그들의 창조성과 능력을 발휘할 수 있었고 그들의 역량에 따라 프로젝트의 실패 유무가 잇따랐다.

사람들은 어떻게 하면 더 예술적이고 효율적으로 시스템을 개발할 수 있을지 고심했고 더 나은 시스템 아키텍처가 있으면 감탄했고 박수를 보냈다. 그러나 시간이 흘러가면서 사람들은 그것이 얼마나 위험천만한 일이고 고비용이 들어가는 일인지를 깨달았고 개발자와 아키텍트가 선별하고 고심해야 했던 아키텍처 요소들을 대신 처리해줄 수 있는 여러 컴포넌트와 미들웨어 제품들을 사용하기 시작했다. 이러한 선택은 웹 시스템 개발에 들어가는 인력과 시간을 줄여주는 듯해 보였고, 점차 순수한 소프트웨어 아키텍트는 손가락을 빨게 됐다. 이제 개발자가 하는 일이라고는 웹 화면의 단순한 인터페이스 노가다이거나 단순 로직에 대한 작업 등을 벗어나지 못했고 이러한 단순 노가다만으로도, 별다른 수고없이 보안이나 성능, 트랜잭션, 확장성 등이 어느 정도 이상 충족되어 가고 있었다. 결국 개발자가 작업한 내용은 전체 시스템에서 보자면 빙산의 일각이었고 눈에 보이는 소스코드 이면에는 그것들에 대한 아키텍처 요건들을 처리해주는 수많은 컴포넌트와 미들웨어 제품들이 얽혀있는 상황이 된 것이다.

문제는 여기에서 발생한다. 웹 시스템에 버그가 발생했을 때 이제는 개발자 한 두 사람이 분석해서 원인을 파악하는 것이 불가능해질 정도로 종합적인 문제 분석 능력이 필요해진 것이다. 때문에 웹 시스템에 버그가 발견되면 해당 사이트에 하드웨어 전문가와 네트워크 전문가, DB전문가, 미들웨어 전문가, 개별 컴포넌트 제품 전문가, 개발자, 운영자 등이 모여서 어디서 문제가 발생한 것인지를 종합적으로 분석해야 하는 상황이 발생하는 경우가 다반사가 되었다. 그래서 이 장애 전문 해결사로서 버그 사냥꾼이라는 직종이 탄생하게 되었다.

버그 사냥꾼 중에서도 특히 미들웨어 전문가의 역할이 매우 중요하게 되었는데, 거의 모든 문제가 발생하는 첫 번째 장소이자 시작 시점으로 거론되는 곳이 바로 이 미들웨어 쪽이기 때문이다. 즉 과거에는 개발로서 해결하던 여러 가지 요소들이 미들웨어 쪽에서 처리되면서 크리티컬한 부분에서의 버그 역시 미들웨어가 처리하게 되었다. 때문에 미들웨어 쪽 버그 사냥꾼의 지식 체계는 넓고 깊다. 왜냐하면 실제로는 하드웨어나 네트워크에 문제가 있어도 일단은 미들웨어에서 문제가 감지되고 소스코드 상에서 버그가 있어도 미들웨어에서 발견할 수 있다. 성능이 문제여도 미들웨어 쪽에서 전체적인 분석을 해야 하는 상황이다 보니 미들웨어 쪽 버그 사냥꾼은 만물박사가 되지 않을 수가 없다. 그들은 때때로 성능이나 개발에 대한 작은 컨설팅까지 해가며 웹 시민들의 안녕을 위해 고군분투하고 있다.

버그 사냥꾼 스파이크
그래서 이번 기사에서는 버그 사냥꾼 스파이크씨를 소개할까 한다. 그는 모 회사에서 판매하고 있는 웹 애플리케이션 서버 제품에 대한 기술지원을 담당하고 있는 경력 5년의 버그 사냥꾼이다. 그가 주로 하는 일은 회사가 판매하고 있는 제품을 구매해서 쓰고 있는 고객들이 개발이나 운영 중에 제품에 문제가 발생했을 때 문제를 해결해주는 것이다. 그러나 웹 애플리케이션 서버라는 것이 위로는 사용자의 요청을 받아서 일차적으로 처리하는 웹 애플리케이션과 맞닿아 있고 아래로는 DB나 네트워크, 하드웨어, Legacy 등의 리소스와 연결되어 있다보니 일단 고객이 뭔가 서비스가 되지 않으면 무조건 스파이크씨를 부른다. 그러면 스파이크씨는 전체 시스템을 모니터링하면서 문제의 원인을 분석하고 고객에게 해결책을 알려주는 것이다. 이런 그에게 최근 웹 시스템에서 발생하는 버그의 유형에 대해 의견을 물어보았다.

버그요? 말도 마세요. 버그 같은 버그, 정말 웹 애플리케이션 서버에 문제가 있어서 생기는 버그면 말도 안하죠. 미들웨어라는 게 눈에 보이지는 않으면서 하는 일은 무진장 많으니까 걸핏하면 저를 호출하는데요, 사실 일어나는 문제 중의 상당수는 개발 쪽이나 DB 그리고 서버에서 생기는 문제예요. 사이징을 제대로 하지 못해서 생기는 경우도 많죠. 그래도 일단 에러 로그는 웹 애플리케이션 서버 쪽에서 나오니까 일단 고객은 저를 부르는 거에요. 그런데 사실 요새에는 개발 쪽에서 생기는 버그도 많질 않아요. 워낙에 개발자들의 능력도 좋아졌지만 개발자들이 웹 개발에서 해볼만한 게 없거든요. 대부분의 중요한 로직들은 웹 애플리케이션이 해결해주니까 단순한 버그는 많지 않은거죠. 다들 버그, 버그 하지만 요새처럼 버그 잡기 어려운 시절이 어디 있겠어요? 버그 잡는 거 쉬운 노릇이 아니거든요. 하드웨어부터 개발까지 IT 지식 전반적인 것들을 다 알아야만 버그를 잡을 수가 있는거죠. 아무나 버그 사냥꾼 하는거 아니거든요.

횡설수설하는 스파이크씨의 인터뷰를 통해서 그가 얼마나 쌓여있는 할 말이 많은지 알 수가 있다. 버그 사냥꾼의 입장에서 과연 최근의 웹 기반 시스템에서 발생하는 버그의 유형은 어떠한 것들이 있는지 살펴보자.

버그의 종류
스파게티 코드와 리소스에 대한 정확한 사용
세상이 많이 변하고 변했지만 아직까지도 이런 허접한 코드를 보면 왕짜증이죠. 개인 홈페이지 만드는 것도 아니고 명색이 대기업 홈페이지라고 해서 들어가 보았더니 JSP 코드에 DB 호출하려고 JNDI 룩업해서 직접 DB랑 쿵작쿵작하는 걸 박아놓고 있더라구요. 정말 한숨부터 나옵니다. 그래도 좀 안다 하는 운영자분들은 미안해하기라도 하지요. 요즘 웹 개발에서 그나마 전체 시스템을 망가뜨릴 수 있는 이슈는 리소스 관리에요. 예를 들어 개발자가 코딩하면서 DB 리소스만 공손하게 사용해준다면 웹 애플리케이션에서 생기는 버그의 반 이상은 방지할수 있을 거예요. 그런데 JSP 코드에 로직과 뷰가 분리되기는커녕 오묘한 조화로 손잡고 있으면 정말 버그 잡기도 힘들 뿐더러 리소스에 대한 반환이 제대로 되는지 파악조차 사실 잘 안 되거든요. 확장성에도 문제가 있고. 아무튼 이런 구석기 시대코드는저질버그를양산하는창고같은역할을하는거죠.

스파이크씨도 과거에는 웹 개발자였다. 특히 그는 php 전문 개발자였는데 초짜시절에 그 역시 php로 무수한 스파게티 코드를 작성한 경험이 있다. 자유로운 php라는 언어의 특성상 개발 속도가 빨랐고 단시일 내에 원하는 사이트를 개발하는 것은 어렵지 않았지만, 초짜시절 그는 지인을 통해 아르바이트로 자그마한 컴퓨터 회사의 홈페이지를 php로 개발하게 되었다. 하루가 지나니 게시판이 생기고 또 하루 지나니 견적 페이지가 만들어졌다. 그렇게 후다닥 만들어진 홈페이지는 고객과 홈페이지 주인의 원망을 듣는 버그 투성이 사이트로 전락해버렸다. 객체지향이고 뭐고 없이 생각나는 대로 만들어진 스파게티 코드는 나중에 다시 고쳐보려 해도 어찌할 수 없을 만큼 복잡해진 말썽꾸러기가 되어버리고 만 것이다. 그러나 이런 사례는 사실 요 근래에는 많이 찾아볼 수 없거나 혹은 이러한 로직과 뷰의 분리가 완전히 되어 있지는 않더라도 중요한 비즈니스 로직 정도는 컴포넌트화 시켜놓는 것이 요 근래의 추세이다. 이것은 그동안 웹 기반 개발자들이 양적으로 뿐만 아니라 질적으로도 많은 향상을 보여왔음을 뜻하는 것이다.

스파게티 코드와 함께 웹 기반 시스템에서 웹 개발자가 실수하는 것들 중의 하나가 리소스에 대한 해제를 제대로 해주지 않아서 전체 시스템에 무리가 가게 만든다는 것이다. 또한 서블릿 사용시 쓰레드 기반 프로그래밍에 익숙하지 않은 개발자가 리소스 변수에 대한 잘못된 사용으로 인해 부하를 일으키는 경우도 종종 있는 일이다. 사실 이러한 현상은 무조건 개발자의 탓으로만 돌릴 것이 아니라 문제가 될 만한 소지가 있는 부분들을 미연에 방지할 수 있도록 별도의 공통 컴포넌트로 끄집어내서 통합관리를 하는 등의 개발 환경을 구축해 놓아야만 해결될 수 있을 것이다.

몇 달 전 스파이크씨가 고객의 요청으로 들어간 사이트에서 있었던 일이다. 평소에는 이상 없이 잘 돌아가던 시스템이 부하가 어느 정도 쌓이면 갑자기 행(hang) 현상이 발생하면서 웹 애플리케이션 서버가 죽어버렸다. 늘 있어왔던 현상이고 이런 경우 대부분 애플리케이션에서 리소스 관리를 제대로 하지 못했기 때문에 발생하는 경우가 다반사였다. 역시나 문제는 애플리케이션 쪽이었다. 각각의 JSP 코드에서 직접 DB 리소스를 가져와서 함부로 썼던 것이다. 즉 그 수많은 JSP 코드에서 직접 DB를 연결하여 필요한 작업을 수행하고서는 때때로 연결을 닫지 않기도 하고 예외처리도 엉성하게 되어 있었다. 더구나 JSP 코드는 로직과 뷰가 전혀 분리되지 않은 상태이다보니 문제를 해결하는것도 어렵기 그지없었다. 천상 스파이크씨는 고객에게 애플리케이션에서 DB 리소스 해제를 제대로 해주지 않은 것이 문제여서 발생한 것임을 보고했고, 되도록이면 DB 제어에 대한 부분은 기업 공통 컴포넌트를 작성하여 그것을 전사적으로 사용할 것을 권했다. 또한 웹 개발자들에게 좀 더 좋은 교육의 기회를 제공하여 웹 프레임워크나 기타 기업 내의 프레임워크 등에 대한 가이드라인을 다시 한 번 제시할 것을 권고했다.

이러한 스파게티 코드와 정확치 않은 리소스 사용으로 인한 버그는 많이 발생하기도 하지만 문제의 원인이 분명한 만큼 스파이크씨가 짜증내는 일면 쉽게 해결할 수 있는 범위에 속한다는 측면에서 반가운 현상이기도 하다. 하지만 스파이크씨가 다음으로 언급하는 여러 상황들은 스파이크씨에게도 참으로 버거운 버그들, 고급 버그들이다.

시스템 및 프레임워크에 대한 이해 부족
생각있는 운영자들이 가장 꺼려하는 것 중의 하나가 무엇인지 아세요? 최신 기술입네 하고 무턱대고 개발자들이 인기있는 오픈소스 프레임워크를 도입해서 써버리는 경우에요. 문제는 그 프레임워크가 얼마나 신뢰할만 하냐는 거죠. 그 프레임워크를 썼는데 막상 운영하고 보니 치명적인 문제가 발생하면 대체 누구에게 하소연하겠습니까? 개발자는 그제서야 부랴부랴 오픈소스를 뜯어고치거나 이미 어디론가 회사를 옮겨버린 후란 말이죠. 게다가 무턱대고 프레임워크를 도입해버리면 그 프레임워크를 알고 있는 개발자는 어떻게든 문제를 해결한다하더라도 향후 업그레이드나 확장을 해야 할 시점이 왔을 때 생소한 프레임워크 때문에 개발에 드는 비용보다 프레임워크를 이해하는 데 드는 비용이 더 커져버린다 이겁니다. 저도 지원을 하다보면 이렇게 프레임워크에서 문제가 발생한 경우에는 어떻게 손을 쓸 수가 없어요. 그 프레임워크를 들어내라고 할수도 없고 말이죠. 게다가 프레임워크의 철학을 제대로 이해하지도 못하고 써버리면 문제는 아주 골치아파지는 거죠.

자바 엔터프라이즈 기술 중 EJB는 상당히 성공한 컴포넌트 기반의 기술이다. 수많은 서적에서 EJB를 다루었고 마치 JEE의 수준 높은 개발을 이루려면 EJB를 써야 하는 것처럼 보이기도 한다. EJB는 결국 웹 기반 서비스에서 트랜잭션과 분산처리가 꼭 필요한 요소가 있을 때 그러한 위험을 대신 처리해주기 위해 탄생했다. 물론 비즈니스 로직에 대하여 EJB로 만들어두고 추후 두고두고 쓰겠다고 마음먹겠다면, 그리고 EJB라는 좋은 프레임워크 안에서 개발을 하겠다는데 말릴 사람은 아무도 없을 것이다.

그러나 EJB를 통해서 얻을 수 있는 것이 있다면 반대로 잃는 것이 있게 마련이다. 우선 속도의 문제를 들을 수 있다. RMI Call을 통한 분산 컴포넌트 기술이다보니 아무래도 직접 메쏘드 호출에 드는 비용보다 많을 수밖에 없다. 또한 EJB 기술을 충분하게 숙지하지 않은 개발자일 경우 잘못된 설계와 사용으로 인하여 오히려 사용 안하느니만 못한 결과를 종종 가져올 수 있다. 왜냐하면 EJB는 성숙한 JEE 기반의 설계 지식을 바탕으로 개발되었을 때 그 기능을 십분 발휘할 수 있는 것이지, 비즈니스 로직과 도메인 로직에 대한 분리 개념 없이 접근했다가는 큰코 다칠 기술이기 때문인 것이다. 이런 이유로 가뜩이나 무거운 JEE 환경에서 EJB 호출이 너무나 빈번히 발생하여 전체 시스템에 오버헤드가 일어나는 경우 그 결과는 느려진 서비스와 고비용으로 귀결될 뿐이다.

재차 강조하자면 앞에서도 언급했듯이 웹 기반 시스템에서의 버그가 점점 개별적인 소스코드에서 프레임워크나 전체 시스템단으로 옮겨오는 추세이다. 때문에 전체 시스템과 도입된 프레임워크에 대한 충분한 이해 없이 개발된 시스템은 결국 버그를 양산해낸다. 그 중에서도 프레임워크에 따른 폐해는 정말 심각하다. 문제는 해당 프레임워크가 검증되지 않았다는 것과 프로젝트에 참여하는 개발자 전원이 프레임워크에 대한 이해가 충분하느냐에 있다. 소프트웨어는 단지 바이너리 데이터 덩어리만을 의미하지는 않는다. 소프트웨어에는 고객이 있고 개발 프로세스가 있고 문서가 있으며 유지보수에 따른 절차가 포함된다. 이러한 소프트웨어의 필요충분조건을 무시하고 신뢰성에 대한 검증과 유지보수에 대한 확실한 책임 소지를 분명히 하지 않을 경우 어줍잖은 프레임워크 도입은 오히려 더 큰 버그를 양산하는 요소가 된다.

충분한 테스트 없이 운영
요새 프로젝트를 보면 개발에 걸리는 시간보다는 테스트에 걸리는 시간이 훨씬 많이 소요되고 그 중요성이 증대되고 있는것 같아요. 그만큼 운영 환경에서의 검증작업을 확실하게 한다는 얘긴데요. 그럼에도 불구하고 평상시에는 잘 돌아가던 것들이 운영 때만 되면 꼭 문제가 일어나요. 테스트할 때 제대로 운영 환경에 맞추어 시나리오를 구성하지 못했다는 것이고 운영 환경을 제대로 예측하지 못한 결과이기도 하죠.

지금도 여전히 스파이크씨는 운영 하루 만에 시스템이 정지된 고객의 현장에 출동하느라 여념이 없다. 그만큼 운영과 테스트는 다르다는 것을 입증하는 것이리라. 또한 이것은 단순히 운영과 테스트가 다르기 때문에 일어나는 당연한 현상이라고 넘겨버리기에는 아쉬운 무언가가 있다. 즉, 고객이 테스트의 중요성을 제대로 인식하지 못한 경우에 발생한다는 것이다.

며칠 전 스파이크씨는 고객의 신규 오픈 사이트 통합 테스트 현장에 출동했다. 테스트 중 웹 애플리케이션 서버에서 문제가 발생했을 때를 대비하여 같이 모니터링을 요청한 것이다. 테스트 현장에는 몇 명의 애플리케이션 개발자와 운영자 그리고 부하테스트 전문가들이 모여 있었다. 늦은 밤 시간이었고 개발자들은 하나같이 초췌함 일색이었다. 저녁 9시에 성능 테스트가 시작됐다. 그런데 테스트는 단 30분도 더 진행시킬 수가 없었다.왜냐하면 애플리케이션에서 버그가 발생했기 때문이었다!

스파이크씨는 황당했다. 분명 그 통합 테스트는 성능 테스트였다. 그렇다면 적어도 한번쯤은 애플리케이션에 대한 단위 테스트 정도는 해보았을 것이 아닌가? 스파이크씨가 개발자에게 물어보니 단 한번도 애플리케이션에 대한 통합 테스트를 이전까지 진행해본 적이 없다고 한다. 결국 그 날의 테스트 현장은 파장되었고 개발자는 성능 테스트에서 발생하여 접수된 버그를 해결하기 위해 밤을 샜다.

통합 테스트는 운영 테스트와 성능 테스트로 분류할 수 있고 이러한 통합 테스트 이전에 각각의 애플리케이션들에 대한 충분한 단위 테스트와 애플리케이션 별 통합 테스트가 선행되어야만 한다. 그런데 이러한 순차적인 과정을 무시하고 오픈이 얼마 남지도 않은 시점에서 개별 애플리케이션들에 대한 기본적인 버그조차 해결되지 않은 상황에서 성능 테스트한답시고 밤을 새워가며 애플리케이션 성능이 나오지 않음을 탓하는 경우를 스파이크씨는 가끔 목격하곤 한다. 테스트는 아무리 강조해도 지나치지 않으며 테스트 기간 산정은 시스템의 신뢰성을 가름하는 가장 중요한 잣대가 될 수도 있다.

제품에 문제가 있는 경우
버그 중에 저 같은 버그 사냥꾼들이 가장 무서워하는 것이 제품 버그죠. 새 버전의 웹 애플리케이션 서버가 출시되면 일단 처음에 겁부터 나요. 이번엔 어떤 버그가 있을까? 하구요. 제가 담당하고 있는 제품이 그래도 이 바닥에서는 유명하고 검증받은 제품인데도 가끔씩 황당한 버그를 발견하곤 하거든요. 세상에 버그없는 소프트웨어가 어디 있겠어요? 하지만 특히 웹 애플리케이션 서버 버그는 찾기도 어렵고 치명적인 경우가 많아서 신경이 많이 쓰이죠. 보통 문제가 발생한 사이트에 나가면 문제의 원인이 어디에 있는지 추적해 들어가는데, 전체 IT 인프라부터 개별 애플리케이션까지 다 추적해보거든요. 그런데 결국 추적의 방향이 웹 애플리케이션 서버 자체의 결함으로 결론지어지면 고객에게 할 말이 곤궁해져요. 금방 고칠 수 있는 거면 고치지만 제가 개발한 것도 아니다보니 시간이 길어질 수밖에 없어요. 아무튼 이런 경우 입이 바짝 바짝 마릅니다.

보통 고객에게 제품을 판매하기 전에 정말 이 제품이 제 성능을 발휘하는 지를 보여주기 위해 때때로 벤치마크 테스트를 고객이 보는 앞에서 시연하는 경우가 있다. 스파이크씨는 몇 달 전 고객에게 웹 애플리케이션 서버의 성능을 보여주기 위해 벤치마크 테스트에 참여했다. 테스트는 클러스터링된 환경에서 여러가지 패일오버(Failover)와 세션 클러스터링 그리고 고객의 샘플 애플리케이션에 대한 성능 테스트였다. 웹 애플리케이션 서버에서 클러스터링 기능은 가장 기본이 되는 기능이기 때문에 비록 새 버전의 제품이기는 하지만 결국 같은 제품 라인이므로 스파이크씨는 큰 무리없이 테스트가 진행되리라 생각했다.

그러나 이후 엄청 황당한 경험을 해야 했다. 클러스터링으로 묶여있는 서버군 중 하나의 서버를 임의로 중지시키고 다시 가동시켰더니 나머지 다른 하나의 서버가 죽어버리는 현상이 발생한 것이다. 아마도 세션 정보를 서로 공유하다가 무언가가 꼬여버린 것 같은데 전날 테스트할 때에는 아무런 문제가 없다가 특정 상황에서 그것도 하필 고객이 바로 옆에 있는 그 상황, 너무나 중요한 그 상황에서 제품은‘엿 먹으라는 듯’버그를 발생시키고 만 것이다. 스파이크 씨를 비롯한 회사의 모든 사람들의 얼굴은 흙빛이 되었고 그 날 테스트는 그것으로 끝이 났다. 그 이후로 스파이크씨는 밤새도록 제품 개발자와 문제를 재현하여 해결하는데 많은 시간을 들였고 결국 단순히 하나의 클래스를 교체함으로써 더 이상 해당 버그는 발생하지 않았다.

앞서 언급한 것처럼 웹 시스템 개발자가 담당하는 역할 상 리소스에 대한 제대로 된 사용만 철저히 한다면 전체 시스템에 걸쳐 영향을 미칠 수 있을만한 여지가 적은 반면에 미들웨어에서 상대적으로 처리해주는 기능이 많아지다 보니 만약에 이러한 미들웨어가 부실한 신뢰성을 가진다면 그 파급 효과는 상당한 것이다. 때문에 미들웨어를 선택할 때에는 신뢰할만한지 지원은 얼마나 철저한지를 제대로 점검해보지 않으면 두고두고 전체 IT 인프라를 좀먹을 수 있는‘악의 근원’이 될 소지가 있다.

나무를 보지 말고 숲을 보자
가장 황당한 버그는, 사실 이건 버그도 아닌데요. 사람들은 문제가 발생하면 아무래도 시야가 좁아지죠. 개발자는 소스에 이상이 없는지만 살피게 되고 운영자는 운영 환경만 살펴보게 되죠. 그런데 문제는 정말 엉뚱하게도 너무나 당연하게 생각했던 부분에서 해결되는 경우가 많아요. 이를테면 네트워크 선이 뽑아져 있었다든지, DB 서버가 잠시 죽어있었다든지 우리가 평소에 당연히 되리라고 믿어 의심치 않는 요소들이 문제여서문제 상황이 지체되는 경우가 심심치 않게 일어나죠. 그래서 가끔 지원나갔다가 랜선 뽑아져 있던거 연결해주거나 시스템만 한 번 껐다 켜주고 돌아오는 경우가 의외로 많지요. 이런 상황이 있으니 저처럼 미들웨어 쪽 기술 지원하는 사람이 만능박사가 될 수밖에 없는 거죠. 일도 많지만 그만큼 전체 시스템을 보게 되는 힘을 기를 수 있어서 즐겁습니다.

어느 중요한 고객으로부터 스파이크씨에게 연락이 왔다. 엄청나게 성능 좋은 서버를 도입해서 프로젝트를 진행하고 오픈이 얼마 남지 않았는데 성능이 제대로 나오질 않아서 난리가 났다고 한다. 허접한 오픈소스 제품으로 돌릴 때만도 못한 성능이 나오니 이것은 분명 스파이크씨가 담당한 제품의 문제이고 이것을 해결하지 못하면 앞으로 장사 못할 줄 알아라고 말한다. 다급한 스파이크씨 곧장 고객에게 달려간다.

실제로 문제 상황을 보니 같은 웹 애플리케이션을 실행하는데 유독 스파이크씨가 담당한 제품에서만 느린 것을 확인했다. 스파이크씨는 당연히 제품만의 문제로 규정하고 제품의 버그를 찾기 시작했다. 애플리케이션의 알고리즘을 바꿔보기도 하고 버그 리스트를 찾아보기도 했으며 다른 서버 환경에서의 차이점도 분석해보았다. 그러기를 며칠, 결론은 제품의 문제인 것 같기는 하지만 다른 서버에서는 전혀 발생하지 않는 문제라는 것이다. 결국 문제는 고객이 최신 기종이랍시고 들여온 서버에 문제가 있음을 검증하는 단계에 이르렀고 스파이크씨가 며칠 동안을 애써가며 웹 애플리케이션 서버안의 문제를 파헤쳤던 수고는 공염불이 돼버렸다. 즉, 애초에 스파이크씨가 문제의 원인을 좀 더 다각도로 바라보았다면 일찍 서버에 문제가 있었음을 간파할 수있었을 것이며 상황은 훨씬 빨리 종결될 수 있었을 것임에도 불구하고 고정관념에 사로잡혀 하나의 포인트만을 바라보다 보면 숲을 보지 못하는 결과가 생길 수 있음을, 즉 문제는 의외로 다양한 곳에서 복합적으로 일어날 수 있음을 간과한 결과라고 할 수 있겠다.

이렇게 숲을 보지 못해서 쉽게 해결할 수도 있는 문제가 오래동안 여러 사람의 밤잠을 설치게 하는 경우는 스파이크씨에게 비일비재하다. 밤늦게 전화가 온다. 급하게 어느 사이트에서 장애가 발생했는데 웹 애플리케이션 서버 쪽 문제인 것 같다. 그러니 빨리 와 달라. 그래서 찾아간 고객의 사이트에서 스파이크씨가 한 일이라고는 고작 랜 선 꽂아주고 라우터 한 번 껐다 켜준 일 밖에 없을 때 고객과 스파이크씨는 서로 얼마나 X씹은 얼굴일지 상상해보라. 그러니 문제가 발생했을 때에는 일단은 먼저 숲을 바라봐야 한다. 숲을 바라본 다음에 우리가 가진, 문제의 원인일 것이라고 생각하는 고정관념을 배제한 상태에서 문제의 원인을 추적해 들어가는 것. 그것이 웹 기반 시스템에서 문제를 접하는, 스파이크씨가 권하는 방법론이다.

웹 기반 시스템 버그 해결 프로세스
앞서 버그 사냥꾼 스파이크씨의 경험을 토대로 웹 기반 하의 시스템에서 어떠한 버그들이 있는지 사례별로 살펴보았다. 스파이크씨의 말처럼 웹 기반에서의 시스템이 일으키는 버그는 여타 다른 아키텍처에 비하여 상당히 복합적이고 다층적인 관점에서 문제 해결 능력을 필요로 한다는 것을 여실히 느낄 수 있을 것으로 생각한다.

<그림 1> 웹 기반 시스템 버그 해결 프로세스

여기서 짚고 넘어가야 할 것은 어느 문제 상황에서나 스파이크씨처럼 다양한 문제 해결 경험을 가진 이가 여러분 곁에 있을수는 없다는 것이다. 버그는 사람을 가리지 않고, 오히려 상황이 다급하고 주위에 전문가가 없을 때 더 잘 나타난다. 그게 버그의 습성이다. 따라서 필자는 스파이크씨에게 과연 웹 기반 시스템에서 버그를 해결하기 위한 방법론은 없겠는가 물어보았다. 스파이크씨는 비록 웹 기반 시스템이 복합적인 성격을 가지고 다양한 지식과 경험을 가진 이의 분석을 필요로 하는 것은 맞지만 그럼에도 불구하고 어느 정도의 수준을 가진 개발자 내지 운영자가 문제를 해결하는 데 있어 쉽게 접근해 볼 만한 방법론을 제시했다.

어디서 시작할까?
문제가 발생하고 버그가 예상되었을 때 디버깅을 하기 이전에 먼저 전체 웹 시스템이 어떻게 운영되는지를 점검해볼 필요가 있다. 만약 시스템 아키텍처에 대한 간략한 구성도가 있다면 그것을 보면서 점검해보면 좋을 것이다. 과연 아키텍처 각각의 구성원들이 서로 어떻게 연결되어 있는지를 살펴보자. 웹을 구성하고 있는 아키텍처 상에는 생각보다 상당히 많은 구성원들과 리소스 그리고 메시지 프로토콜로 이루어져 있는 것을 알아챌 수 있으며 이와 관련하여 당신이 운영자가 아니라면 운영자와 대화를 통해 각 구성상의 취약점은 없었는지 그리고 최근에 벌어졌던 다른 문제 상황과 변경된 사항들을 먼저 수집해 나가야 한다.

던져야 할 질문들
넓고 넓은 시스템 아키텍처 중에서 가장 먼저 살펴봐야 할 그 곳은 어디일까? 그 곳을 찾는 것이 문제 분석의 첫걸음이다. 이 결정을 위해 몇 가지 간단한 질문을 스스로에게 던져보아야 한다. 첫 번째로 이 문제의 증상은 무엇인가? 만약 에러 메시지가 클라이언트 브라우저에서 발생한 것이라면 아무래도 클라이언트와 맞물려 있는 여러 구성요소들을 의심해 볼 만할 것이다. 아니면 특정 프로세스가 죽거나 행 현상이 발생했다면 이것 역시 가장 먼저 살펴 볼 그 곳을 결정하는 데 중요한 단서가 된다. 물론 해당 프로세스가 죽거나 행 현상이 발생했다면 다음 절차는 해당 프로세스에 대한 행동을 기록하고 있던 로그 파일을 보는 행위가 될 것이 명백하다.

두 번째로 가져야 할 질문은‘언제 해당 증상이 발생하는가?’이다. 발생하는 시간과 발생하는 주기 등이 문제의 본질에 대해 이해하는 데 매우 중요한 단서가 된다. 예를 들어 사용자가‘계정 정보’페이지를 클릭할 때면 무조건 에러 메시지가 출력된다면 너무나 당연하게도‘계정 정보’와 관련된 소스코드를 먼저 볼것이다. 반면에 사용자 트래픽이 매우 높을 때에만 발생하는 현상이라면 무언가 시스템 리소스와 관련이 있는 문제라는 것을 직감할 수 있을 것이다. 반면에 아무런 시기적인 유사성이 없는 상황에서 발생하는 문제라면 이 문제에 제3의 구성원의 개입이 있을 수 있거나 좀 더 시간과 상황에 따른 유사성을 발견해내야할 것이다. 하지만 이렇게 간헐적으로 발생하는 문제가 가장 해결하기 어려운 문제임은 확실하므로 단단히 긴장해야 한다.

세 번째로 가져야 할 질문은‘최근에 시스템 변경사항은 무엇이었는가?’이다. 최근에 애플리케이션 혹은 시스템에 변경 사항은 없었는가? 무언가가 변경이 되었다면 그것이 원인이 되어 발생한 문제 혹은 버그임을 우선 의심할 수 있을 것이다.

버그를 고립시키기
쥐를 잡아본 적이 있는가? 쥐를 잡으려면 일단 쥐가 어디에 숨어있는지를 알아야 하고 위치를 알았다면 적절한 도구로 쥐를 야금야금 몰아가야 한다. 자 이제 어디에 버그가 숨어있는지를 눈치 챘다면 적절한 도구로 버그 사냥에 들어간다.

디버깅 툴
웹 기반 시스템에서 발생한 버그라는 것이 대부분 런타임 환경에서 발생하는 경우가 많기 때문에 디버깅하기가 상당히 까다롭기는 해도 요즘 출시되고 있는 각종 개발 툴에서는 런타임에서의 디버깅 환경이 꽤 유용할 만큼의 환경을 제공해준다. 그럼에도 불구하고 디버깅 툴에는 어느 정도 한계가 있다. 그 첫 번째가 운영환경에서의 버그일 경우 디버깅 툴로서는 잡아내는 게 여의치 않다는 것이다. 이를테면 사용자 접속이 얼마 이상일 때 발생하는 버그일 경우 주로 객체와 메시지 자체에 대한 정보만을 바라볼 수 있는 디버깅 툴만으로는 현상 파악에 무리가 있는 것이다. 따라서 자세한 정보를 위해서라면 한 손에는 디버깅 툴을 그리고 다른 손에는 또 다른 유용한 툴을 지니고 있어야 한다.

로그 파일
거의 대부분의 프레임워크와 미들웨어 및 리소스 관리 툴에서는 로그 파일을 남긴다. 때때로 특정 제품의 경우 성능 등의 이유로 최소한의 로그만을 남기는 경우가 있는데 대부분 로깅 수준을 조절하여 더 세밀한 정보를 볼 수가 있다. 로그 파일에는 단순히 각각의 서버가 제공하여 주는 것들 이외에도 JVM이나 네트워크스위치 등이 제공해줄 수 있는 파일(쓰레드 덤프와 힙 덤프 등)들도 있다. 이 뿐만 아니라 문제가 발생하고 있는 부분에 대한 자세한 추적을 위한 로그를 별도로 추가함으로써 문제의 원인을 좀 더 막다른 골목으로 좁혀볼 수 있을 것이다. 따라서 전체 시스템 아키텍처 구성도를 바탕으로 해서 하나라도 빠짐없이 로그파일을 챙기는 것이 문제 원인을 해결할 수 있는 지름길이다.

모니터링 툴
요즘 출시되고 있는 DB 서버나 웹 애플리케이션 서버, 웹 서버,메시징 엔진 제품 등은 더 편리한 관리 환경을 위해 비주얼한 형태의 모니터링 툴을 제공하여 자원의 상태 등을 파악하고 런타임 환경이 제대로 운영 중인지 파악하는 데 많은 도움을 주고 있다. 또한 이러한 적절한 툴이 없다 할지라도 간단한 스크립트를 이용하여 서버 상황을 이해하는 데 기본이 되는 여러 가지 정보를 추출하는 것이 가능하다. 이를테면 네트워크 연결 수나 DB 연결수 그리고 CPU와 메모리 활용 상태 등은 간단한 스크립트로도 추출하는 것이 가능하다. 이러한 툴을 쓰는데 인색하지 말라.

숙련된 버그 사냥꾼이 필요하다
이제까지 버그 사냥꾼 스파이크씨의 경험을 토대로 웹 환경에서의 버그의 유형과 이러한 버그를 잡아내는 대략적인 방법론에 대한 이야기를 들어보았다. 우리는 흔히 버그 없는 소프트웨어는 없다고 하고 단 백 줄도 안되는 소스코드에서도 얼마든지 버그는 존재한다고 한다. 그만큼 개발자에게 있어 버그는 여름철의 모기처럼 평생을 따라다니는 숙명과도 같은 존재다. 그럼에도 불구하고 웹 기반 시스템은 날이 갈수록 그 복잡도를 더해가서 하나의 웹 사이트 안에 포함되어 있는 프레임워크나 미들웨어 제품 그리고 각종 부가적인 서버들의 종류가 점점 더 다양해져가고 있다.

이는 곧 웹 기반 시스템이 점점 더 단순한 개발자로서의 능력보다는 전체 시스템에 대한 안목과 다양한 경험을 아우르는 능력을 가진 인력을 더 필요로 함을 반증하는 것이기도 하다는 생각이다. 때문에 이렇게 복잡해져가는 시스템에 대한 문제 해결 능력을 기르는 것은 개발 본연의 경험과 함께 매우 중요한 능력이라 생각하며 본 기사를 통해 더 깊은 웹 기반 시스템 문제 분석가의 길에 매력을 느끼는 독자들이 많아지면 바랄 것이 없겠다.

* 이 기사는 ZDNet Korea의 제휴매체인 마이크로소프트웨어에 게재된 내용입니다.
Posted by SB패밀리