출처 : http://blog.naver.com/seonsin25?Redirect=Log&logNo=30154358810


1. SM (System Maintenance) 

   1) 정의 : 현재 운영중인 시스템의 기능을 새로운 환경 변화에 적응되도록 변경시키거나, 

      현재 시스템의 고장 등을 수리하여 정상적으로 가동될 수 있도록 하는 일련의 작업

      (네이버 지식 백과 정보)

   2) 상세 설명 : 현대의 모든 기업은 기업의 업무를 위해서 프로그램을 사용하고 있습니다. 

      SM은 이런 회사에 상주하여, 시스템의 기능상 오류가 발생하거나, 현재 구축된 프로그램의

      기능을 변경 혹은 추가 하는등 실제 현업에서 업무를 담당하는 사람들이 시스템을 편리하고 

      안정적으로 사용할 수 있도록 지원하는 업무를 말합니다. 

   3) 업무 내역 :

     - 오류 수정 : 시스템 데이터의 오류나, 작업 진행중 발생한 오류를 수정해주는 작업

     - 기능 개선 : 기존에 존재하던 기능에 부가 기능을 더하거나, 불편 요소를 개선하는 작업

     - 기능 추가 : 새로운 기능을 추가 개발 하는 기능

     - 데이터 제공 : 사용자들이 요구하는 데이터를 DB에서 조회 제공

     - 시스템 안정화 : 시스템이 다운되거나, 부하가 걸리지 않도록 안정화를 유지 시키는 작업

   4) 특성 : 

     - SM을 담당하고 있는 현업의 업무 지식에 특화됨. 예를 들면 금융시스템의 SM을 담당하는

       개발자들은 프로그램 개발 뿐만 아니라, 금융업에 대한 지식이 있어야 하며, 업무를 담당하다

       보면 자연스럽게 해당 업무의 지식이 쌓이게 됩니다. 

    - SM은 한 시스템을 장기적으로 담당하는 경우가 많습니다. 그러다 보니 해당 시스템에 대해서는

      잘 하지만, 이후 설명드릴 SI나 솔루션에 비해서 IT 적인 지식(프로그램, DB, WAS등)에 대한

      다양한 지식과 경험 면에서는 약점을 드러내는 경우가 많습니다. 

 

 

 

 

 

 

 

 

2. SI (System Integration)

   1) 정의 : 기업이 필요로 하는 정보시스템에 관한 기획에서부터 개발과 구축, 나아가서는 운영까지   

      의 모든 서비스를 제공하는 일.

      (네이버 지식 백과 정보)

   2) 상세 설명 : 쉽게 말하면, 기업에서 사용할 프로그램을 구축하는 작업입니다. SM이 구축된 

      프로그램을 운영, 유지/보수 하는 작업이라면, SI는 SM이 운영할 시스템을 아무것도 없는

      상태에서 구축하는 작업입니다. 무의 상태에서 고객의 요구 사항을 분석하고 분석된 요구 사항에

      맞게 시스템을 구축하는 작업입니다. 

   3) 업무 내역(프로젝트 구축시 발생 업무)

     - 요구사항 분석 : 고객의 요구 사항을 수집하는 작업. (PM)

     - 분석/설계 : 요구 사항을 분석하여, 실제 개발이 가능한 형태로 설계하는 작업(PM/PL)

     - 개발 : 분석/설계를 통해서 나온 자료를 기반으로 실제 프로그램을 구축하는 작업

     - 테스트 : 구축된 프로그램을 테스트 안정화 하는 작업

     - 검수 : 최종 구축된 프로그램을 고객으로부터 이상없이 구축되었음을 인증받는 작업

   4) 특성 

     - 프로젝트 단위로 적게는 몇개월 길게는 년단위까지 진행됨

     - 다양한 프로그래밍언어, 개발환경등을 접하게 되어 다양한 경험을 얻을 수 있게된다.

     - 프로젝트 단위이기 때문에 본사혹은 정해진 위치에서 작업을 하는 것이 아니라, 

       프로젝트에 따라 다양한 장소에서 작업을 함

     - 모든 SI쪽이 그런 것은 아니지만, 대부분 특정영역의 전문지식을 갖는 부분에서는

       조금 부족함이 있다.

     - 전반적으로 프로젝트 기간동안 많이 힘든 경우가 많다.

 

 

 

 

3. 솔루션 

   1) 정의 : 소프트웨어 패키지나 응용프로그램과 연계된 문제들을 처리해주는 하드웨어나 

      소프트 웨어이다.

     (네이버 지식 백과 정보)

   2) 상세 설명 : 솔루션은 SI와 상당한 부분에서 비슷하다. 고객이 필요로하는 프로그램을 

      프로젝트 단위의 작업을 구성하여 제공하는 면은 같다. 하지만 차이는 SI가 아무것도 없는 

      상태에서 고객의 요구사항을  기반으로 만들어진다면, 솔루션은 이미 완성된 프로그램(제품)을

      가지고와서 고객의 요구 사항에 맞게  커스터마이징 시켜서 제공한다는 차이를 가지고 있다. 

      예를 들면 똑같은 금융 프로그램을 만들더라도 아무것도 없는 상태에서 프로젝트에 들어와 

      고객 요구사항대로 만들어진다면 그것은 SI개발이며, 

       미리 만들어진 프로그램을 가지고 들어온다면 그것은 솔루션이 구축된 것이다.

   3) 업무 내역

    - 요구사항 분석(GAP분석) : 가지고 있는 솔루션과 고객이 바라는 요구 사항간의 차이(GAP)을 

      분석하는 작업

    - 커스터마이징 : GAP분석으로 나온 차이를 설계하고 개발 변경하는 작업

    - 테스트 : SI와 동일

    - 검수 : SI와 동일

   4) 특성 

    - 일반적으로 SI보다 연구 개발 부분의 능력이 강화된다.

    - SM과 SI의 장점들을 중간 정도로 가진다. 담당 솔루션의 업무에 대한 업무 지식이 쌓이고, 

       프로젝트를 하며 기술적인 부분에 있어서 경험도 많이 쌓을 수 있다.

    - 프로젝트 단위의 업무가 대부분 힘들지만, SI에 비해서는 상대적으로 조금 여유있게 

       프로젝트가 진행된다.

    - 영업 부문에 있어서는 양극화 현상이 나온다. 좋은 솔루션은 지속적인 판매가 되지만, 

      도태된 솔루션은 쉽게 시장에서 사장되는 경우가 있다.


[참고사이트]

1. SI 업계에 대한 나무위키에서 정리한 글

https://namu.wiki/w/SI

Posted by 모과이IT
,
How to be a Programmer: A Short, Comprehensive, and Personal Summary


프로그래머가 되는 방법: 짧고 폭넓고 개인적인 요약.



번역 처로 강창기


Copyright © 2002, 2003 Robert L. Read


Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with one Invariant Section being 'History (As of May, 2003)', no Front-Cover Texts, and one Back-Cover Text: 'The original version of this document was written by Robert L. Read without renumeration and dedicated to the programmers of Hire.com.' A copy of the license is included in the section entitled 'GNU Free Documentation License'.


목차

Contents

 [-]
1 도입
2 초보자
2.1 개인적 기능들
2.1.1 디버그 배우기
2.1.2 문제 공간을 나눠서 디버그 하는 방법
2.1.3 오류를 제거하는 방법
2.1.4 로그를 이용해서 디버그 하는 방법
2.1.5 성능 문제를 이해하는 방법
2.1.6 성능 문제를 해결하는 방법
2.1.7 반복문을 최적화하는 방법
2.1.8 I/O 비용을 다루는 방법
2.1.9 메모리를 관리하는 방법
2.1.10 가끔씩 생기는 버그를 다루는 방법
2.1.11 설계 기능을 익히는 방법
2.1.12 실험을 수행하는 방법
2.2 팀의 기능들
2.2.1 시간 추정이 중요한 이유
2.2.2 프로그래밍 시간을 추정하는 방법
2.2.3 정보를 찾는 방법
2.2.4 사람들을 정보의 원천으로 활용하는 방법
2.2.5 현명하게 문서화하는 방법
2.2.6 형편없는 코드를 가지고 작업하기
2.2.7 소스 코드 제어 시스템을 이용하는 방법
2.2.8 단위별 검사를 하는 방법
2.2.9 막힐 때는 잠깐 쉬어라
2.2.10 집에 갈 시간을 인지하는 방법
2.2.11 까다로운 사람들과 상대하는 방법
3 중급자
3.1 개인적 기능들
3.1.1 의욕을 계속 유지하는 방법
3.1.2 널리 신뢰받는 방법
3.1.3 시간과 공간 사이에서 균형을 잡는 방법
3.1.4 압박 검사를 하는 방법
3.1.5 간결성과 추상성의 균형을 잡는 방법
3.1.6 새로운 기능을 배우는 방법
3.1.7 타자 연습
3.1.8 통합 검사를 하는 방법
3.1.9 의사소통을 위한 용어들
3.2 팀의 기능들
3.2.1 개발 시간을 관리하는 방법
3.2.2 타사 소프트웨어의 위험 부담을 관리하는 방법
3.2.3 컨설턴트를 관리하는 방법
3.2.4 딱 적당하게 회의하는 방법
3.2.5 무리 없이 정직하게 반대 의견을 내는 방법
3.3 판단 능력
3.3.1 개발 시간에 맞춰 품질을 조절하는 방법
3.3.2 소프트웨어 시스템의 의존성을 관리하는 방법
3.3.3 소프트웨어의 완성도를 판단하는 방법
3.3.4 구입과 개발 사이에서 결정하는 방법
3.3.5 전문가로 성장하는 방법
3.3.6 면접 대상자를 평가하는 방법
3.3.7 화려한 전산 과학을 적용할 때를 아는 방법
3.3.8 비기술자들과 이야기하는 방법
4 상급자
4.1 기술적 판단 능력
4.1.1 어려운 것과 불가능한 것을 구분하는 방법
4.1.2 내장 언어를 활용하는 방법
4.1.3 언어의 선택
4.2 현명하게 타협하기
4.2.1 작업 일정의 압박과 싸우는 방법
4.2.2 사용자를 이해하는 방법
4.2.3 진급하는 방법
4.3 팀을 위해 일하기
4.3.1 재능을 개발하는 방법
4.3.2 일할 과제를 선택하는 방법
4.3.3 팀 동료들이 최대한 능력을 발휘하게 하는 방법
4.3.4 문제를 나누는 방법
4.3.5 따분한 과제를 다루는 방법
4.3.6 프로젝트를 위한 지원을 얻는 방법
4.3.7 시스템이 자라게 하는 방법
4.3.8 대화를 잘 하는 방법
4.3.9 사람들에게 듣고 싶어 하지 않는 말을 하는 방법
4.3.10 관리상의 신화들을 다루는 방법
4.3.11 조직의 일시적 혼돈 상태를 다루는 방법
5 참고 문헌
5.1 책
5.2 웹 사이트
6 역사 (2003년 5월 현재) / History (As Of May, 2003)
6.1 피드백 및 확장 요청 / Request for Feedback or Extension
6.2 원본 / Original Version
6.3 원저자의 경력 / Original Author's Bio


1 도입 

좋은 프로그래머가 되는 것은 어렵고도 고상한 일이다. 소프트웨어 프로젝트의 공동 비전을 현실화하려고 할 때 가장 어려운 부분은 함께 일하는 개발자들과 고객들을 상대하는 일이다. 컴퓨터 프로그램을 짜는 것은 중요한 일이고 지식과 기능이 많이 드는 일이다. 하지만 그것은 좋은 프로그래머가 고객 및 자기가 크고 작게 책임을 지고 있는 수많은 동료들을 만족시키는 소프트웨어 시스템을 만들기 위해 해야 하는 다른 모든 일들에 비교해 볼 때 정말 어린아이 장난과 같다. 나는 내가 스물 한 살이었을 때 누군가가 나에게 설명해 주길 바랐던 것들을 가능한 한 간결하게 요약하려고 했다.

이것은 매우 주관적이며, 따라서 이 글은 개인적이고 다소 고집스럽게 보일 수밖에 없다. 이 글은 프로그래머가 일하면서 맞부딪치기 아주 쉬운 문제들에 한정되어 있다. 이런 문제들과 이에 대한 해결책은 사람 사는 데서 흔히 볼 수 있기 때문에 이 글이 설교처럼 보일 수도 있다. 그럼에도 불구하고 이 글이 유용하게 쓰이길 바란다.

컴퓨터 프로그래밍은 여러 강좌를 통해 배울 수 있다. The Pragmatic Programmer <Prag99>, Code Complete <CodeC93>, Rapid Development <RDev96>, Extreme Programming Explained <XP99> 등의 훌륭한 책을 통해 컴퓨터 프로그래밍에 대해 배우고, 좋은 프로그래머란 무엇인가에 대한 다양한 논점들을 알게 된다. 폴 그레이엄(Paul Graham) <PGSite>과 에릭 레이먼드(Eric Raymond) <Hacker>의 글은 이 글을 읽기 전이나 읽는 도중에 꼭 읽어 보아야 한다. 이 글은 이상의 훌륭한 글들과 달리 사회 활동의 문제를 강조하고 있으며 내가 보기에 꼭 필요하다고 생각하는 모든 기능들을 폭넓게 요약하고 있다.

이 글에서 "상사"는 나에게 프로젝트를 배정해 주는 사람을 의미한다. 사업, 회사, 부족(tribe)이라고 할 때, 사업이 돈을 버는 것, 회사가 현시대의 일터, 부족이 충성심을 공유하는 사람들이라는 뜻을 내포하는 것 외에는 모두 같은 뜻으로 사용했다.

우리 부족에 온 것을 환영한다.

2 초보자 

2.1 개인적 기능들 

2.1.1 디버그 배우기 

디버깅은 프로그래머의 기본이다. 디버그란 말의 처음 뜻은 오류를 제거하는 것이지만, 더 중요한 것은 프로그램이 실행될 때 그것을 상세히 검사하는 일이다. 효과적으로 디버그 할 줄 모르는 프로그래머는 앞을 못 보는 것과 같다.

이상주의자라면 설계, 분석, 복잡도 이론 등등이 더 기본적인 것이라고 생각할 것이다. 하지만 이들은 현업의 프로그래머가 아니다. 현업의 프로그래머는 이상적인 세계에서 살고 있지 않다. 완벽한 프로그래머라 해도, 그는 대형 소프트웨어 회사, GNU 등의 조직, 자기 동료들이 만든 코드들에 둘러싸여 있고 그것을 가지고 작업해야 한다. 이 코드들은 대부분 불완전하며 불완전하게 문서화되어 있다. 어떤 코드가 실행될 때 그것을 꿰뚫어 볼 수 있는 능력이 없다면 사소한 문제에도 대책 없이 나가떨어질 수밖에 없다. 이러한 투시력은 실험해 보는 것을 통해 얻어지며, 그것이 바로 디버깅이다.

디버깅은 프로그램의 실행에 대한 것이지 프로그램 자체에 대한 것이 아니다. 대형 소프트웨어 회사에서 프로그램을 구입했다면 보통은 프로그램을 들여다볼 수 없다. 하지만 그 코드가 문서대로 동작하지 않거나 (컴퓨터가 멈춰 버리는 것은 아주 흔하고 극적인 예이다) 문서에 원하는 내용이 없는 일은 항상 일어난다. 더 흔한 것은, 오류가 생겨서 자기가 짠 코드를 검사하는데 어떻게 그런 오류가 생길 수 있는지 전혀 실마리를 잡을 수 없는 경우이다. 당연히 이것은 그 프로그래머가 짐작하고 있는 것 중 어떤 것이 잘못됐거나, 예상하지 못했던 상황이 발생하기 때문이다. 가끔은 소스 코드 응시하기 마법으로 문제를 해결할 수 있다. 하지만 그 마법이 통하지 않을 때는 디버그를 해야 한다.

프로그램의 실행에 대한 투시력을 얻기 위해서는 코드를 실행하면서 무엇인가를 관찰해야 한다. 어떤 경우에는 그것이 화면에 나타나서 눈으로 볼 수도 있지만, 다른 많은 경우에는 코드 내의 변수의 상태, 현재 실행되고 있는 코드의 줄 수, 복잡한 자료 구조에서 어떤 검증 조건(assertion)이 계속 유지되는가의 여부 등과 같이 눈에 보이지 않는다. 이런 숨겨진 것들은 드러나야 한다. 실행되고 있는 프로그램의 내부를 들여다보기 위해 널리 쓰이는 방법을 다음과 같이 분류할 수 있다.
  • 디버깅 도구 이용
  • 프린트 줄 넣기(printlining) -- 프로그램을 임시로 고치는 것, 특히 필요한 정보를 프린트하는 줄을 추가하는 것
  • 로그 기록 -- 로그 파일의 형태로 프로그램을 들여다볼 수 있는 영구적인 창을 만드는 것 

디버깅 도구는 제대로 동작한다면 훌륭한 것이지만, 그 다음의 두 가지 방법이 더욱 더 중요하다. 디버깅 도구는 종종 언어의 발달을 따라가지 못하기 때문에 어떤 시점이 되면 쓸모 없게 될 수 있다. 그리고 디버깅 도구 자체가 프로그램의 수행 방식을 미묘하게 변화시킬 수도 있기 때문에 모든 경우에 유효한 것이 아니다. 끝으로, 대규모 자료 구조에 대한 검증 조건을 검사하는 것과 같은 디버깅의 경우에는 어떻든 간에 코드를 새로 짜야 한다. 디버깅 도구가 안정적이라면 그것의 사용 방법을 아는 것이 좋은 일이겠지만, 그 다음의 두 가지 방법을 쓸 줄 아는 것은 필수불가결한 일이다.

어떤 초보자는 코드를 고치고 실행하는 일을 반복해야 하는 디버깅에 대한 두려움이 잠재의식 속에 있는 것 같다. 이해할 만한 일이다. 이것은 처음 외과 수술을 하는 것과 비슷해 보인다. 하지만 초보자들은 코드가 쌩쌩 돌아가게 하기 위해 여기저기 찔러 보는 것에 익숙해져야 한다. 그들은 코드를 가지고 실험해 보는 것에 익숙해져야 하고, 자기가 코드를 가지고 무엇을 하더라도 그것이 문제를 악화시키지 않는다는 것을 배워야 한다. 이 소심한 사람들의 교사나 사수라면, 어떻게 해야 하는지 친절하게 알려 주고 손이라도 잡아 이끌면서 그 두려움을 극복할 수 있도록 도와 주라. 그 두려움 때문에 좋은 프로그래머가 될 수 있는 사람들도 아슬아슬하게 시작했다가 포기하는 경우가 많다.

2.1.2 문제 공간을 나눠서 디버그 하는 방법 

디버깅은 수수께끼에서 출발하기 때문에 재미있다. 이렇게 디버그 하면 저렇게 될 것이라고 생각하지만 실제로는 다른 결과가 생긴다. 디버깅은 만만한 일이 아니다. 여기에서 무슨 사례를 제시하든 그것은 실제 상황에 비하면 상당히 부자연스운 것이 될 것이다. 디버깅은 창의력과 독창성이 필요하다. 디버깅에 한 가지 열쇠가 있다면 그것은 수수께끼에 대한 분할 정복 기법(divide and conquer technique)을 사용하는 것이다.

예를 들어 열 가지 일을 차례로 하는 프로그램을 만들었다고 하자. 그런데 실행해 보니 멈춰 버렸다. 멈추도록 프로그램하지 않았는데 말이다. 이제 "프로그램이 멈춘다"는 수수께끼가 생긴 것이다. 출력된 결과를 보면 처음 7번까지는 제대로 실행된 것을 알 수 있다. 나머지 세 가지가 출력 결과에서 안 보인다. 이제 우리의 수수께끼는 "프로그램이 8번이나 9번이나 10번에서 멈췄다"로 줄어들었다.

그럼 프로그램이 어디에서 멈췄는지 알아볼 수 있는 실험을 설계할 수 있을까? 물론이다. 디버거를 쓸 수도 있고 8번과 9번 다음에 프린트 줄을 넣을 수도 있다. (물론 사용하는 언어에 적합한 다른 방법을 쓸 수도 있다.) 그리고 다시 실행해 보면 우리의 수수께끼는 "프로그램이 9번에서 멈췄다"와 같이 더 줄어든다. 어느 순간에든 수수께끼가 정확히 무엇인지 기억하는 것은 집중하는 데 도움이 된다. 여러 사람이 급하게 어떤 문제에 매달려 있을 때는 그 일이 무척 혼란스러워질 수 있다.

분할 정복이라는 열쇠는 디버깅 기법일 뿐만 아니라 알고리듬 설계 기법이기도 하다. 수수께끼의 중간을 둘로 나누는 것만으로 일 처리를 잘 할 수 있다면, 더 이상 많이 나눌 필요는 없을 것이고 디버깅도 더 빨리 끝날 것이다. 그런데 수수께끼의 중간이란 어디쯤을 말하는 것인가? 여기가 바로 창의력과 경험이 필요한 지점이다.

아직 초보인 사람에게는, 모든 오류가 존재하는 공간이 소스 코드의 모든 몇 줄뿐인 것처럼 보일 것이다. 그는 아직 프로그램의 다른 차원, 즉, 줄들이 실행되는 공간, 자료 구조, 메모리 관리, 외부 코드와 상호작용, 문제가 생길 만한 코드와 간단한 코드 등을 볼 수 있는 감각이 없다. 이런 다른 차원들은 경험이 쌓인 프로그래머에게 문제를 일으킬 수 있는 모든 것들에 대해 완벽하지는 않지만 매우 유용한 머리 속의 모형(mental model)을 형성하게 해 준다. 이런 모형을 머리 속에 갖고 있으면 수수께끼의 중간이 어디인지 효과적으로 찾는 데 도움이 된다.

문제를 일으킬 수 있는 모든 것들의 공간을 둘로 균등하게 나눴다면, 이제는 그 둘 중 어느 쪽에서 오류가 생겼을지 결정해야 한다. 수수께끼가 "프로그램을 멈추게 하는 그 줄은 이 줄이 실행되기 전에 실행됐을까, 후에 실행됐을까?"와 같이 단순한 경우에는 어느 줄이 실행되는지 관찰하기만 하면 된다. 다른 경우에는 수수께끼가 이런 식으로 분할될 것이다. "저 그래프에 잘못된 노드를 가리키는 포인터가 있거나, 그 그래프에 변수들을 추가하는 알고리듬에 문제가 있다." 이런 경우에는 분할된 수수께끼 중 어느 쪽을 버릴 것인지 결정하기 위해 그 그래프의 포인터들이 모두 정확한지 알아보는 작은 프로그램을 작성해야 할 수도 있다.

2.1.3 오류를 제거하는 방법 

나는 의도적으로 프로그램의 실행을 점검하는 행위와 오류를 고치는 행위를 구분하고 있다. 물론 디버깅은 버그를 제거하는 것을 뜻한다. 이상적으로는 코드를 완벽하게 이해하여 오류의 정체와 그것을 고칠 방법을 완벽하게 알게 되면서 "아하!" 하고 외치는 순간에 이를 수도 있다. 하지만 문서화가 잘 되어 있지 않아 그 속을 들여다 볼 수 없는 시스템들을 가지고 프로그램을 만드는 경우도 종종 있으므로 이런 일이 항상 가능한 것은 아니다. 또한 코드가 너무 복잡해서 그것을 완벽하게 이해할 수 없는 경우도 있다.

버그를 고칠 때에는 가능한 한 조금만 수정하여 버그를 고치고 싶을 것이다. 그러면서 성능 개선이 필요한 다른 것들을 보게 될 수도 있다. 하지만 이것들을 동시에 고치지는 말라. 한 번에 단 한 가지만 변경하는 과학 실험 방법을 사용하도록 하라. 이를 위한 최선의 과정은, 그 버그를 쉽게 다시 확인할 수 있게 되면, 고친 내용을 바꿔 넣고 나서, 프로그램에서 버그가 더 이상 없다는 것을 확인하는 것이다. 물론 때때로 한 줄 이상을 고쳐야 하겠지만 그렇다 해도 개념적으로는 더 이상 나눌 수 없는(atomic) 한 부분만 변경해서 버그를 고쳐야 한다.

실제로 버그가 여러 개인데 그것들이 하나인 것처럼 보이는 경우도 있다. 버그를 어떻게 정의하여 그것들을 하나씩 고쳐 갈 것인지 결정하는 것은 결국 프로그래머의 몫이다. 프로그램이 무엇을 해야 하는지, 또는 원래 개발자가 의도했던 것이 무엇인지 불분명할 경우도 있다. 그런 경우에는 경험을 근거로 판단을 내리고 그 코드에 자기 나름대로 의미를 부여해야 할 것이다. 그 프로그램이 무엇을 해야 할지 결정하고, 그것에 대해 주석을 달거나 어떤 식으로든 명료화하고, 그 코드가 그 의미에 부합하도록 만든다. 이것은 중급에서 고급의 기능으로서 처음부터 새로운 함수를 작성하는 것보다 더 어려울 경우도 있지만, 현업에서는 이런 귀찮은 일이 종종 생긴다. 어쩌면 자신에게 수정 권한이 없는 시스템을 고쳐야 하게 될지도 모른다.

2.1.4 로그를 이용해서 디버그 하는 방법 

로그 기록(logging)이란 정보를 제공하는 일련의 기록인 로그(log)를 생성하도록 시스템을 작성하는 활동을 말한다. 프린트 줄 넣기(printlining)는 간단한, 보통은 일시적인, 로그를 생성하기만 한다. 완전한 초보자들은 프로그래밍에 대해 아는 것에 한계가 있기 때문에 로그를 이해하고 사용해야 한다. 시스템 설계자들은 시스템의 복잡성 때문에 로그를 이해하고 사용해야 한다. 로그가 제공하는 정보의 양은, 이상적으로는 프로그램이 실행되는 중에도, 설정 가능해야 한다. 일반적으로 로그 기록은 다음의 이점이 있다.
  • 로그는 재현하기 힘든 (예를 들어, 개발 완료된 환경에서는 발생하지만 테스트 환경에서는 재현할 수 없는) 버그에 대한 유용한 정보를 제공할 수 있다.
  • 로그는, 예를 들어, 구문(statement)들 사이에 걸리는 시간과 같이, 성능에 관한 통계와 정보를 제공할 수 있다.
  • 설정이 가능할 때, 로그는 예기치 못한 특정 문제들을 디버그하기 위해, 그 문제들을 처리하도록 코드를 수정하여 다시 적용하지(redeploy) 않아도, 일반적인 정보를 갈무리할 수 있게 한다. 

로그에 남기는 정보의 양은 항상 정보성과 간결성 사이의 타협으로 결정된다. 정보를 너무 많이 남긴다면 로그가 낭비적이 되고 스크롤에 가려지게(scroll blindness) 되어, 필요한 정보를 찾기 어려워질 것이다. 너무 조금 남긴다면 필요한 정보가 남지 않을 것이다. 이런 점에서, 무엇이 출력될지 설정할 수 있게 하는 것은 매우 유용하다. 일반적으로 로그에 남는 기록을 통해, 그 기록을 남긴 소스 코드의 위치, (적용 가능하다면) 문제가 되는 작업을 실행한 쓰레드, 정확한 실행 시각, 그리고 일반적으로, 어떤 변수의 값, 여유 메모리의 양, 데이터 객체의 개수 등 그 밖의 유용한 정보를 알 수 있다. 이러한 로그 생성 구문들은 소스 코드 전체에 흩어져 있는데, 특히 주요 기능이 있는 지점과 위험 부담이 있는 코드 근처에 있다. 구문마다 수준이 정해질 수 있으면 시스템의 현재 설정에 따라 그 수준에 해당하는 기록만 남기게 될 것이다. 로그 생성 구문을 설계할 때에는 어디에서 문제가 생길지 예상해서 그것을 기록으로 남길 수 있게 해야 한다. 성능을 측정할 필요성도 예상하고 있어야 한다.

영구적인 로그를 남긴다면, 로그 기록이 프린트 줄 넣기(printlining)를 대신 할 수 있을 것이고, 디버그 구문들 중에도 로그 기록 시스템에 영구적으로 추가할 것들이 있을 것이다.

2.1.5 성능 문제를 이해하는 방법 

실행중인 시스템의 성능을 알아내는 방법을 이해하는 일은 디버깅과 마찬가지로 피할 수 없는 일이다. 자기가 작성한 코드의 실행에 드는 비용을 완벽하고 정확하게 이해하고 있다 해도, 그 코드는 통제할 수 없거나 들여다볼 수 없는 다른 소프트웨어 시스템들을 호출할 때도 있다. 하지만 실제로 성능의 문제는 일반적으로 디버깅과는 조금 다르고 또 조금은 쉬운 문제이다.

어떤 시스템이나 하위 시스템이 너무 느린 것 같다고 가정해 보자. 그것을 빠르게 하기 전에 우선 왜 그것이 느린지에 대해 머리 속으로 모형을 만들어야 한다. 그렇게 할 수 있도록 시간과 그 밖의 자원들이 어디에 실제로 쓰이고 있는지 알기 위해 성능 기록 도구(profiling tool)나 좋은 로그 기록을 쓸 수 있다. 유명한 격언 중에 90%의 시간은 10%의 코드에 쓰인다는 말이 있다. 나는 그 격언에 성능 문제에서 입출력 시간(I/O)의 중요성을 추가하고 싶다. 종종 대부분의 시간은 이러저러한 방식으로 I/O에 쓰인다. 낭비가 심한 I/O와 그러한 10%의 코드를 찾아냈다면 한 발짝 잘 내딛은 것이다.

컴퓨터 시스템의 성능에는 여러 차원이 있고 여러 자원들이 사용된다. 측정해야 할 첫 번째 자원은 벽시계 시간(wall-clock time), 즉 계산에 걸리는 총 시간이다. 벽시계 시간을 로그에 기록으로 남기는 것은, 다른 성능 기록 방법이 통하지 않는 예상치 못한 상황에 대한 정보를 줄 수 있으므로 특히 가치가 있다. 하지만 이것으로 모든 것을 알 수는 없다. 때로는 시간이 좀 더 걸리기는 하지만 프로세서의 처리 시간을 많이 잡아먹지 않는 코드가 실제로 작업해야 하는 전산 환경에서는 훨씬 더 좋을 수 있다. 마찬가지로, 메모리, 네트웍 대역폭, 데이터베이스, 그 밖의 서버 접속들이 결국에는 프로세서 처리 시간보다 더 낭비가 클 수 있다.

동시에 사용해야 하는 공유 자원 쟁탈(contention)로 교착 상태(deadlock)나 기아 상태(starvation)가 생길 수도 있다. 교착 상태란 동기화나 자원 요청이 부적절하여 더 이상 진행할 수 없는 상태를 말한다. 기아 상태란 구성요소에 시간을 적절히 배분하는 데에 실패한 것이다. 이런 상황을 예상할 수 있다면 프로젝트를 시작할 때부터 이런 쟁탈을 측정할 방법을 마련하는 것이 최선이다. 이러한 쟁탈이 일어나지 않는다 해도 그것을 확실히 검증할 수 있게 해 놓는 것은 매우 도움이 된다.

2.1.6 성능 문제를 해결하는 방법 

대부분의 소프트웨어 프로젝트는 첫 배포판을 냈을 때보다 비교적 적은 노력으로도 10배에서 100배나 더 빠르게 진행될 수 있다. 출시일의 압박 하에서는, 일을 간단하고 신속하게 끝낼 수 있는, 하지만 다른 해결책보다는 효율이 떨어지는, 해결책을 선택하는 것이 어쩌면 현명하고도 효과적인 방법일 수 있다. 하지만 성능은 사용 편이성(usability)의 일부이며, 결국에 가서는 더욱 세심하게 고려해야 할 경우가 많다.

매우 복잡한 시스템의 성능을 향상시키는 열쇠는 병목(bottleneck), 즉 대부분의 자원들이 사용되는 지점을 찾기 위해 충분히 잘 분석하는 것이다. 계산 시간의 1% 밖에 차지하지 않는 함수를 최적화하는 것은 별 의미가 없다. 실제로 시간이 어디에 쓰이는지 알아내기 위해 성능 분석을 먼저 해야 하며, 그로부터 무엇을 향상시킬 것인지 결정할 수 있다. 경험상으로 볼 때, 어떤 작업이 시스템이나 시스템의 중요한 부분을 최소한 두 배 빠르게 할 것이라고 생각되지 않는다면, 그것을 실행에 옮기기 전에 신중하게 생각해야 한다. 보통 이것을 위해 쓰는 방법이 있다. 그 변화에 따라 필요하게 되는 검사와 품질 확인의 수고를 고려하라. 모든 변화에는 검사라는 짐이 따르므로 큰 변화가 적을수록 더 좋은 것이다.

어디에선가 두 배의 향상을 달성한 후에는, 최소한 다시 생각하고 또 다시 분석하여 그 다음으로 낭비가 심한 병목이 어디인지 발견해 내고, 또 다른 두 배의 성능 향상을 이루기 위해 그 지점을 공략해야 할 것이다.

성능 상 병목은 소를 셀 때 머리를 세는 대신 다리를 센 다음 4로 나누는 것에 비유할 수 있을 것이다. 예를 들어, 나는 어떤 관계형 데이터베이스 시스템에서 자주 검색하는 열에 적절한 인덱스를 달지 않아서, 검색이 최소한 스무 배는 느려지는 오류를 일으킨 적이 있다. 그 외에도, 내부 반복문에서 불필요한 I/O를 하는 것, 더 이상 필요 없는 디버그 구문을 남겨 놓는 것, 불필요한 메모리 할당, 성능에 대해 제대로 문서화되어 있지 않은 라이브러리나 그 밖의 하위 시스템들을 전문적인 안목 없이 사용하는 것 등을 예로 들 수 있을 것이다. 이런 식의 성능 향상을, 쉽게 따서 성과를 낼 수 있다는 의미에서, 낮게 달린 과일(low-hanging fruit)이라고 부르기도 한다.

낮게 달린 과일들을 거의 다 따 버렸다면 어떻게 할 것인가? 아마도 더 높이 손을 뻗거나 나무를 베어 내릴 것이다. 즉, 조그만 성능 향상을 계속해 갈 수도 있고, 시스템이나 하위 시스템을 진지하게 재설계할 수도 있을 것이다. (이것은, 새로운 설계라는 측면뿐만 아니라 자기 상사에게 이것이 좋은 생각이라는 것을 설득한다는 측면에서도 좋은 프로그래머로서 자신의 능력을 발휘할 수 있는 훌륭한 기회이다.) 하지만, 재설계를 주장하기 전에는 이것이 하위 시스템을 다섯 배에서 열 배는 더 낫게 할 수 있는지 스스로 질문해 봐야 한다.

2.1.7 반복문을 최적화하는 방법 

때때로 제품에서 실행하는 데 시간이 오래 걸리거나 병목(bottleneck)이 되는 반복문이나 재귀함수를 보게 될 것이다. 그 반복문을 조금 빠르게 고치려고 하기 전에, 혹시 그것을 완전히 제거할 방법은 없는지 잠시 생각해 보라. 다른 알고리듬으로 그 일을 할 수 없을까? 다른 계산을 하면서 동시에 그 계산을 할 수는 없을까? 그런 식의 방법을 찾을 수 없다면 반복문 최적화 작업을 해도 된다. 이 일은 단순하다. 잡동사니를 없애 버려라. 결국 이 일은 독창성뿐만 아니라 그런 종류의 구문이나 식에 드는 비용에 대한 이해가 요구된다. 여기 몇 가지를 제안해 보겠다.
  • 실수 연산(floating point operation)을 제거하라
  • 필요 없이 메모리 블록을 새로 할당하지 말라
  • 상수들을 미리 계산하라(fold together)
  • I/O는 버퍼로 옮겨라
  • 나눗셈을 피하라
  • 쓸데없는 형변환(cast)을 피하라
  • 첨자(index)를 반복 계산하는 것보다는 포인터를 옮기는 것이 낫다 

이러한 연산에 드는 비용은 사용하는 시스템에 따라 다르다. 어떤 시스템의 컴파일러와 하드웨어는 알아서 이런 일들을 해 준다. 그래도 분명하고 효율적인 코드가 특정 시스템에 대한 이해가 필요한 코드보다 더 낫다.

2.1.8 I/O 비용을 다루는 방법 

많은 문제에서 프로세서는 하드웨어 장치들과 통신하는 데 드는 시간에 비해 빠르게 동작한다. 이런 시간 비용을 보통 줄여서 I/O라고 하고, 여기에는 네트웍 시간, 디스크 I/O, 데이터베이스 질의, 파일 I/O, 그리고 프로세서에 가깝지 않은 어떤 하드웨어가 뭔가를 하게 하는 작업들이 포함된다. 따라서 빠른 시스템을 만든다는 것은, 어떤 빽빽한 반복문 속에 있는 코드를 개선하거나 더 나아가 알고리듬을 개선하는 것보다 I/O를 개선하는 일이 될 경우가 많다.

I/O를 개선하는 두 가지 매우 기초적인 방법, 즉 캐쉬와 효율적 데이터 표현(representation)이 있다. 캐쉬는 (일반적으로 어떤 추상적인 값을 읽어 오는) I/O를 피하기 위해 그 값을 가깝게 복사해 놓아서 그 값을 가져오기 위해 I/O를 다시 발생시키지 않는 것을 말한다. 캐쉬의 핵심은 어떤 데이터가 원본(master)이고 어떤 데이터가 복사본인지 분명하게 구분하는 것이다. 원본은 단 하나만 있다! 캐쉬는 복사본이 원본의 변화를 즉시 반영하지 못하는 경우가 있다는 위험 부담이 있다.

효율적 데이터 표현이란 데이터를 더욱 효율적으로 표현하여 I/O의 비용을 줄이는 방식이다. 이 방법은 종종 가독성과 호환성 등의 다른 요구 조건과 대립되기도 한다.

효율적 데이터 표현은 처음의 표현 방식보다 두세 배의 개선 효과가 있기도 하다. 이를 위한 방법들로는 사람이 읽을 수 있는 표현 방식 대신 2진 표현 방식을 사용하는 것, 데이터와 함께 심벌 사전을 전송하여 긴 심벌들을 인코딩할 필요가 없게 하는 것, 그리고 극단적으로는 허프만(Huffman) 인코딩 같은 것 등이 포함된다.

때때로 가능한 세 번째 방법은 계산 부분을 데이터에 밀착시켜 더 가까운 곳에서 참조할 수 있게 하는 것이다. 예를 들어, 데이터베이스에서 어떤 데이터를 읽어 와서 합계와 같은 간단한 계산을 한다고 할 때 데이터베이스 서버가 직접 그 작업을 하게 하는 것이다. 이 방법은 작업하는 시스템의 특성에 매우 많이 의존하기는 하지만, 시험해 볼 필요는 있다.

2.1.9 메모리를 관리하는 방법 

메모리는 절대로 다 써 버리면 안 되는 소중한 자원이다. 잠시 동안은 그것을 무시할 수 있겠지만 결국에는 메모리를 어떻게 관리할 것인지 결정해야 할 것이다.

단일 서브루틴이 차지하는 범위 이상으로 유지될 필요가 있는 공간을 종종 할당된 힙(heap)이라고 한다. 아무도 참조하지 않는 메모리 영역은 쓸모없는 쓰레기(가비지, garbage)일 뿐이다. 사용하는 시스템에 따라 메모리가 가비지가 될 것 같으면 명시적으로 메모리 할당을 해제해야 한다. 가비지 수집기를 제공하는 시스템을 사용할 수 있을 경우도 많다. 가비지 수집기는 가비지를 발견하면 프로그래머의 어떤 조작도 필요 없이 그것이 차지하는 공간을 풀어준다. 가비지 수집은 훌륭한 방법이다. 이를 통해 오류를 줄이고, 적은 노력으로도 코드를 더욱 간결하게 할 수 있다. 할 수 있다면 이 방법을 사용하라.

하지만 가비지 수집을 한다 해도 모든 메모리를 가비지로 채우게 될 수 있다. 고전적인 실수 중의 하나는 해쉬 테이블(hash table)을 캐쉬로 사용하고는 해쉬 테이블에 있는 참조 주소들을 제거하는 것을 잊어버리는 것이다. 참조 주소가 남아 있으므로 그 주소에 해당하는 메모리 영역은 가비지 수집이 될 수 없는 상태로 못 쓰게 된다. 이것을 메모리 누수(leak)라고 한다. 메모리 누수는 일찍부터 찾아서 고쳐야 한다. 장시간 실행되는 시스템이 있다면 검사할 때는 메모리가 고갈되는 일이 없다가 실제로 사용될 때가 돼서야 고갈되기도 한다.

새로운 객체의 생성은 어떠한 시스템에서도 어느 정도 시간 비용이 드는 작업이다. 하지만 서브루틴의 지역 변수들(local variables)에 직접 할당된 메모리는 할당 해제 방식이 매우 간단해질 수 있으므로 그렇게 시간 비용이 들지는 않는다. 어떻든 불필요한 객체 생성은 피해야 한다.

한 번에 필요한 객체 수의 상한을 정할 때 생기는 중요한 경우가 있다. 이 객체들이 모두 같은 양의 메모리를 필요로 한다면 그것들을 모두 수용하기 위해 단일 블록의 메모리, 즉 버퍼를 할당할 수 있을 것이다. 그 객체들은 이 버퍼 안에서 정해진 순환 방식에 따라 할당되고 해제될 수 있으므로 이 버퍼를 링 버퍼(ring buffer)라고 부르기도 한다. 이것은 보통 힙 할당보다 더 빠르다.

때로는 할당된 공간이 다시 할당될 수 있도록, 가비지 수집에 의존하는 대신, 그것을 명시적으로 풀어줘야 한다. 그래서 할당된 각 영역을 잘 알아내어 그것을 적절한 때에 해제하는 방법을 설계해야 한다. 그 방법은 생성된 객체의 종류에 따라 달라질 수 있다. 메모리 할당 작업이 수행될 때마다 그것이 결국에는 메모리 할당 해제 작업과 짝을 이뤄야 한다는 사실을 명심해야 한다. 이것은 매우 어렵기 때문에 프로그래머들은 이를 위해 단순하게 참조 회수 세기와 같은 기초적인 형태의 가비지 수집 방법을 구현하는 경우도 있다.

2.1.10 가끔씩 생기는 버그를 다루는 방법 

가끔씩 생기는 버그는 "외계에서 온 20미터짜리 투명 전갈"의 사촌 같은 종류의 버그이다. 이 끔찍한 악몽은 관찰하기 어려울 만큼 가끔씩 나타나지만, 또한 무시할 수 없을 만큼 자주 일어난다. 이런 버그는 발견하기도 어렵게 때문에 고치기도 어렵다.

그 버그를 찾기 위해 여덟 시간을 매달린 뒤에 그것이 정말 있는 것인지 의심하기 시작한다 해도, 가끔씩 생기는 버그는 다른 모든 것들이 따르는 동일한 논리 법칙을 따를 수밖에 없다. 이 버그를 상대하기 힘든 것은 알지 못하는 어떤 조건들에서만 생기기 때문이다. 그 버그가 생기는 바로 그 때의 상황들을 기록하여 정말로 어떤 변이가 생긴 것인지 추측할 수 있도록 해 보라. 그 조건은, 예를 들어, '이 버그는 '와이오밍(Wyoming)'이라는 값을 입력했을 때만 생긴다"는 것과 같이, 데이터 값에 관련되어 있을 수도 있다. 만약 이것이 변이의 원인이 아니라면 다음으로는 동시에 수행되어야 하는 작업이 실제로는 그렇게 되지 못했을 경우를 의심해 볼 수 있다.

어떤 통제된 방식으로 그 버그가 다시 나타나도록 계속, 계속, 계속 시험해 보라. 다시 나타나게 할 수 없다면, 버그가 실제로 발생할 때 그것을 분석하기 위해 필요하다고 생각되는 정보들을 기록으로 남길 수 있는 (필요하다면 특별한) 로그 기록 시스템을 만들어 그 버그 앞에 덫을 놓아 보라. 버그가 개발 환경에서는 나타나지 않고 완성 제품에서만 나타난다면 그것은 오래 걸리는 프로세스 때문일 것이라고 믿어 보라. 로그 기록에서 얻는 실마리들은 해결책을 제공해 주지는 못하더라도 로그 기록 방법을 개선하기 위한 정보는 충분히 줄 수 있을 것이다. 개선된 로그 기록 시스템을 완성하는 데에는 오랜 시간이 걸릴 수도 있다. 그리고는 더 많은 정보를 얻기 위해 그 버그가 다시 나타날 때까지 기다려야 한다. 이 일은 어느 시간 동안 계속 반복해야 할 수도 있다.

가끔씩 생기는 버그들 중에서 내가 저지른 가장 어리석었던 것은, 어떤 수업의 프로젝트에서 함수형 프로그래밍 언어(functional programming language)를 다중 쓰레드로 구현하는 것이었다. 나는 그 함수형 프로그램이 모든 (이 수업에서는 여덟 개의) CPU들을 잘 활용하여 수치 계산을 동시에 정확하게 해 내도록 매우 주의를 기울였다. 그런데 가비지 수집기를 동기화하는 것을 깜빡 잊었다. 이 시스템은 오랜 시간 동안 잘 돌아갔고, 뭔가 이상하다는 것을 눈치 채기 전까지는, 어떤 작업을 시작하든 잘 마무리되는 것 같았다. 부끄럽게도 나는 내 실수가 드러나기 전까지는 하드웨어에 문제가 있다고 생각했었다.

최근에 일하면서는, 발견하기까지 몇 주나 걸렸던 가끔씩 생기는 버그를 만난 적이 있다. 우리에게는 아파치(Apache) 웹 서버 뒤에 자바(Java)로 구현된 다중 쓰레드 어플리케이션 서버들이 있다. 페이지 전환을 빠르게 유지하기 위해 우리는 모든 I/O가 페이지 전환 쓰레드들과는 다른 네 개의 독립된 쓰레드에서 일어나게 하고 있다. 그런데 이것들이 (우리 로그 기록에 따르면) 가끔 한 번씩 몇 시간 동안 멈춘 것처럼 되면서 아무 일도 하지 않았다. 쓰레드가 네 개가 있기 때문에 네 개 모두 멈추지 않는 한 그 자체로는 큰 문제는 아니었다. 그렇게 된다면 이 쓰레드들이 비워내는 큐(queue)가 남아 있는 모든 메모리를 순식간에 다 채워서 서버가 멈춰버렸을 것이다. 이것을 알게 되기까지 한 주 정도 걸렸지만 무엇 때문에 이런 일이 생기는지, 언제 생길지, 또는 멈출 때 어느 쓰레드가 어디쯤 작업을 하고 있는지조차 여전히 몰랐다.

이것은 타사 소프트웨어와 연관된 위험성을 보여준다. 우리는 텍스트에서 HTML 태그를 제거하는 코드의 사용권을 받아서 쓰고 있었다. 우리는 그 코드가 나온 나라 이름을 따서 그것을 '프랑스 스트리퍼'라는 애칭으로 불렀다. 우리는 소스 코드를 가지고 있었지만 (감사하나이다!) 우리 서버의 로그 기록을 살펴보다가 이메일 쓰레드들이 프랑스 스트리퍼에서 멈춘다는 것을 알게 되기까지 그 소스를 주의깊게 연구하지 않았다.

이 스트리퍼는 제대로 동작했지만 길이가 길고 특이한 텍스트에 대해서는 그렇지 못했다. 이런 텍스트를 처리하는 데에는 텍스트 길이의 제곱에 비례하거나 더 많은 시간이 걸렸다. 이런 텍스트들이 자주 나타나는 것이었다면 우리는 그 버그를 금방 발견했을 것이다. 그것이 전혀 나타나지 않았다면 우리는 전혀 문제가 없었을 것이다. 하지만 그것은 나타났고, 우리는 문제를 이해하고 해결하는 데 몇 주나 걸렸던 것이다.

2.1.11 설계 기능을 익히는 방법 

소프트웨어를 설계하는 방법을 배우기 위해서는 사수(mentor)가 설계를 할 때 그들과 한 자리에 있으면서 그들의 행동을 연구하라. 그리고 잘 작성된 소프트웨어를 연구하라. 그 후에는 최근에 나온 설계 기법에 대한 책을 읽으라.

그리고 그것들을 직접 실천해야 한다. 소규모 프로젝트부터 시작하라. 최종 작업을 마쳤으면 그 설계가 어떻게 실패하거나 성공했는지, 처음 생각했던 개념에서 어떻게 달라졌는지 숙고하라. 이런 식으로 다른 사람들과 더 큰 프로젝트를 수행하게 된다. 설계 기능은 판단 능력의 문제이며, 그것을 얻기까지 몇 년은 걸린다. 현명한 프로그래머는 두 달이면 적당한 수준에서 기본 기능을 익힐 수 있을 것이며 그것을 기반으로 발전해 갈 것이다.

자기 자신의 스타일을 개발하는 것은 자연스러운 일이며 자신에게 도움이 될 것이다. 설계는 예술이지 과학이 아니라는 것을 명심하라. 이런 주제로 책을 쓰는 사람들은 흔히 그것이 과학적으로 보이게 하는 데에 관심을 갖는다. 하지만 특정한 설계 스타일을 고집하지는 않도록 하라.

2.1.12 실험을 수행하는 방법 

이제는 고인이 된 위대한 에처 다익스트라(Edsger Dijkstra)는 전산 과학은 실험 과학이 아니며<ExpCS> 전자적인 컴퓨터에 의존하지 않는다고 설득력 있게 설명했다. 그가 1960년대의 전산 과학에 대해 다음과 같이 말했다. <Knife>

해로운 일이 일어났다. 이 주제는 '전산 과학'으로 알려지기 시작했다. - 이것은 꼭 외과 수술을 '칼 과학'이라고 부르는 것과 같다. - 그리고 전산 과학은 기계와 그 주변 장치들에 대한 학문이라고 사람들의 생각 속에 단단히 자리를 잡게 되었다. 


프로그래밍이 실험 과학이 되어서는 안 되겠지만, 대부분의 실무 프로그래머들은 다익스트라가 전산 과학에 대해 내린 정의에 동감할 만큼 여유롭지는 못하다. 우리는, 전부는 아니더라도 일부 물리학자들이 그러하듯이, 실험의 영역 속에서 일해야 한다. 지금부터 30년 동안 프로그래밍이 실험 없이 이뤄질 수 있다면, 그것은 전산 과학의 위대한 승리라고 할 수 있을 것이다.

앞으로 해 보게 될 몇 가지 실험들은 다음과 같다.
  • 문서 내용에 부합하는지 검증하거나 (문서가 없다면) 시스템의 반응을 이해하기 위해 몇몇 표본들로 시스템을 검사하기
  • 실제로 버그가 고쳐졌는지 알아보기 위해 코드의 바뀐 부분을 검사하기
  • 시스템의 성능 특성을 완벽하게 알기 위해 두 가지 다른 조건에서 시스템의 성능을 측정하기
  • 데이터의 무결성을 점검하기
  • 어려운, 혹은 반복하기 힘든 버그 해결의 실마리를 얻기 위해 통계 자료를 수집하기 

내가 이 글에서 실험 설계를 설명할 수 있으리라고는 생각하지 않는다. 독자 스스로 연구하고 연습해 보아야 할 것이지만, 두 가지 짧은 조언을 해 줄 수는 있겠다.

첫째, 자신의 가설이나 점검하려고 하는 검증 조건(assertion)이 무엇인지 명쾌해야 한다. 혼돈스럽거나 다른 사람들과 함께 작업할 때는 가설을 적어 보는 것이 도움이 되기도 한다.

각 실험이 지난 실험에서 얻은 지식에 기반을 두는 일련의 실험들을 설계해야 하는 상황에 처할 때가 종종 있을 것이다. 그러므로 가능한 한 많은 정보를 얻어낼 수 있도록 실험을 설계해야 한다. 불행히도 이것은 각 실험이 단순명료해야 한다는 조건과 대립된다. 이런 상황에 대한 판단은 경험을 통해 개발해야 할 것이다.

2.2 팀의 기능들 

2.2.1 시간 추정이 중요한 이유 

소프트웨어 시스템이 최대한 빨리 적극적으로 활용되게 하기 위해서는 개발 계획을 세우는 것뿐만 아니라 문서화, 시스템 배치, 마케팅 등의 계획도 세워야 한다. 상업적인 프로젝트에서는 영업과 재무도 포함한다. 개발 시간을 예측할 수 없다면 이러한 것들을 효과적으로 계획하는 것은 불가능하다.

정확한 시간 추정은 예측 가능성을 높인다. 관리책임자들은 그렇게 되는 것을 매우 좋아하며, 또 당연히 그래야 한다. 관리책임자들은 소프트웨어를 개발하는 데 얼마나 시간이 걸릴지 정확하게 예측하는 것이 이론적으로나 실제적으로 불가능하다는 사실을 전혀 이해하지 못하는 경우가 있다. 우리는 이런 불가능한 일을 하도록 항상 요구받으므로 그 사실을 정직하게 대면해야 한다. 어쨌든 이 과제가 불가능하다는 것을 인정하지 않는 것은 부정직한 일이 될 것이므로 필요하다면 그것을 설명하라. 사람들은,

그 문제를 제대로 이해한 것이라면, (아무도 그 동안 우리를 방해하지 않는다고 할 때) 5주 안에 마칠 가능성이 50% 정도 있다고 추정됩니다. 


위의 문장이 실제로는,

그 일을 모두 5주 안에 틀림없이 마치겠습니다. 


위의 문장을 뜻한다고 부풀려 생각하는 놀라운 경향이 있으므로, 시간 추정에 대해 의사소통의 문제가 생길 가능성이 많다.

이러한 일상적인 해석의 문제가 있으므로 상사나 고객이 아무 것도 모른다 생각하고 그 시간 추정이 무엇을 의미하는 것인지 분명하게 논의해야 한다. 그리고 예상 시간이 아무리 틀림없어 보여도 다시 한 번 더 그것을 추정해 보아야 한다.

2.2.2 프로그래밍 시간을 추정하는 방법 

시간 추정은 연습이 필요하다. 또한 노력해야 한다. 시간 추정은 노력이 많이 드는 일이기 때문에, 특히 대규모 작업 시간을 추정해야 할 경우에는 시간 추정 자체에 드는 시간을 추정할 필요도 있다.

대규모 작업 시간을 추정해야 할 때에는 천천히 하는 것이 가장 정직한 것이다. 대부분의 기술자들은 열심이 있으며 사람들을 기쁘게 하고 싶어 하기 때문에 천천히 하는 것을 분명히 좋아하지 않을 것이다. 하지만 즉석으로 추정한 것은 대개 정확하지도 정직하지도 않다.

천천히 하는 동안 그 과제를 수행하거나 과제의 모형을 만드는 것에 대해 숙고할 수 있을 것이다. 정책의 압력을 피할 수 있다면 이것이 시간 추정을 도출할 수 있는 가장 정확한 방법이며, 실제로도 그대로 작업이 진행될 수 있을 것이다.

조사할 시간을 충분히 갖는 것이 불가능할 때에는, 우선 그 추정이 무엇을 뜻하는지 아주 분명하게 확정해야 한다. 추정 내용 기록의 첫 부분과 마지막 부분에 그 의미를 다시 써 놓으라. 과제를 점진적인 소규모 하위 과제들로 분해하되 각 소규모 과제가 하루 이상이 되지 않을 때까지, 이상적으로는 그 이하의 길이로 추정 내용 기록을 준비하라. 가장 중요한 것은 하나라도 빠뜨리는 일이 없도록 하는 것이다. 예를 들어, 문서화, 검사, 계획 시간, 다른 그룹과 회의 시간, 휴가 시간 등이 모두 매우 중요하다. 매일 바보들을 상대하며 보내는 시간이 있다면 그것도 추정 내용에 한 항목으로 적어 넣으라. 이렇게 하면 최소한 무엇 때문에 시간을 써 버리게 되는지 상사가 알아볼 수 있게는 될 것이며, 자신의 시간을 지킬 수 있게 될 것이다.

추정 시간을 은연중에 불려서 쓰는 기술자들도 있지만, 나는 그렇게 하지 말라고 권하고 싶다. 불려서 쓰는 것이 낳는 결과들 중 하나는 다른 사람의 신뢰를 잃게 된다는 것이다. 예를 들어, 어떤 기술자가 사실은 하루가 걸릴 것이라고 생각되는 어떤 과제를 3일로 추정했다고 하자. 그 기술자가 나머지 이틀은 문서 작업을 하거나 어떤 다른 유용한 프로젝트를 하겠다고 계획했을 수 있다. 하지만 그 과제가 단 하루 만에 끝났다는 것은 (그 사실이 알려졌다면) 추적할 수 있을 것이며, 일을 늦추거나 과대 추정했다는 기색이 보일 것이다. 자신이 실제로 하고 있는 것을 적절히 볼 수 있게 하는 것이 더욱 좋다. 문서 작업하는 데 드는 시간이 코딩 시간의 두 배가 된다는 사실을 시간 추정 내용에서 확인할 수 있다면, 이것을 관리책임자가 볼 수 있게 하는 것이 더욱 큰 이득이 될 것이다.

추정 시간은 숨김없이 불려서 쓰라. 어떤 과제가 하루가 걸릴 것 같은데, 현재 접근 방법이 들어맞지 않을 경우 열흘이 걸릴 수도 있다면, 이 사실을 어떻게든 추정 내용에 적으라. 그렇지 않으면 적어도 추정한 확률을 가중치로 한 평균값을 계산하라. 알 수 있고 추정할 수 있는 위험 부담 요소는 모두 일정에 들어가야 한다. 한 사람이라면 주어진 기간 동안 아프지 않을 수 있다. 하지만 여러 기술자들이 함께 하는 큰 프로젝트에서는 환자가 생기는 시간도 있고 휴가 기간도 있다. 필수로 참석해야 하는 회사의 연수 세미나가 일어날 확률은 얼마나 될까? 추정할 수 있다면 꼭 끼워 넣으라. 물론 알려지지 않은 미지수의 일, 즉 예측불허의 일들도 있다. 예측불허란 개별적으로는 추정할 수 없다는 말이다. 모든 예측불허의 일에 대해 공통적으로 쓰이는 한 항목을 만들거나, 상사와 의사소통하는 그 밖의 방식으로 그것들을 처리할 수 있을 것이다. 하지만 상사가 그것들의 존재를 잊어버리게 하지는 말라. 예측불허의 일을 생각하지 않고 시간을 추정한 그대로 일정이 잡히기는 지독하게도 쉽다.

팀 환경에서는, 그 일을 하는 사람이 그 시간을 추정하도록 해야 하며, 전체 추정 시간에 대해 팀 전체가 합의하도록 해야 한다. 사람들은 능력, 경험, 준비도, 자신감에 큰 차이가 있다. 능력 있는 프로그래머가 자기에게 맞게 추정한 것을 능력이 부족한 프로그래머들도 따라 하다가는 큰 문제가 생긴다. 팀 전체가 추정 내용에 대해 한 줄, 한 줄씩 동의하게 함으로써 팀 전체의 이해를 분명히 하고, 자원을 전술적으로 재분배할 수 있는 (예를 들어, 능력이 부족한 팀원에게서 능력 있는 팀원에게 짐을 넘기는) 기회도 생긴다.

수치로 나타낼 수 없는 큰 위험 부담이 있다면, 프로그래머는 관리책임자가 함부로 거기에 뛰어들었다가 그 위험이 발생했을 때 당황하지 않도록 강력하게 말해 줄 의무가 있다. 바라기에는 그 경우에 그 위험 부담을 줄이기 위해 필요한 모든 일을 하게 될 것이다.

익스트림 프로그래밍(Extreme Programming) 기법을 사용하도록 회사를 설득할 수 있다면 비교적 적은 것들만 추정해도 될 것이며, 더 재미있으면서 더 생산적으로 일할 수 있을 것이다.

2.2.3 정보를 찾는 방법 

알아야 하는 정보의 성격에 따라 그것을 찾는 방법이 결정된다.

어떤 소프트웨어의 최근 패치 단계와 같이 객관적이고 검증하기 쉬운 구체적인 것들에 대한 정보가 필요하다면, 그 정보에 대해 인터넷을 검색하거나 토론 그룹에 글을 올려 많은 사람들에게 공손히 물어 보라. 의견이나 주관적인 해석의 낌새가 있는 것은 절대 인터넷에서 검색하지 말라. 허튼 소리가 진실로 취급되는 비율이 매우 놓다.

어떤 것에 대한 생각이 변화해 온 역사와 같이 주관적인 것에 대한 일반적인 지식을 원한다면, (실제 건물이 있는) 도서관으로 가라. 예를 들어, 수학이나 버섯이나 신비주의에 대해 알고 싶다면 도서관으로 가면 된다.

사소하지 않은 어떤 일을 하는 방법을 알고 싶다면 그 주제에 대한 책을 두세 권 사서 읽으라. 소프트웨어 패키지를 설치하는 방법 같은 사소한 일을 하는 방법은 인터넷에서 배울 수 있다. 좋은 프로그래밍 기법 같은 중요한 것들을 인터넷에서 배울 수도 있지만, 그 결과를 검색하고 분류하거나 그 결과가 믿을 만한 것인지 파악하느라, 손으로 잡을 수 있는 책의 적당한 부분을 찾아 읽는 데 드는 시간보다 더 많은 시간을 낭비할 가능성이 크다.

"이 신제품 소프트웨어는 대규모의 데이터를 처리할 수 있는가?"와 같이 아무도 알 것 같지 않은 정보가 필요하다면, 어쨌든 인터넷이나 도서관을 검색해 봐야 할 것이다. 열심히 찾아도 찾을 수 없다면 그것을 확인하기 위한 실험을 설계해야 할 것이다.

어떤 특정한 상황에 대한 의견이나 가치 판단을 원한다면, 전문가에게 이야기하라. 예를 들어, 최신 데이터베이스 관리 시스템(DBMS)을 LISP로 만드는 것이 좋은 생각인지 알고 싶다면 LISP 전문가와 데이터베이스 전문가와 이야기해야 한다.

어떤 응용프로그램을 위한, 아직 발표되지 않은 더 빠른 알고리듬이 있는지 알고 싶다면 그 분야에서 일하는 사람과 이야기해야 할 것이다.

사업을 시작할 것인지 말 것인지에 대한 결정과 같이 자신만이 내릴 수 있는 개인적인 결정을 하려고 한다면, 그 생각에 대한 긍정적인 조건과 부정적인 조건을 나열해서 적어 보라. 그래도 결정을 못하겠다면 점(divination)을 쳐 보라. 어떤 생각에 대해 다각도로 연구해 봤고, 해야 할 일을 다 했고, 모든 결과와 긍정적, 부정적 조건들을 다 따져 봤다 해도, 아직은 결정하지 마라. 이제 머리는 잠시 쉬고 마음의 움직임을 따라 보라. 잘 의식하지 못하는 자신의 욕망을 파악하는 데에는 다양한 점 기법들이 유용하게 쓰일 수 있다. 이 기법들이 보여 주는 모호하고 무작위적인 패턴에 대해 자신의 잠재의식이 의미를 부여하게 될 것이기 때문이다.

2.2.4 사람들을 정보의 원천으로 활용하는 방법 

각 사람의 시간을 존중하고 자신의 시간과 균형을 맞추라. 어떤 사람에게 질문하는 것은 답을 얻는다는 것 이상의 것을 이루게 한다. 그 사람은 나의 존재를 인정하고 특정 질문에 귀를 기울이면서 나에 대해 알게 된다. 나도 마찬가지로 그 사람을 알게 되며, 찾던 답도 알 수 있게 된다. 대개의 경우 이것이 질문 자체보다 더욱 중요하다.

하지만 그것을 반복하게 되면 그 가치는 줄어든다. 질문을 한다는 것은 결국 어떤 사람이 갖고 있는 소중한 필수품, 즉 그들의 시간을 사용하는 것이다. 의사소통의 소득은 그 비용과 비교하여 저울질해 보아야 한다. 게다가 그 비용과 소득은 사람마다 다르다. 나는 100명의 부하 직원이 있는 사람은 그 조직의 모든 사람들에게 한 달에 5분씩은 이야기할 시간이 있어야 한다고 확신한다. 이것은 자기 시간의 약 5%를 할애하는 것이 될 것이다. 하지만 10분은 너무 많은 것 같고, 같은 5분이라 해도 직원이 1,000명이라면 그것도 너무 많다. 자신의 조직에 속한 사람들에게 이야기하는 시간의 양은 그 사람들의 (직위보다는) 역할에 따라 다르다. 상사에게 이야기하는 시간이 상사의 상사에게 이야기하는 시간보다는 더 많아야 한다. 불편할 수도 있겠지만, 무엇에 대해서든 자신의 모든 상급자들에게 매달 조금씩 이야기를 할 의무가 있다고 생각한다.

여기에서 기본 법칙은, 우리에게 잠깐 이야기를 하는 사람은 모두 이득을 얻지만, 이야기가 길어질수록 그 이득은 적어진다는 것이다. 우리는 그들에게 이 이득을 나눠주고 그들과 대화하면서 이득을 받아와야 하며, 들인 시간과 이득 사이에 균형을 맞춰야 한다.

자신의 시간을 존중하는 것도 중요하다. 누군가에게 이야기하는 것을 통해, 그들의 시간을 쓰게 한다 해도, 자신의 시간을 많이 아낄 수 있다면, 그 사람의 시간이 나의 시간보다 더 소중하다고 생각하지 않는 한, 그것을 해야 한다. 우리 부족(tribe)에 대해서도 마찬가지이다.

특이한 사례로서 여름방학 인턴의 경우를 들 수 있다. 고급 기술직에 들어온 여름방학 인턴이 무슨 큰 일을 해 낼 것이라고 기대하기는 힘들다. 그들은 단지 거기 있는 모든 사람들을 괴롭게 할 것이라고 기대할 수 있을 것이다. 그렇다면 왜 이걸 참아야 하는가? 괴롭힘을 받는 사람은 그 인턴에게서 중요한 것을 얻게 될 것이기 때문이다. 그들은 살짝 자랑할 수 있는 기회가 생긴다. 새로운 아이디어를 들을 기회가 생길지도 모른다. 다른 시각에서 관찰해 볼 기회가 생긴다. 그 인턴을 채용하려는 의도가 있을 수도 있지만, 그렇지 않다 하더라도 얻는 것이 많다.

솔직히 누군가가 도움이 되는 말을 해 줄 수 있겠다는 생각이 들면, 그들에게 지혜와 판단력을 나눠 달라고 부탁해야 한다. 그러면 그 사람들은 뿌듯해 할 것이며, 나는 그들에게 무엇인가를 배우고 또 무엇인가를 가르쳐 주게 될 것이다. 좋은 프로그래머에게 영업 부사장의 조언은 별로 필요가 없겠지만, 만약 필요하게 된다면 반드시 조언을 구해야 한다. 나는 우리 영업부 직원들이 하는 일을 더 잘 이해하기 위해서 영업 관련 전화 통화 내용 몇 건을 같이 듣게 해 달라고 요청한 적도 있다. 30분도 채 안 걸린 일이었지만 그런 작은 노력이 영업부에 좋은 인상을 주었다고 생각한다.

2.2.5 현명하게 문서화하는 방법 

아무도 읽지 않을 쓰레기 같은 글을 쓰기에는 인생은 너무 짧다. 쓰레기 같은 글은 아무도 읽지 않을 것이다. 따라서 문서화를 조금이라도 잘 하는 것이 최선이다. 관리책임자들은 이것을 이해하지 못하는 경우가 많다. 질이 떨어지는 문서를 보면서도 그들이 프로그래머들에게 의존하지 않고 있다는 헛된 안도감을 갖게 하기 때문이다. 누가 나에게 내가 작성한 문서가 정말 쓸모없다고 단호하게 말한다면, 그 말을 인정하고 조용히 다른 직업을 찾아보는 게 좋을 것이다.

문서를 잘 만들어내는 데 걸리는 시간의 양을 정확히 추정하여 문서화에 대한 요구를 완화시키는 데 드는 시간을 추정하는 데 이용하는 것만큼 효과적인 일은 없을 것이다. 진실은 냉혹하다. 문서화는 제품 검사처럼 코드 개발보다 더 긴 시간이 걸릴 수 있다.

문서화를 잘 하기 위해서는 우선 작문 실력이 있어야 한다. 작문에 대한 책을 찾아서 공부하고 실습해 보기를 권한다. 글이 깔끔하지 못하고 문서에 써야 하는 언어를 잘 모른다 해도, 다음의 황금률을 따르면 된다. "무엇이든지 남에게 대접을 받고자 하는 대로 너희도 남을 대접하라." 시간 여유를 가지고서 이 문서를 읽을 사람이 누구이며, 그 사람이 무엇을 얻고 싶어 할지, 그리고 그것을 어떻게 가르쳐 줄 수 있을지 진지하게 생각해 보라. 그렇게만 해도 평균 수준 이상의 문서는 만들어낼 수 있을 것이며 프로그래머로서도 훌륭하게 될 것이다.

코드 자체에 대해 문서화를 하게 될 때에는, 프로그래머가 아닌 사람들이 주로 읽을 문서를 작성할 때와는 반대로, 내가 아는 최고의 프로그래머들이 모두 공감하고 있는 바와 같이, 보면 바로 알 수 있게 코드를 작성하고, 코드만으로 그 의미가 분명하지 않은 곳에만 코드에 대해 문서화하라. 이렇게 하는 것이 좋은 두 가지 이유가 있다. 첫째로, 코드 수준의 문서를 봐야 하는 사람이라면 대부분의 경우에 어떻게든 그 코드를 읽을 수 있으며 그것을 선호하기 때문이다. 물론, 이것은 초보보다는 경력 있는 프로그래머에게 더 적당한 말이다. 하지만 더 중요한 것은, 따로 문서화하지 않을 경우, 코드와 문서가 불일치할 리가 없을 것이라는 사실이다. 소스 코드는 아무리 잘못되어 봐야 틀리거나 혼돈스러울 뿐이다. 하지만 문서는 정확하게 쓰지 않는다면 거짓말을 할 수 있고 이것은 천 배나 더 나쁜 일이다.

책임감 있는 프로그래머는 이 사실을 가볍게 받아들이지 않을 것이다. 보면 바로 알 수 있는 코드를 어떻게 작성할 것인가? 그것이 과연 무슨 뜻인가? 바로 이런 뜻이다.
  • 누군가 읽을 것이라는 사실을 염두에 두고 코드를 작성하기
  • (앞에서 말한) 황금률을 적용하기
  • 복잡하지 않은 해법을 선택하기 (다른 해법이 용케 더 빠르다 해도)
  • 코드를 어지럽게 하는 사소한 최적화 시도는 포기하기
  • 코드를 읽을 사람을 생각하면서 그 사람이 쉽게 이해할 수 있게 하기 위해 시간을 할애하기
  • "foo", "bar", "doIt" 같은 함수명은 절대 쓰지 않기! 

2.2.6 형편없는 코드를 가지고 작업하기 

다른 사람이 작성한 질이 떨어지는 코드를 가지고 작업해야 하는 경우가 많다. 하지만, 신발을 신고 걸어 보기까지는 그 신발이 아주 형편없다고 생각하지는 말라. 그 사람이 일정의 압박에 맞추기 위해 어떤 일을 빨리 끝내도록 독촉을 받았을 수 있다. 어떻든 간에, 불분명한 코드를 가지고 작업을 하려면 그것을 이해해야 한다. 그 코드를 이해하자면 시간이 걸릴 것이고, 그 시간은 정해진 일정의 어디에선가 빼 와야 할 것이므로, 이 사실을 분명히 해야 한다. 소스 코드를 이해하기 위해서는 그것을 읽어 볼 수밖에 없다. 아마도 그것을 가지고 실험을 해 봐야 할 것이다.

비록 자기 자신만을 위한 것이라 해도, 코드에 대한 문서화 노력을 통해 생각해 보지 못했던 각도에서 그 코드를 생각해 볼 수 있으므로, 지금이 문서화하기 좋은 시간이며, 그 결과로 나온 문서는 유용할 것이다. 이렇게 하는 동안 그 코드의 일부나 전체를 재작성하려면 무엇이 필요할 것인지에 대해 생각해 보라. 그것을 재작성하는 것이 실제로 시간을 아끼는 일이 될 것인가? 코드를 재작성한다면 더 믿을 만하게 될 것인가? 이 때에는 자만심을 주의하도록 하라. 코드를 재작성한다면, 그것을 검사해야 하는 부담은 얼마나 될 것인가? 얻을 수 있는 이득과 비교해 볼 때 정말로 재검사할 필요가 있는 것인가?

자기가 작성하지 않은 코드에 대한 작업 시간을 추정할 때, 그 코드의 품질에 따라 문제나 예측불허의 것이 생길 위험 가능성에 대한 인식이 달라진다.

깔끔하지 못한 코드에는 프로그래머의 최고의 도구 두 가지, 즉 추상화와 캡슐화가 특히 잘 적용된다는 사실을 잘 기억해 두라. 코드의 큰 부분을 재설계할 수는 없겠지만, 어느 정도 추상화를 해 줄 수 있다면, 전체를 재작업하지 않고서도 좋은 설계가 주는 이득을 어느 정도는 얻을 수 있을 것이다. 특히 안 좋은 부분은 다른 부분에서 떼어 놓아 독립적으로 재설계할 수 있도록 해 볼 수도 있다.

2.2.7 소스 코드 제어 시스템을 이용하는 방법 

소스 코드 제어 시스템은 프로젝트를 효과적으로 관리할 수 있게 해 준다. 이 시스템은 개인에게도 유용하고 그룹에게는 필수적이다. 이 시스템은 여러 버전의 모든 변경 사항을 추적하므로 어떤 코드도 없어지지 않으며 변경 사항들의 의미를 기록해 놓을 수 있다. 소스 코드 제어 시스템이 있으면 소스 코드의 일부를 버리거나 디버그 코드를 넣는 일을 자신 있게 할 수 있다. 변경한 코드는 팀과 공유하거나 배포할 공식 코드와 잘 분리되어 보존되기 때문이다.

나는 뒤늦게야 소스 코드 제어 시스템의 이득을 알게 되었지만, 이제는 혼자 하는 프로젝트라 해도 그것 없이는 살 수 없을 것 같다. 일반적으로 이 시스템은 동일한 코드를 놓고 팀으로 작업할 때 필요하다. 하지만 이 시스템은 또 다른 큰 장점이 있다. 즉 이것을 통해 소스 코드를 성장하는 유기체로 인식하게 해 준다는 점이다. 변경된 것마다 새 이름이나 번호를 붙여 새로운 개정판으로 표시하기 때문에, 소프트웨어가 눈에 보이게 점진적으로 향상되어 간다고 생각하게 되는 것이다. 이것은 특히 초보자들에게 유용하다고 생각된다.

소스 코드 관리 시스템을 잘 이용하는 방법 중 하나는, 항상 최신의 상태를 유지하면서 며칠 동안 가만히 있는 것이다. 며칠 안에 마무리할 수 없는 코드는 체크인 상태로 있지만, 그것은 활성화되지 않고 호출되지 않을 상태로 있거나, 그 자신에서 갈라져 나온 분기(branch) 위치에 있을 것이므로, 다른 누구에게 어떠한 문제도 일으키지 않을 것이다. 실수가 있는 코드를 올려서 팀 동료들의 작업을 더디게 하는 것은 심각한 오류이다. 이것은 언제나 금기 사항이다.

2.2.8 단위별 검사를 하는 방법 

단위별 검사, 즉 코드로 만든 기능의 각 부분을 그것을 작성한 팀에서 검사하는 것은 코딩의 일부이지, 코딩과 다른 무엇이 아니다. 코드를 어떻게 검사할지 설계하는 것도 코드 설계의 한 부분이다. 비록 한 줄이라 해도 검사 계획을 기록해 놓아야 한다. 때때로 그 검사는 다음과 같이 단순할 것이다. "이 버튼이 좋아 보이는가?" 때로는 다음과 같이 복잡할 수도 있다. "이 정합(matching) 알고리듬은 틀림없이 정확한 짝을 찾아낼 것인가?"

할 수 있다면 검증 조건(assertion) 확인 방법이나 검사 자동화 도구(test driver)를 사용하라. 이 방법은 버그를 일찍 잡을 수 있게 해 줄 뿐만 아니라, 나중에도 유용하게 쓰일 수 있으며, 이렇게 하지 않았더라면 한참 고민하게 되었을 애매한 문제들을 줄일 수도 있을 것이다.

익스트림 프로그래밍(Extreme Programming) 기법을 사용하는 개발자들은 단위별 검사를 최대한 효과적으로 활용하여 코드를 작성한다. 이 작성 방법을 추천하는 것만큼 좋은 일도 없을 것이다.

2.2.9 막힐 때는 잠깐 쉬어라 

막힐 때는 잠깐 쉬어라. 나는 막힐 때는 15분 정도 명상을 하곤 한다. 그러면 다시 문제로 돌아왔을 때 그것이 마술같이 해결되곤 한다. 규모가 클 경우에는 하룻밤 잘 자는 것이 같은 효과를 내기도 한다. 잠시 다른 활동을 하는 것이 효과적일 수도 있다.

2.2.10 집에 갈 시간을 인지하는 방법 

컴퓨터 프로그래밍은 문화라고 할 만한 활동이다. 불행한 것은, 이것이 정신적, 신체적 건강을 그렇게 중요하게 생각하지 않는 문화라는 사실이다. 문화적이고 역사적인 이유 (예를 들어, 컴퓨터가 쉬는 밤중에 작업할 필요) 때문에, 그리고 저항할 수 없는 출시 일정의 압박과 프로그래머의 부족 때문에 컴퓨터 프로그래머는 전통적으로 초과 근무를 해 왔다. 소문으로 듣는 모든 이야기를 믿을 것이라고 생각하지는 않지만, 주당 60시간 근무는 일상적이며, 50시간은 상당히 적은 편에 속한다. 즉, 이보다 더 많은 시간이 요구되는 경우가 있다는 말이다. 이것은 좋은 프로그래머에게는 심각한 문제이다. 그는 자기 자신만 아니라 자기 팀 동료들도 책임지고 있기 때문이다. 자기가 집에 갈 시간, 때로는 다른 사람을 집에 보낼 시간도 인지하고 있어야 한다. 아이를 키우는 불변의 법칙이 없듯이, 이 문제를 해결할 불변의 법칙은 없다. 모든 사람은 서로 다르기 때문이다.

주당 60시간 이상 일하는 것은, 짧은 기간 (한 주 정도) 동안이나 해 볼 수 있을 정도로, 내게는 엄청난 노력이 필요하지만, 때로는 그렇게 해야 할 때가 있다. 한 사람에게 60시간 동안 일을 하게 하는 것이 공정한 것인지는 잘 모르겠다. 사실 40시간이 공정한 것인지도 잘 모르겠다. 하지만 분명한 것은, 초과 근무하는 시간 동안 별로 얻는 것 없이 오래 일하기만 하는 것은 어리석은 일이라는 사실이다. 나에 대해 말하자면, 주당 60시간 이상 일하는 것이 그렇다. 개인적으로는, 프로그래머는 고귀한 의무(noblesse oblige)를 다해야 하고 무거운 짐을 져야 한다고 생각한다. 하지만 봉이 되는 것은 프로그래머의 의무가 아니다. 그런데 슬프게도 프로그래머들은, 경영진의 눈에 들기 위해 애쓰는 관리책임자 같은 이들을 위해 재주를 부리는 곰이 되는 경우가 있다. 프로그래머들은, 다른 사람들을 기쁘게 하고 싶고, 싫다는 말을 잘 못하기 때문에, 종종 이런 요구에 굴복한다. 이를 대처하기 위한 네 가지 방어법이 있다.
  • 회사의 모든 사람들과 최대한 많이 대화하여 아무도 무슨 일이 일어나고 있는지에 대해 경영진을 현혹하지 못하게 하라.
  • 시간을 추정하고 일정을 잡을 때 방어적이고 명백하게 하여, 모든 사람들이 일정이 어떻게 되고 현재 어디쯤 가고 있는지 잘 볼 수 있게 하라.
  • 요구를 거부하는 법을 배우고, 필요하다면 팀이 함께 거부하도록 하라.
  • 어쩔 수 없다면 회사를 그만두라. 

많은 프로그래머들이 좋은 프로그래머이고, 좋은 프로그래머는 많은 것을 이루길 원한다. 이를 위해 그들은 시간을 효과적으로 관리해야 한다. 어떤 문제에 대해 생각을 가다듬고 거기에 깊이 몰두하게 될 때까지는 상당한 수고가 필요하다. 많은 프로그래머들은 생각을 가다듬고 몰두할 수 있는, 방해받지 않는 긴 시간이 있을 때 가장 잘 일할 수 있다고 한다. 하지만 사람들은 잠도 자고 다른 의무들도 이행해야 한다. 모든 사람들은 자신의 인간적 리듬과 업무적 리듬을 모두 만족시키는 방법을 찾아야 한다. 모든 프로그래머는, 아주 중요한 회의에만 참석하고 나머지는 일에 집중하는 날들을 확보하는 것과 같이, 효율적인 업무 기간을 획득하기 위해 최선을 다해야 한다.

나는 아이들이 있기 때문에 가끔이라도 아이들과 저녁 시간을 보내기 위해 노력한다. 나에게 가장 잘 맞는 리듬은, 하루 날 잡아 오래 일하고, 사무실이나 사무실 부근에서 잠을 잔 다음 (나는 집에서 직장까지 통근 시간이 길다), 일찍 집에 가서 아이들이 잠자리에 들기 전까지 시간을 보내는 것이다. 이것이 편안하지는 않지만, 여태껏 시험해 본 최선의 타협점이었다. 전염성 있는 병에 걸렸다면 집에 가라. 죽고 싶다는 생각이 든다면 집에 가야 한다. 몇 초 이상 누군가를 죽이고 싶다는 생각이 든다면 집에 가서 쉬어야 한다. 누군가가 가벼운 우울증을 넘어서 심각한 정신 이상이나 정신병의 증세를 보인다면 집에 가게 해야 한다. 피로 때문에 평소와 달리 부정직하거나 남을 속이고 싶다는 유혹이 든다면 쉬어야 한다. 피로와 싸우기 위해 마약이나 각성제를 쓰지 말라. 카페인을 남용하지도 말라.

2.2.11 까다로운 사람들과 상대하는 방법 

까다로운 사람들과 상대해야 하는 일이 있을 것이다. 자기 자신이 까다로운 사람일 수도 있다. 나 자신이 같이 일하는 사람들이나 권위 있는 인물들과 수시로 충돌하는 유형의 사람이라면, 여기에서 볼 수 있는 독립심은 소중하게 여겨야 할 것이나, 자신의 지성이나 원칙들을 희생하지 않는 범위 내에서 인간관계의 기능도 길러야 할 것이다.

이런 종류의 일을 겪어 보지 않았거나, 지금까지 살면서 직장 생활에는 별로 쓸모없는 행동 양식만 익혀 온 프로그래머들에게는 이것이 짜증스러운 일이 될 수 있다. 까다로운 사람들은 대개 반대 의견에 단련되어 있고 다른 사람들과 타협해야 한다는 사회적 압력에 별로 영향을 받지 않는다. 이 때 열쇠는 그 사람들을 적당히 존중해 주는 것이다. 이것은 내가 하고 싶은 것 이상으로 해 주는 것이지만, 그 사람들이 원하는 만큼은 안 될 것이다.

프로그래머들은 팀으로 함께 일해야 한다. 의견 불일치가 생기면, 어떻게든 해결해야 한다. 무작정 피할 수는 없는 노릇이다. 까다로운 사람들은 종종 매우 똑똑하고 쓸 만한 이야기를 하기도 한다. 까다로운 사람에게 편견 없이 귀를 기울이고 이해해 주는 것은 매우 중요하다. 대화 단절은 의견 불일치의 기반이 되지만, 강한 인내심으로 극복할 수 있는 경우도 있다. 대화가 산뜻하고 정감 있게 이뤄지도록 노력하고, 의견 충돌을 일으킬 만한 논쟁에 말려들지 말라. 이해하려고 노력할 만큼 한 뒤에는 결단을 내리라.

으스대는 사람의 강요 때문에 동의하지도 않는 일을 하지는 말라. 자신이 팀장이라면 최선이라고 생각하는 일을 하라. 개인적 이유로 결정을 내리지 말고, 자기가 결정한 근거를 설명할 준비를 해 두라. 까다로운 사람이 팀장이라면, 그의 결정이 개인적으로 영향을 미치지 않도록 하라. 일이 자기 방식대로 진행되지 않아도, 그 다른 방식에 따라 마음을 다해 일하라.

까다로운 사람들도 변하며 나아지기도 한다. 내 눈으로 직접 본 적도 있지만, 그렇게 흔하지는 않다. 어쨌든 모든 사람은 수시로 오르락내리락하기 마련이다.

모든 프로그래머, 특히 팀장들이 대면해야 하는 도전들 중 하나는 까다로운 사람을 전적으로 몰두하게 하는 것이다. 그런 사람들은 다른 사람에 비해서 일의 책임을 피하거나 수동적으로 저항하는 경향이 크다.

3 중급자 

3.1 개인적 기능들 

3.1.1 의욕을 계속 유지하는 방법 

프로그래머들이 아름답고 유용하고 멋진 것을 만들고 싶어 하는 의욕이 매우 크다는 사실은 훌륭하고도 놀라운 일이다. 이러한 욕구는 프로그래머에게만 있는 것도 아니고 보편적인 것도 아니지만, 이것은 프로그래머들 사이에 매우 강하고 일반적이어서 다른 일을 하는 사람들과 구분이 된다.

이것은 실제로 중요한 결과를 낳는다. 프로그래머에게 아름답지도 유용하지도 멋지지도 않은 일을 시키면 그들은 사기가 떨어진다. 너저분하고 멍청하고 지루한 일을 해서 돈을 많이 벌기도 한다. 하지만 결국에는 재미있게 하는 일이 회사에 큰 돈을 벌어다 준다.

분명히 의욕을 불러일으키는 기법들을 중심으로 조직된 모든 산업 분야에서 여기에 적용되는 것들이 있다. 프로그래밍에 해당한다고 인정할 만한 것들은 다음과 같다.
  • 그 일을 자랑스럽게 이야기한다.
  • 새로운 기법, 언어, 기술을 적용할 기회를 찾는다.
  • 각 프로젝트에서 아무리 작더라도 무엇인가를 배우거나 가르치려고 노력한다. 

끝으로, 할 수 있다면, 개인적으로 의욕을 얼마나 고취시키는가에 따라 자신의 일의 영향력을 가늠해 보라. 예를 들어, 버그를 고칠 때, 내가 버그를 몇 개나 고쳤는지 세는 것으로 의욕이 생기지는 않는다. 지금까지 고친 버그의 개수가 아직 남아 있는 버그의 개수와 무관하며, 그 개수는 회사의 고객들에게 기여하는 전체 가치에서 아주 사소한 부분을 차지할 뿐이기 때문이다. 하지만, 버그 하나마다 고객 한 사람이 기뻐한다고 생각하면 그것은 개인적으로 의욕이 생기게 한다.

3.1.2 널리 신뢰받는 방법 

신뢰받기 위해서는 신뢰받을 만해야 한다. 또한 활동이 두드러져야 한다. 자신에 대해 아무도 알지 못한다면, 아무런 신뢰도 받을 수 없을 것이다. 팀 동료처럼 자신과 가까운 사람들과 같이 있을 때는 이것이 큰 문제가 아닐 것이다. 신뢰는 자기 부서나 팀이 아닌 사람들에게 응답하고 지식을 줌으로써 쌓아간다. 때로는 이러한 신뢰를 악용하여 불합리한 부탁을 하는 사람도 있다. 이럴 때에는 걱정하지 말고, 그 부탁을 들어주자면 자신이 무슨 일을 포기해야 하는지 설명하면 된다.

모르는 것을 아는 체하지 말라. 팀 동료가 아닌 사람들에게는 "머리에서 맴돌면서 기억나지 않는 것"과 "전혀 알 수 없는 것"을 명확히 구분해야 할 것이다.

3.1.3 시간과 공간 사이에서 균형을 잡는 방법 

대학에 가지 않아도 좋은 프로그래머는 될 수 있지만, 기초적인 계산 복잡도 이론을 모른다면 좋은 중급 프로그래머는 될 수 없다. O("big O") 표기법을 알 필요는 없지만, "상수 시간", "n log n", "n 제곱"의 차이는 이해할 수 있어야 한다. 이런 지식이 없어도 시간과 공간 사이에서 균형을 잡는 방법을 직관으로 알고 있을 수 있지만, 그런 지식이 없다는 것은 동료들과 대화할 때 필요한 튼튼한 기초가 없는 것과 같다.

알고리듬을 설계하거나 이해할 때, 그것을 실행하는 데 걸리는 시간은 입력 값의 크기의 함수인 경우가 있다. 이 때, 알고리듬의 실행 시간이 (변수 n으로 표현되는) 그 크기와 그 크기의 로그값의 곱에 비례하면, 그 최악(또는 기대되는, 또는 최선)의 실행 시간이 "n log n"이라고 말할 수 있다. 이 표기법과 말하는 방식은 자료 구조가 차지하는 공간에도 마찬가지로 적용될 수 있다.

내게는, 계산 복잡도 이론이 물리학만큼이나 아름답고 심오하게 보인다. (조금 딴 길로 샌 것 같다!)

시간(프로세서 속도)과 공간(메모리)은 서로 균형을 맞출 수 있다. 공학이란 타협에 대한 것이며, 이것은 아주 좋은 예가 된다. 이것은 항상 체계적인 것은 아니다. 일반적으로 꽉 조이는 인코딩을 통해 공간을 절약할 수 있지만, 그것을 디코딩해야 할 때는 계산 시간이 더 많이 걸릴 것이다. 캐쉬를 사용함으로써, 즉 가까이에 복사본을 저장할 공간을 사용함으로써 시간을 절약할 수 있지만, 캐쉬의 내용을 일관되게 유지하고 있어야 할 것이다. 자료 구조에 더 많은 정보를 담음으로써 시간을 절약할 수 있는 경우가 있다. 이것은 대개 적은 공간을 차지하지만 알고리듬이 복잡해질 수 있다.

공간이나 시간의 균형 관계를 개선하는 것은 종종 다른 쪽이 극적으로 변하게 할 수 있다. 하지만 이 작업을 하기 전에 지금 개선하려고 하는 것이 정말로 그런 개선이 필요한 것인지 스스로 물어야 한다. 알고리듬을 가지고 작업하는 것은 재미있는 일이지만, 아무 문제가 없는 것을 개선하려는 것은 눈에 띌 만한 차이는 못 내면서 검사할 짐만 늘어나게 할 것이라는 냉엄한 사실에 대해 눈이 가려지지 않도록 조심해야 한다.

최신 컴퓨터의 메모리는, 프로세서 시간과 달리 벽에 부딪히기 전까지는 그것이 어떻게 쓰이는지 볼 수 없기 때문에, 값싼 것처럼 보인다. 하지만 문제가 생기기라도 하면 그것은 재앙이 된다. 메모리를 사용하는 데에는, 메모리에 상주해야 하는 다른 프로그램에 미치는 영향이나, 메모리를 할당하고 해제하는 데 드는 시간 등의 숨어 있는 비용이 있다. 속도를 얻으려고 공간을 써 버리기 전에 이 사실을 주의 깊게 생각하라.

3.1.4 압박 검사를 하는 방법 

압박 검사(stress test)는 재미있다. 처음에는 압박 검사의 목적이 시스템에 부하가 걸려도 잘 동작하는지 알아보는 것으로 보인다. 실제로는 시스템에 부하가 걸려도 잘 동작하지만 부하가 아주 클 때는 어떤 방식으로든 동작이 멈추는 경우가 대부분이다. 나는 이것을 벽에 부딪침 또는 탈진이라고 부른다. 예외가 있기도 하지만, 거의 항상 '벽'은 있다. 압박 검사의 목적은 그 벽이 어디에 있는지 알아보는 것이며, 그 벽을 얼마나 더 밀어낼 수 있을지 알아보는 것이다.

압박 검사 계획은, 그것을 통해 프로젝트에서 기대하는 바가 무엇인지 명확해지기 때문에, 프로젝트 초기에 세워야 한다. 웹 페이지 요청에 2초가 걸리는 것은 비참한 실패일까, 대단한 성공일까? 동시 사용자 500명은 충분한가? 이것은 물론 상황에 따라 다르지만, 그 요구에 부응하는 시스템을 설계할 때 그 답을 알고 있어야 한다. 압박 검사는 실제 상황을 충분히 쓸 만하게 본떠서 해야 한다. 동시에 시스템을 사용하면서 오류를 일으키거나 무엇을 할지 예측할 수 없는 500명의 사람들을 쉽게 흉내 내는 일이 실제로는 불가능하지만, 500개의 모의실험을 만들어 사람들이 어떻게 행동할지 본뜨게 해 보는 정도는 할 수 있을 것이다.

압박 검사를 할 때는 가벼운 부하에서 시작해서, 입력 비율이나 입력 크기와 같은 어떤 범위에 따라 벽에 부딪칠 때까지 부하를 늘려간다. 벽이 요구 조건을 만족하기에 너무 가깝다면, 어떤 자원이 병목이 되어 있는지 알아내라. (대개 주된 원인이 있기 마련이다.) 그것이 무엇 때문인가? 메모리? 프로세서? I/O? 네트워크 대역폭? 데이터 쟁탈? 그 후에는 그 벽을 어떻게 움직일 수 있을지 알아내라. 벽을 움직이는 것, 즉 시스템이 견딜 수 있는 최대 부하를 증가시키는 것이 부하가 적은 시스템의 성능에 도움이 되지 않거나 오히려 해가 될 수도 있다는 사실은 기억하라. 보통은 큰 부하가 걸렸을 때의 성능이 적은 부하가 걸렸을 때의 성능보다 중요하다.

머리 속으로 모형을 그릴 수 있도록 여러 가지 다른 차원들도 살필 수 있어야 한다. 한 가지 기법만으로는 충분하지 않다. 예를 들어, 로그 기록은 시스템에서 일어난 두 사건 사이의 벽시계 시간에 대해 잘 알 수 있게 해 주지만, 그것이 잘 구성되어 있지 않은 한, 메모리 사용이나 자료 구조의 크기에 대해서는 살펴볼 수 없다. 같은 원리로, 현대적인 시스템에서는 많은 컴퓨터와 많은 소프트웨어 시스템들이 서로 협력하여 동작하는데, 특히 벽에 부딪쳤을 때 (즉, 성능이 입력 크기에 비례하지 않게 될 때) 이 다른 소프트웨어 시스템들이 병목이 될 수 있다. 이 시스템들을 살펴볼 수 있는 것은, 모든 관련 장비들의 프로세서 부하만 측정할 수 있다 해도, 큰 도움이 될 수 있을 것이다.

벽이 어디에 있는지 아는 것은, 벽을 옮기는 것뿐만 아니라 사업을 효과적으로 관리할 수 있도록 예측 가능성을 마련해 주는 데에도 필수적이다.

3.1.5 간결성과 추상성의 균형을 잡는 방법 

추상성은 프로그래밍의 열쇠이다. 얼마나 추상화해야 할지는 주의해서 선택해야 한다. 초보 프로그래머들은 열심이 지나쳐서 실제로 필요 이상으로 추상화하는 경우가 있다. 이것의 징조 중 하나는 아무 코드도 들어 있지 않으면서, 다른 것을 추상화하는 것 외에 아무 일도 하지 않는 클래스를 만드는 것이다. 이런 것의 매력은 이해할 만하지만 코드 간결성의 가치도 추상성의 가치에 비교하여 재 봐야 한다. 때때로 열정적인 이상주의자들이 저지르는 실수를 보게 된다. 즉 프로젝트 초기에 수많은 클래스들을 정의하면서 그것을 통해 추상성을 멋지게 달성하고, 발생할 수 있는 모든 사태를 다룰 수 있을 것으로 기대한다. 그런데 프로젝트가 진행되고 피로가 쌓임에 따라 코드 자체가 너저분해진다. 함수의 몸체는 되어야 할 것 이상으로 길어진다. 비어 있는 클래스들은 문서화하는 데 짐이 되고 압박이 오면 결국 잊혀진다. 추상화에 쏟은 에너지가 프로그램을 간결하고 단순하게 하는 데에 쓰였다면 최종 결과가 더 좋아졌을지도 모른다. 이것은 사색적인(speculative) 프로그래밍의 전형이다. 나는 폴 그레이엄(Paul Graham)의 "간결함이 힘이다(Succinctness is Power)"라는 글을 강력 추천한다. <PGSite>

정보 은닉이나 객체 지향 프로그래밍과 같은 유용한 기법들을 지나치게 사용하면서 독단적 견해가 생기기도 한다. 이 기법들은 코드를 추상화하게 하고 변화를 예측하게 한다. 하지만 개인적인 생각으로는 너무 사색적인 코드를 작성하지 않는 것이 좋다. 예를 들어, 어떤 객체의 정수 변수를 변경자(mutator)와 접근자(accessor) 뒤에 숨겨서 변수 자체는 드러나지 않고 작은 접점(interface)만 드러나게 하는 것은 받아들일 만한 스타일이다. 이를 통해서, 호출하는 코드에 영향을 주지 않으면서 그 변수의 구현 방식을 바꿀 수 있으며, 이것은 매우 안정된 API를 내놓아야 하는 라이브러리 제작자에게 적합할 것이다. 하지만 나는, 호출하는 코드를 우리 팀이 소유하고 있어서 호출되는 쪽만큼 호출하는 쪽도 다시 코딩할 수 있다면, 코드가 장황해지는 것을 감수할 만큼 이것이 이득이 된다고 생각하지는 않는다. 이런 사색적 프로그래밍으로 얻는 이득을 따져 보면 코드 너덧 줄 늘어나는 것도 아깝다.

이식성(portability)에 대해서도 비슷한 문제를 볼 수 있다. 모든 코드는 다른 컴퓨터, 컴파일러, 소프트웨어 시스템, 플랫폼에 바로 혹은 아주 쉽게 이식될 수 있어야 하는가? 나는 이식성은 없지만 간결하면서 쉽게 이식할 수 있는 코드가, 장황하면서 이식성 있는 것보다 낫다고 생각한다. 특정 DBMS에 맞는 데이터베이스 질의를 하는 클래스와 같이 이식성 없는 코드를 정해진 영역에 한정해 놓는 것도 비교적 쉬우면서 분명히 좋은 생각이다.

3.1.6 새로운 기능을 배우는 방법 

새로운 기능, 특히 기술과 무관한 것을 배우는 것은 무엇보다 재미있는 일이다. 이것이 프로그래머들의 의욕을 얼마나 많이 불러일으키는지 이해하는 회사들은 사기가 더욱 높아질 수 있을 것이다.

인간은 행함으로 배운다. 책 읽기와 수업 듣기가 유용한 것은 틀림없지만, 아무 프로그램도 작성해 보지 않은 프로그래머를 인정할 수 있겠는가? 어떤 기능이든 배우기 위해서는 그 기능을 스스럼없이 연습해 볼 수 있어야 할 것이다. 새로운 프로그래밍 언어를 배울 때에는, 큰 프로젝트를 해야 하게 되기 전에 그 언어를 사용하는 작은 프로젝트를 해 보라. 소프트웨어 프로젝트 관리를 배울 때에는, 작은 프로젝트를 먼저 관리해 보도록 하라.

좋은 사수(mentor)가 있다고 해서 스스로 하는 것을 소홀히 해서는 안 되겠지만, 사실 책 한 권보다는 훨씬 낫다. 사수의 지식을 전수받는 대신 그들에게 무엇을 해 줄 수 있을까? 최소한 그들의 시간이 낭비가 되지 않도록 열심히 공부해 줄 수는 있을 것이다.

상사에게 공식 연수를 받게 해 달라고 요청해 보라. 하지만 이것이 그 시간 동안 배우고 싶은 새로운 기술을 가지고 놀아 보는 것보다 별로 나을 것이 없는 경우도 있다는 것을 알아 두라. 그렇다 해도, 우리의 불완전한 세상에서는 공식 연수에서 저녁 식사 파티를 기다리며 강의 내내 잠만 자는 경우가 많음에도 불구하고 노는 시간보다는 연수를 요청하기가 쉬울 것이다.

팀장이라면, 팀원들이 어떻게 배우는지 이해하고 그들에게 관심 있는 기능을 연습할 수 있는 적절한 규모의 프로젝트를 할당함으로써 그들을 도와주라. 프로그래머에게 가장 중요한 기능은 기술에 관한 것이 아니라는 사실을 잊지 말라. 팀원들에게 용기와 정직성과 의사소통 능력을 시험하고 실행할 수 있는 기회를 주라.

3.1.7 타자 연습 

자판을 보지 않고 타자할 수 있도록 연습하라. 이것은 중급 기능이다. 왜냐하면, 코드 작성은 어려운 일이므로, 아무리 타자를 잘 한다 해도, 거기에는 타자 속도가 별 의미가 없고, 코드 작성에 걸리는 시간에 별 영향을 주지도 않기 때문이다. 하지만, 중급 프로그래머가 되면 동료나 다른 사람들에게 일반 언어로 글을 쓰는 데 많은 시간을 보내게 될 것이다. 이것은 자신의 헌신성에 대한 재미있는 시험이다. 그런 것을 배우는 일이 그렇게 즐겁지는 않지만 어쨌든 시간을 바쳐야 한다. 마이클 티먼(Michael Tiemann)이 MCC에 있을 때 사람들이 그의 방문 밖에 서서, 엄청나게 빠른 타자 속도 때문에 자판이 윙윙거리는 소리를 듣곤 했다는 전설이 있다. 주: 지금 현재 그는 레드햇(RedHat)의 최고 기술 책임자(CTO)이다.

3.1.8 통합 검사를 하는 방법 

통합 검사(integration testing)는 단위별 검사를 마친 여러 구성요소들을 통합하는 검사이다. 통합은 비싼 대가를 치르고 얻게 되며, 그것은 이 검사를 통과함으로써 얻게 된다. 시간 추정과 일정 계획에 이 검사를 포함시켜야 한다.

이상적으로는 마지막 단계에서 별도로 통합을 실시하지 않아도 되도록 프로젝트를 조직해야 할 것이다. 프로젝트가 진행되는 과정에서 각 요소들이 완성되어 가면서 점진적으로 그것들을 통합하는 것이 훨씬 낫다. 별도의 통합 과정을 피할 수 없다면 주의해서 시간을 추정하라.

3.1.9 의사소통을 위한 용어들 

프로그래밍 언어는 아니지만 의사소통을 위해 공식적으로 정의된 문법 체계에 따른 용어들이 있다. 이 용어들은 특별히 표준화를 통해 의사소통을 돕기 위해 만들어진 것이다. 2003년 현재, 이런 용어들 중 가장 중요한 것으로 UML, XML, SQL이 있다. 이것 모두에 대해서는, 제대로 의사소통하고 언제 그 용어를 사용할지 결정할 수 있기 위해, 어느 정도 친숙해질 필요가 있다.

UML은 설계에 대해 설명하는 도형을 그리기 위해 풍부하게 갖춰진 형식 체계이다. 시각적이고 형식적이라는 점에서 일종의 미학(beauty lines)이라고 할 수 있다. 저자와 독자가 모두 UML을 안다면 많은 양의 정보를 쉽게 전달할 수 있다. 설계 내용에 대해 의사소통할 때 UML을 사용하는 경우가 있으므로 그것을 알 필요가 있다. UML 도형을 전문적으로 그려 주는 유용한 도구들이 있다. 많은 경우에 UML는 너무 형식적이어서, 나는 설계 내용을 도형으로 나타내기 위해 단순한 상자와 화살표 형식을 사용하곤 한다. 하지만 나도 UML이 최소한 라틴어를 공부하는 것만큼 도움이 된다는 사실은 어느 정도 확신한다.

XML은 새로운 표준을 정의하기 위한 표준이다. 간혹 XML이 데이터의 상호교환 문제에 대한 해결책인 것처럼 소개되기도 하지만 사실 그런 것은 아니다. 그것보다는, 데이터의 상호교환에서 가장 따분한 부분, 즉 특정 방식으로 표현된 데이터를 선형의 구조로 나열하고, 그것을 다시 원래의 구조로 파싱하는 작업을 기특하게도 자동화하는 것이다. XML은, 비록 아직 필요한 것들의 일부만 구현되긴 했어도, 훌륭하게 자료형 검사와 정확성 검사를 한다.

SQL은, 완전한 프로그래밍 언어는 아니지만, 매우 강력하고 풍부한 데이터 질의와 처리 언어이다. 이것은 다양한 종류가 있으며, 특히 제품에 크게 의존하지만 표준화된 핵심 부분보다는 덜 중요하다. SQL은 관계형 데이터베이스의 공통 언어이다. 관계형 데이터베이스를 이해하는 것이 득이 되는 분야에서 일할 수도 있고 그렇지 않을 수도 있지만, SQL과 그 문법에 대해 기초적인 것은 알아둘 필요가 있다.

3.2 팀의 기능들 

3.2.1 개발 시간을 관리하는 방법 

개발 시간을 관리하기 위해서는, 프로젝트 계획서가 간결하고 신선(up-to-date)하도록 하라. 프로젝트 계획서에는 시간 추정, 작업 일정, 진척 상황을 표시하기 위한 진도표(milestones), 시간 추정된 각 과제에 대한 팀이나 자기 자신의 시간 할당 등이 들어 있다. 여기에는 품질보증팀 사람들과 회의, 문서 준비, 장비 주문과 같이 잊지 말고 해야 할 다른 일들도 포함된다. 팀으로 일하는 것이라면, 프로젝트 계획서는 프로젝트 시작부터 진행 과정 내내 팀 전체의 동의에 의한 것이어야 한다.

프로젝트 계획서는 의사결정을 돕기 위해 존재하는 것이지, 자신이 얼마나 조직적인 사람인지 보여 주기 위한 것이 아니다. 프로젝트 계획서가 너무 길고 오래되었다면 의사결정에 아무 소용이 없을 것이다. 실제로 이러한 의사결정은 개개인에 관한 것이다. 계획서와 판단력에 의해 과제를 이 사람에게서 저 사람에게로 넘길 것인지 결정해야 한다. 진도표는 진척 상황을 표시한다. 화려한 프로젝트 기획 도구를 사용한다면 그것으로 프로젝트에서 '개발 초기 대형 설계(Big Design Up Front)'를 하려는 유혹에 빠지지 말고, 간결함과 신선함을 위해 사용하도록 하라.

진도를 못 맞췄다면, 그 진도만큼 프로젝트 일정 완료가 늦어진다고 상사에게 알리는 등의 즉각적인 행동을 취해야 한다. 시간 추정과 작업 일정은 처음부터 완벽할 수는 없을 것이다. 이것은 진도를 못 맞춘 날들을 프로젝트 후반에 만회할 수 있을지도 모른다는 환상을 낳는다. 물론 그럴 수 있을지도 모른다. 하지만 이것은 그 부분을, 과대 추정할 수도 있었겠지만, 과소 추정했기 때문이다. 그러므로 좋듯 싫든 간에 프로젝트의 일정 완료는 이미 늦어진 것이다.

계획서에 다음의 시간들도 포함되도록 명심하라. 팀 내부 회의, 시연, 문서화, 일정에 따라 반복되는 활동들, 통합 검사, 외부인들 상대하기, 질병, 휴가, 기존 제품들의 유지, 개발 환경의 유지 등. 프로젝트 계획서는 외부인이나 상사에게 자신이나 자신의 팀이 무엇을 하고 있는지 보여 줄 수 있는 '중간' 다리가 될 수 있다. 이런 이유 때문에 계획서는 짧고 신선해야 한다.

3.2.2 타사 소프트웨어의 위험 부담을 관리하는 방법 

프로젝트 내에서 통제할 수 없는 다른 조직이 만든 소프트웨어에 의존해야 하는 경우가 있다. 타사 소프트웨어와 연관된 큰 위험 부담들은 관련된 모든 사람이 인식하고 있어야 한다.

절대, 절대로 거품(vapor)에 희망을 두지 말라. 거품이란, 나올 것이라고 광고는 하면서 아직 나오지 않은 소프트웨어를 말한다. 이것은 업계를 떠나게 될 가장 확실한 방법이다. 어떤 특징이 있는 어떤 제품이 어느 날에 출시될 것이라는 소프트웨어 회사의 약속을 의심스러워하기만 하는 것은 현명하지 않다. 그것을 완전히 무시하고 그 소식을 들었다는 것조차 잊어버리는 것이 더욱 현명하다. 회사에서 쓰이는 어떤 문서에도 그 소프트웨어에 대해 쓰지 않도록 하라.

타사 소프트웨어가 거품이 아니라면, 위험 부담은 여전히 있지만 그래도 최소한 손을 써 볼 수는 있을 것이다. 타사 소프트웨어의 사용을 고려하고 있다면, 일찍 에너지를 들여서 그것을 평가해야 한다. 사람들은 세 가지 제품이 적합한지 평가하는 데에 2주에서 2개월이 걸린다는 말을 듣고 싶어 하지 않겠지만, 최대한 일찍 그 일을 마쳐야 한다. 적절한 평가 없이는 통합(integration)에 드는 비용을 정확하게 추정할 수 없다.

특정한 목적에 기존의 타사 소프트웨어가 적합한지는 극소수의 사람들만 알고 있다. 그것은 매우 주관적이며 일반적으로 전문가들의 영역이다. 이런 전문가들을 찾을 수 있다면 많은 시간을 아낄 수 있다. 프로젝트가 타사 소프트웨어 시스템에 너무 완전히 의존해서 통합에 실패하면 프로젝트 자체가 실패하는 경우도 있을 수 있다. 그러한 위험 부담들을 작업 일정에 분명히 밝혀 두라. 쓸 수 있는 다른 시스템을 확보하는 등 만약의 사태에 대비한 계획도 세워 두고, 위험 부담을 일찍 제거할 수 없을 때 스스로 그 기능을 구현할 수 있는 능력도 키워 두라. 절대로 일정이 거품에 의존하지 않도록 하라.

3.2.3 컨설턴트를 관리하는 방법 

컨설턴트를 활용하되 그들에게 의지하지는 말라. 그들은 훌륭하고 많이 존중받을 만하다. 그들은 수많은 다양한 프로젝트들을 보아 왔기 때문에 특정한 기술들이나 프로그래밍 기법들에 대해 많이 알고 있는 경우가 있다. 그들을 활용하는 최선의 방법은, 사례를 중심으로 강의하는 사내 강사로서 활용하는 것이다.

하지만, 그들의 강점과 약점을 알 만한 충분한 시간이 없다고 해서 그들을 일반 직원들처럼 팀의 일원이 되게 할 수는 없다. 그들이 금전적 손실을 감수하는(financial commitment) 경우는 거의 없다. 그들은 아주 쉽게 떠난다. 회사가 잘 운영된다면 그들이 얻을 것은 별로 없을 것이다. 어떤 사람은 좋고, 어떤 사람은 그저 그렇고, 어떤 사람은 안 좋을 것이다. 컨설턴트를 선정할 때도 직원을 채용할 때처럼 주의를 기울이지 않는다면 좋은 사람을 만나기는 힘들 것이다.

컨설턴트가 코드를 작성해야 한다면, 계속해서 그 코드를 주의를 기울여 검토해야 한다. 검토해 보지 않은 코드가 뭉텅이로 있는 위험 부담을 안고서 프로젝트를 잘 마칠 수는 없을 것이다. 이것은 사실 모든 팀원들에게도 적용되는 사실이지만, 가까이에 있는 팀원들이야 잘 아는 사람들 아닌가.

3.2.4 딱 적당하게 회의하는 방법 

회의에 드는 비용을 잘 고려하라. 그 비용은 회의 시간에 참석 인원수를 곱한 값이다. 회의가 필요할 때도 있지만 규모가 작을수록 좋다. 의사소통의 질은 소규모 회의 때 더 좋고, 낭비되는 총 시간도 적다. 누가 회의 때 지루해하는 것 같으면, 이것은 회의 참석 인원을 줄여야 한다는 신호이다.

비공식적인 의사소통을 장려하기 위해서는 할 수 있는 일은 모두 해야 한다. 다른 시간들보다 동료들과 함께 하는 점심시간 동안 쓸만한 일들이 더 많이 이뤄진다. 그런데 이것을 인식하지도 않고 이 사실을 지지하지도 않는 회사가 더 많다는 것은 부끄러운 일이다.

3.2.5 무리 없이 정직하게 반대 의견을 내는 방법 

반대 의견은 의사 결정을 잘 하기 위해 꼭 필요한 것이지만, 조심스럽게 다뤄야 한다. 자기 생각을 적절히 표현했고 결정이 내려지기 전에 사람들이 그 생각에 귀를 기울였다고 스스로 느낀다면 좋겠다. 그 경우 더 이상 할 말은 없는 것이고, 이제는 결정된 일에 대해 반대했더라도 그것을 후원할 것인지 결정하면 된다. 반대했더라도 이제 그 결정을 따를 수 있다면 그렇게 하겠다고 말하라. 이것은 내가 생각이 있으며 무조건 찬성하는 사람이 아니지만, 결정된 것은 존중하며 팀의 일원으로 일한다는 자신의 가치를 보여 준다.

어떤 때는 결정 사안에 대해 반대했음에도, 의사결정권자들이 그 의견을 충분히 고려하지도 않고 결정을 내리기도 할 것이다. 이 때에는 문제 제기를 할 것인지 회사나 부족(tribe)의 차원에서 잘 따져 봐야 한다. 그 결정에 사소한 실수가 있는 것 같다면, 재고할 가치는 없을 것이다. 만약 그 실수가 크다면, 당연히 논쟁을 벌여야 한다.

보통은, 이것은 별 문제가 되지 않지만, 스트레스가 많은 상황이나 특별한 성격의 사람들에게는 이것이 개인적인 문제를 일으키기도 한다. 예를 들어, 일 잘 하는 어떤 프로그래머는 결정이 잘못되었다고 믿을 만한 충분한 이유가 있어도 그것에 도전할 자신감이 없다. 더 나쁜 상황이라면, 의사결정권자도 자신감이 없어서 그것을 자기 권위에 대한 개인적인 도전으로 받아들이기도 한다. 이런 경우에 사람들은 비열하게 머리를 써서 반응한다는 것을 꼭 기억할 필요가 있다. 논쟁은 남들이 없을 때 벌여야 하고, 새로운 사실을 알게 됨으로써 전에 내린 결정의 근거가 어떻게 달라지는지 잘 보여주도록 노력해야 한다.

그 결정이 번복되든 그렇지 않든, 그 대안은 충분히 검토되지 않았을 것이므로 나중에라도 '내 그럴 줄 알았어!' 하고 우쭐대지 않도록 하라.

3.3 판단 능력 

3.3.1 개발 시간에 맞춰 품질을 조절하는 방법 

소프트웨어 개발은 항상 프로젝트의 목적과 프로젝트의 마무리 사이에서 타협하는 일이다. 프로젝트 결과의 배치를 신속하게 하기 위해 공학적 혹은 사업적 감수성을 거스르면서까지 품질을 조절하라는 요구를 받을 수 있다. 예를 들어, 소프트웨어 공학적으로 형편없고 수많은 유지 보수 문제를 일으킬 것이 뻔한 일을 하도록 요구받을 수 있다.

이런 일이 일어난다면 우선 책임 있게 할 일은, 그 사실을 팀에 알리고 품질 저하에 따른 비용을 분명히 설명하는 것이다. 어쨌든, 상사보다는 그 사실에 대해 더 잘 이해하고 있어야 한다. 무엇을 잃을 것이고 무엇을 얻을 것인지, 또 이번에 잃은 것을 다음 단계에 만회하기 위해서는 어떤 비용을 감수해야 하는지 분명히 하라. 이 때, 잘 짜여진 프로젝트 계획서의 선명함이 도움이 될 것이다. 품질을 조절하는 것이 품질 보증의 노력에 영향을 준다면 (상사와 품질보증팀 사람들 모두에게) 그 사실도 지적하라. 품질 조절 때문에 품질 확인 과정을 거치면서 많은 버그가 발견될 것 같다면 그것도 지적하라.

그래도 요구가 계속된다면, 조잡해지는 것이 특정 부분에만 머물게 하여 다음 단계에 재작성이나 개선 계획을 세울 수 있도록 해야 한다. 이 사실을 팀에 알려서 그 계획을 세울 수 있게 하라.

슬래쉬닷(Slashdot)의 닌자프로그래머(NinjaProgrammer)는 이런 보석 같은 글을 보내 왔다.

설계가 좋으면 코드 구현이 나빠도 회복 가능성이 있다는 사실을 기억하라. 코드 전체에 인터페이스와 추상화가 잘 되어 있으면, 언젠가 있을 수 있는 코드 재작성의 고통도 훨씬 덜할 것이다. 코드를 명쾌하게 작성하기도 힘들고 고치기도 힘들다면, 이런 문제를 야기하는 핵심 설계에 무슨 문제가 없는지 생각해 보라. 

3.3.2 소프트웨어 시스템의 의존성을 관리하는 방법 

최신의 소프트웨어 시스템은 직접 통제할 수 없는 수많은 구성요소(component)들에 의존하는 경향이 있다. 이것은 상승효과(synergy)와 재사용을 통해 생산성을 높인다. 하지만, 각 요소들은 다음의 문제들을 수반한다.
  • 그 구성요소에 있는 버그는 어떻게 고칠 것인가?
  • 그 구성요소 때문에 특정 하드웨어나 소프트웨어 시스템만 사용해야 하는가?
  • 그 구성요소가 기능을 완전히 상실한다면 어떻게 할 것인가? 

그 구성요소를 어떻게든 캡슐화 하여 주변과 격리시키고 언제든 다른 것으로 교체할 수 있게 하는 것이 항상 최선이다. 그 요소가 전혀 동작하지 않는 것으로 판명된다면 다른 것으로 대체할 수도 있지만, 직접 작성해야 할 수도 있다. 캡슐화가 이식성(portability)과 같은 말은 아니지만, 쉽게 이식될 수 있게 하기 때문에 거의 그와 같다고 할 수 있다.

구성요소들의 소스 코드를 갖고 있다면 위험 부담이 네 배 정도는 줄어든다. 소스 코드가 있다면 그것을 평가하기도 쉽고, 디버그 하기도 쉽고, 임시방편을 찾기도 쉽고, 수정판을 만들기도 쉽다. 수정판을 만든다면, 그것을 그 구성요소의 소유자에게도 보내 줘서 공식 배포판에 반영하게 해야 한다. 그렇지 않으면 비공식판을 유지하는 불편을 감수해야 할 것이다.

3.3.3 소프트웨어의 완성도를 판단하는 방법 

다른 사람들이 작성한 소프트웨어를 사용하는 것은 견고한 시스템을 신속하게 완성하는 가장 효과적인 방법 중 하나이다. 그런 일을 망설일 필요는 없지만, 그에 연관된 위험 요소들을 검사해야 한다. 가장 큰 위험 부담 중 하나는 사용할 제품에 포함되어 사용되는 동안, 완성도를 갖추기 전의 소프트웨어에서 흔히 볼 수 있는 것처럼, 버그가 나타나거나 거의 작동 불능인 상태가 되는 것이다. 어떤 소프트웨어 시스템을 통합할 것인지 고려하기 전에, 그것이 사내에서 만들었든 타사에서 만들었든, 그것이 정말로 사용할 수 있을 만큼 충분한 완성도를 갖췄는지 고려하는 것은 매우 중요하다. 스스로 물어봐야 하는 열 가지 질문이 있다.
  1. 거품(vapor)은 아닌가? (약속만 있는 것은 완성도가 아주 떨어지는 것이다.)
  2. 그 소프트웨어에 대한 평판(lore)이 어떤지 알 수 있는가?
  3. 내가 첫 사용자인가?
  4. 개정판이 계속 나올 만한 충분한 동기(incentive)가 있는가?
  5. 유지 보수 노력이 계속되고 있는가?
  6. 현재 유지 보수 담당자가 없어도 사장되지 않을 것인가?
  7. 절반밖에 안 좋더라도 익숙한 다른 대안(seasoned alternatives)이 있는가?
  8. 부족(tribe)이나 회사에서 그것에 대해 알고 있는가?
  9. 부족이나 회사에서 추천할 만한가?
  10. 문제가 있어도 그것을 해결할 만한 사람을 채용할 수 있는가? 

이 항목들을 조금만 생각해 봐도 잘 만들어진 자유 소프트웨어나 공개 소프트웨어가 기업의 위험 부담을 줄이는 데에 얼마나 큰 가치가 있는지 알 수 있을 것이다.

3.3.4 구입과 개발 사이에서 결정하는 방법 

사업을 목적으로 한 회사나 프로젝트에서는 소프트웨어로 무엇인가를 달성하기 위해 노력하면서 빈번히 구입과 개발 사이에서 결정을 해야 한다. 이 단계에 왔다는 것은 두 가지 측면에서 불행한 일이다. 즉, 구입하지 않아도 되는 공개 소프트웨어, 자유 소프트웨어를 제쳐놓았기 때문일 것이고, 더 중요한 것은, 통합에 드는 비용도 고려해야 하기 때문에, 구입해서 통합하는 것과 직접 개발해서 통합하는 것 사이에서 결정하는 것을 의미하게 될 것이기 때문이다. 이것은 영업과 경영과 공학적 이해를 전체적으로 결합할 필요가 있다.
  • 자신의 필요와 그 소프트웨어가 설계된 목적이 얼마나 잘 맞는가?
  • 구입한 것 중 얼마만큼이 필요할 것인가?
  • 통합의 가치를 검토하는 데 드는 비용은 얼마나 되는가?
  • 통합하는 데 드는 비용은 얼마나 되는가?
  • 구입하게 되면 장기적 유지 보수 비용은 증가할 것인가, 감소할 것인가?
  • 그것을 구입함으로써 사업상 원치 않는 처지에 있게 되지는 않을 것인가? 

다른 사업 전체의 기반이 될 만큼 큰 과제를 직접 개발하는 일은 다시 한 번 생각해 봐야 한다. 그런 생각은 대개 팀에 공헌을 많이 하게 될 똑똑하고 낙관적인 사람들이 제안하기 마련이다. 그들의 생각을 꼭 채택하고 싶다면, 사업 계획을 수정할 각오도 해야 할 것이다. 그러나 뚜렷한 생각 없이 원래 프로젝트보다 더 큰 솔루션(solution) 개발에 투자하는 일은 하지 말라.

이 질문들을 고려한 후에 개발에 대한 것과 구입에 대한 것, 이렇게 두 가지 프로젝트 시안을 준비해야 할 것이다. 통합 비용도 반드시 고려해야 할 것이다. 두 솔루션 모두에 대해 장기적 유지 보수 비용도 고려해야 한다. 통합 비용을 추정하기 위해서는 그 소프트웨어를 구입하기 전에 철저하게 평가해야 할 것이다. 그것을 평가할 수 없다면, 그것을 구입함으로써 생기는 예상 밖의 위험 부담까지 가정하여 그 제품을 구입하는 것에 대해 결정해야 한다. 고려할 구입 결정 대상이 여럿이라면, 각각을 평가하기 위해 상당한 노력을 들여야 할 것이다.

3.3.5 전문가로 성장하는 방법 

자신의 권위보다 책임을 더 중하게 생각하라. 바라는 역할에 최선을 다하라. 자신을 개인적으로 도와준 사람들은 물론 조직 전체의 성공에 기여한 사람들에게 감사하라.

팀장이 되고 싶다면, 팀의 합의를 이루기 위해 애쓰라. 관리책임자가 되고 싶다면, 작업 일정에 책임을 지라. 팀장이나 관리책임자 대신 이 일을 맡는다면, 그들이 자유롭게 더 큰 일에 전념할 수 있을 것이므로, 그 일을 편하게 해 낼 수 있을 것이다. 그 일이 시험 삼아 해 보기에 너무 크다면, 한 번에 조금씩 하도록 하라.

자기 자신을 평가하라. 더 나은 프로그래머가 되고 싶다면, 존경하는 사람에게 어떻게 하면 그들과 같이 될 수 있는지 물어보라. 상사에게 물어볼 수도 있다. 그가 아는 것은 적어도 나의 경력에는 큰 영향을 미칠 것이다.

자기 일에 활용할 수 있는 새로운 기능을 배울 방법을 계획하라. 이것은, 새로운 소프트웨어 시스템에 대해 배우는 것과 같이 사소한 기술적 기능일 수도 있고, 글을 잘 쓰는 것과 같이 어려운 사회적 기능일 수도 있다.

3.3.6 면접 대상자를 평가하는 방법 

사원이 될 사람들을 평가하는 일은, 그 가치에 비해 큰 노력을 들이지 않고 있다. 잘못된 채용은, 잘못된 결혼과 마찬가지로, 끔찍한 일이다. 모든 사람들은 자기 에너지의 상당 부분을 인재 발굴에 바쳐야 하지만, 실제로 그런 경우는 드물다.

다양한 면접 유형이 있다. 어떤 것은 고문과 같아서, 지원자가 심한 스트레스를 받게 되어 있다. 이것은 스트레스를 받는 상황에서 인격적인 결점과 약점이 드러날 수 있게 하는 매우 중요한 목적이 있다. 지원자들은 자기 자신에 대해 정직한 만큼 면접관에게 정직할 것이다. 그런데 인간의 자기기만(self-deception) 능력은 대단하다.

최소한 두 시간 동안은 지원자에게 기술적 기능에 대해 묻는 구두시험을 실시해야 한다. 여러 번 하다 보면, 그들이 아는 것이 무엇인지 즉시 파악하고, 경계를 명확히 하기 위해 그들이 모르는 것에 대해 즉시 반응할 수 있게 될 것이다. 면접 대상자들은 이것을 순순히 받아들일 것이다. 나는 면접 대상자들에게서 회사를 선택하는 동기 중 하나가 면접의 질적 수준이라는 말을 몇 번 들은 적이 있다. 좋은 사람들은, 전에 일하던 곳이 어디인지, 어느 학교를 나왔는지, 그 밖의 다른 사소한 특성들보다는 자기 실력 때문에 채용되기를 원한다.

면접을 하면서 그들의 학습 능력에 대해서도 평가해야 한다. 이것은 그들이 현재 알고 있는 것이 무엇인가보다 더욱 더 중요하다. 까다로운 사람이라는 낌새도 알아차려야 한다. 면접 후에 기록해 둔 것들을 비교하면서 이런 것을 알아차릴 수 있을 것이다. 하지만 한참 면접이 진행되는 동안에 그것을 알아차리기는 어렵다. 다른 사람과 의사소통하고 같이 일하는 것을 얼마나 잘 하는가는 최신 프로그래밍 언어에 능통한 것보다 중요하다.

한 독자는 면접 대상자들에게 집에서 풀어오는 시험을 실시하여 결과가 좋았다고 한다. 이 방법은 면접 때 말은 잘 하지만 정작 코딩은 못 하는 사람들을 추려낼 수 있다는 장점이 있다. (사실 그런 사람들이 많다.) 개인적으로 이 기법을 써 보지는 않았지만, 괜찮아 보인다.

끝으로, 면접은 판매의 과정이기도 하다. 지원자들에게 회사나 프로젝트를 잘 팔아야 한다. 하지만, 프로그래머에게 이야기하는 것이므로, 진실을 윤색하려고 하지는 말라. 나쁜 점에서 시작하여 좋은 점에 대해 강한 인상을 주면서 마무리 하라.

3.3.7 화려한 전산 과학을 적용할 때를 아는 방법 

많은 프로그래머들이 알기는 하지만 거의 사용하지 않는 알고리듬, 자료 구조, 수학, 그 밖의 거창한 내용에 대한 지식들이 있다. 실제로 이런 훌륭한 지식들은 너무 복잡하여 일반적으로는 필요가 없다. 예를 들어, 대부분의 시간을 비효율적인 데이터베이스 질의를 만들고 있으면서 알고리듬을 개선한다는 것은 아무 의미가 없다. 프로그래밍을 하면서 시스템들이 서로 통신하게 한다거나 멋있는 사용자 환경(user interface)을 만들기 위해 매우 단순한 자료 구조를 사용해야 한다면 불행이 시작되는 것이다.

고급 기술을 사용하는 것이 적절한 때는 언제인가? 흔하지 않은 다른 알고리듬을 찾기 위해 책을 펼쳐야 하는 때는 언제인가? 그런 것을 사용하는 것이 유용할 경우가 있지만, 그 전에 주의해서 평가해야 한다.

사용하게 될지 모르는 전산 과학 기법에 대해 고려해야 하는 매우 중요한 세 가지 측면이 있다.
  • 캡슐화가 잘 되어 있어서, 다른 시스템에 미칠 위험 부담이 적고, 복잡도나 유지 보수 비용의 증가가 적은가?
  • 그 이득이 대단한가? (예를 들어, 기존의 것과 유사한 시스템이라면 두 배, 새로운 시스템이라면 열 배 정도의 이득)
  • 그것을 효과적으로 검사하고 평가할 수 있을 것인가? 

다소 화려해도 주변과 격리가 잘 되어 있는 알고리듬은 전체 시스템에 대해 두 배 정도로 하드웨어 비용을 줄이거나 그 만큼 성능을 향상시킬 수 있을 것이므로 그것을 고려하지 않는 것은 어리석은 일이 될 것이다. 이런 해결 방법을 주장하기 위한 한 가지 열쇠는, 그 기술에 대한 연구는 이미 잘 되어 있을 것이고 남은 문제는 통합의 위험 부담일 것이므로, 그 위험 부담이 실제로 매우 적다는 것을 보여 주는 것이다. 이렇게 될 때 프로그래머의 경험과 판단 능력이 그 화려한 기술과 어울려 진정한 상승효과를 낼 수 있을 것이며 통합도 쉽게 이뤄질 것이다.

3.3.8 비기술자들과 이야기하는 방법 

대중문화에서 기술자, 특히 프로그래머는 일반적으로 보통 사람들과는 다른 사람이라고 인식된다. 이것은 보통 사람들이 우리와 다르다는 뜻이다. 비기술자들과 대화할 때 이 사실을 염두에 두고 있는 것이 중요하다. 항상 듣는 사람을 이해해야 한다.

비기술자들은 똑똑하더라도 우리처럼 기술적인 것들을 만드는 일에 기초가 있지는 않다. 우리는 무엇인가를 만든다. 그들은 무엇인가를 팔거나 다루거나 세거나 관리하지만, 만드는 일에는 전문가가 아니다. 그들은 기술자들처럼 (물론 예외는 있지만) 팀으로 같이 일하는 것에도 익숙하지 않다. 주: 많은 독자들이 이 절의 내용이 오만하거나 자기 경험과는 거리가 멀다고 느낄 수 있다. 나는 비기술자도 매우 존중한다. 겸손한 척하려고 하는 말이 아니다. 나의 이런 신념들로 기분이 상했다면 용서를 구한다. 하지만 솔직하게 말해서 반대 사례를 경험하게 될 때까지는 그 신념을 거둘 수 없을 것 같다. 내가 이례적으로 운이 좋아서 그 동안 좋은 프로그래머들과 같이 일해 왔을 수도 있고, 다른 사람들이 프로그래머는 대화하기 부담스럽다는 고정관념(stereotype)을 일반적인 표준으로 생각하는 것일 수도 있다. 그들의 사회적 기능은 일반적으로, 팀이 아닌 환경에서 일하는 기술자들과 같거나 더 낫지만, 그들이 하는 일은 우리처럼 깊고 정확하게 의사소통을 해야 하거나 세부 과제를 조심스럽게 나눠야 하는 등의 일이 항상 요구되지는 않는다.

비기술자들은 간절히 다른 사람을 만족시키고 싶어 할 수도 있고, 기술자들에게 위협을 느낄 수도 있다. 우리와 똑같이, 그들도 기술자들을 만족시키기 위해서, 혹은 기술자들에게 다소 겁을 먹어서, 별 뜻 없이 '예'라고 말해 놓고는 나중에는 그 말에 책임지지 않을 수 있다.

비프로그래머들이 기술적인 것들을 이해할 수는 있지만 우리에게도 어려운 그것, 즉 기술적 판단 능력은 없다. 그들은 기술이 어떻게 적용되는지는 이해하지만, 왜 어떤 접근 방식은 석 달이나 걸리고, 다른 방식은 사흘이면 되는지 이해하지 못한다. (어쨌든, 프로그래머들이 이런 종류의 추정에 너무 냉정하다는 것도 맞는 말이다.) 이것은 그들과 함께 상승효과를 낼 수 있는 기회가 있다는 뜻도 된다.

팀에서 이야기할 때에는, 별 생각 없이, 일종의 줄임말을 사용할 것이다. 일반 기술이나 특히 함께 작업하는 제품에 대해 많은 경험을 공유하고 있기 때문에 그것이 효과적이다. 그런 경험의 공유가 없는 사람들에게 이야기할 때, 특별히 자기 팀원들도 같이 있다면, 줄임말을 사용하지 않는 데에 노력을 좀 들여야 한다. 이런 어휘는 우리와 그것을 공유하지 않는 사람들 사이에 벽을 만들고, 더 나쁘게는, 그들의 시간을 낭비하게 한다.

팀원들과 있을 때는 기본 가정이나 목표를 수시로 다시 말할 필요는 없으며, 대부분의 대화가 세부적인 것들에 초점이 맞춰진다. 외부인들과 함께 있을 때는 다른 방식으로 해야 한다. 그들은 우리가 당연하게 여기는 것을 이해하지 못할 수 있다. 어떤 것을 당연하게 여기고 다시 설명하지 않기 때문에, 실제로는 커다란 오해가 있는데도 서로를 잘 이해했다고 생각하면서 외부인들과 대화를 마칠 수도 있다. 자기 생각을 잘못 전달할 수 있다는 것을 항상 가정하고 실제로 그런 일이 없는지 잘 살펴봐야 한다. 그들이 잘 이해했는지 알아보기 위해, 요약을 하게 하거나 다른 말로 표현하게 해 보라. 그들을 자주 만날 기회가 있다면, 내가 효과적으로 대화하고 있는지, 어떻게 하면 더 잘 할 수 있을지 잠깐 물어보는 것도 좋다. 의사소통에 문제가 있다면, 그들에게 실망하기 전에 자신의 습관을 고칠 방법을 찾으라.

나는 비기술자들과 같이 일하는 것을 좋아한다. 가르치고 배울 기회가 많기 때문이다. 명확한 용어로 대화하면서, 예를 들어 가며 안내할 수도 있을 것이다. 기술자들은 무질서에서 질서를, 혼동됨에서 명확함을 찾아내도록 훈련받으며, 비기술자들은 우리의 이런 점을 좋아한다. 우리는 기술적 판단 능력이 있고 사업상의 문제들도 대개 이해할 수 있기 때문에, 종종 문제에 대한 간단명료한 해결책을 찾아내기도 한다.

비기술자들은 좋은 뜻으로, 그리고 잘 해 보려는 마음으로 우리가 일을 더 쉽게 해 낼 수 있을 것이라고 생각하는 해결책들을 제안하기도 한다. 사실은 훨씬 더 좋은 종합적 해결책이 존재하는데, 그것은 외부인들의 관점과 우리의 기술적 판단력이 함께 상승효과를 낼 때에만 보인다. 나는 개인적으로 익스트림 프로그래밍(Extreme Programming)을 좋아한다. 그것이 이런 비효율성을 중점적으로 다루고 있으며, 아이디어와 그에 대한 비용 추정을 신속하게 짝지음으로써, 비용과 이득이 최상으로 결합되는 아이디어를 쉽게 찾을 수 있게 해 주기 때문이다.

4 상급자 

4.1 기술적 판단 능력 

4.1.1 어려운 것과 불가능한 것을 구분하는 방법 

어려운 일은 해 내고, 불가능한 일은 골라내는 것이 우리가 할 일이다. 대부분의 현직 프로그래머들의 관점에서 보면, 단순한 시스템에서 나올 수 없거나 비용을 추정할 수 없는 일은 불가능한 것이다. 이 정의에 따르면 연구라고 불리는 것은 모두 불가능한 일이다. 일거리들의 많은 부분이 어렵기는 하지만, 반드시 불가능한 것은 아니다.

이 구분은 전혀 우스운 것이 아니다. 과학적 관점에서든 소프트웨어 공학적 관점에서든, 실제로 불가능한 일을 하라는 요구를 받는 경우가 많을 것이기 때문이다. 어렵기는 해도 사업주가 원하는 것을 최대한 끌어낼 수 있는 합리적인 해결책을 찾도록 돕는 것이 우리가 할 일이다. 자신 있게 일정을 잡을 수 있고 위험 부담을 잘 이해하고 있다면, 그 해결책은 어려운 것일 뿐이다.

예를 들어, '각 사람에게 가장 매력적인 머리 모양과 색깔을 계산할 수 있는 시스템을 개발하라'와 같은 막연한 요구 사항을 만족시키는 것은 불가능한 일이다. 요구 사항이 좀 더 뚜렷해질 수 있다면, 그 일이 어려울 뿐인 일로 바뀌기도 한다. 예를 들어 다음과 같은 식이다. '어떤 사람에게 매력적인 머리 모양과 색깔을 계산할 수 있는 시스템을 개발하되, 그들이 그것을 미리 보고 수정할 수 있게 하여, 처음 제안한 스타일에 대한 고객 만족을 극대화함으로써 많은 수입을 얻을 수 있게 하라.' 성공에 대한 뚜렷한 정의가 없다면 성공할 수 없을 것이다.

4.1.2 내장 언어를 활용하는 방법 

시스템에 프로그래밍 언어를 내장하는(embedding) 것은 프로그래머에게는 에로틱하다고 할 만한 황홀함을 느끼게 한다. 이것은 해 볼 수 있는 가장 창의적인 활동들 중 하나이다. 이것은 시스템을 굉장히 강력하게 만들어 준다. 이것을 통해 자신의 창의적이고 프로메테우스적인 능력을 최대한 발휘할 수 있다. 이것은 시스템을 친구로 만들어 준다.

세계적으로 가장 우수한 텍스트 편집기들은 모두 내장 언어를 갖추고 있다. 사용자가 그 언어에 완전히 통달하는 경지에까지 이를 수도 있다. 물론, 그것이 텍스트 편집기 안에 들어 있으므로, 써 보고 싶은 사람들은 쓸 수 있고 그렇지 않은 사람들은 그럴 필요 없도록, 그 언어의 사용을 선택 사항으로 둘 수도 있다.

나를 비롯하여 다른 많은 프로그래머들이 특수한 목적의 내장 언어를 만들고 싶다는 유혹에 빠지곤 한다. 나는 두 번 그런 적이 있다. 내장 언어로 특별히 설계된 언어들이 이미 많이 나와 있다. 새로운 것을 또 만들기 전에 한 번 더 생각해 볼 필요가 있다.

언어를 내장하기 전에 스스로 물어봐야 하는 진짜 질문은 이것이다. 이것이 사용자의 문화와 잘 맞을 것인가, 그렇지 않을 것인가? 사용자가 모두 비프로그래머라면 그것이 무슨 도움이 될 것인가? 사용자가 모두 프로그래머라면 오히려 API를 선호하지 않을 것인가? 무슨 언어로 할 것인가? 프로그래머들은 사용 범위가 좁은 새 언어는 배우고 싶어 하지 않는다. 하지만 그것이 그들의 문화와 잘 맞물린다면 많은 시간을 들이지 않고서도 배울 수 있을 것이다. 새로운 언어를 만든다는 것은 즐거운 일이다. 하지만 그렇다고 해서 사용자들의 필요에 대해 눈이 가려져서는 안 된다. 정말로 근본적인 필요와 아이디어가 있는 것이 아니라면, 사용자들이 이미 친숙한 기존의 언어를 사용해서 부담을 줄여 주는 것이 어떤가?

4.1.3 언어의 선택 

자신의 일을 사랑하는 고독한 프로그래머(즉, 해커)는 과제에 가장 잘 맞는 언어를 선택할 수 있다. 대부분의 현직 프로그래머들은 자기가 사용할 언어를 마음대로 고를 수 있는 경우가 드물다. 일반적으로, 이 문제는 잘난 체하는(pointy-haired) 상사들이 마음대로 결정한다. 이들은 기술적으로 결정하기보다는 정략적으로 결정하고, 아직 일반화되지 않은 어떤 도구가 가장 좋다는 것을 (대개 실무 경험에 의해) 알면서도 재래식이 아닌 도구를 사용하자고 나설 만한 용기는 없다. 어떤 경우에는 팀 전체, 더 넓게는 공동체 전체의 통일이 매우 실제적인 이득이 있기 때문에 개인적인 입장에서 선택하는 것을 배제하기도 한다. 관리책임자들은 정해진 언어에 대한 경험이 있는 프로그래머들을 채용해야 하는 필요에 따라 움직이기도 한다. 그들이 프로젝트나 회사에 가장 큰 이익이 된다고 생각하는 것을 위해 일한다는 것은 분명하며, 그것에 대해 존중받을 만하다. 하지만 나는 개인적으로 이것이 흔히 마주치게 되는 가장 낭비적이고 잘못된 일이라고 생각한다.

물론, 모든 일이 1차원적인 경우는 없다. 한 가지 중심 언어가 필수로 정해지고 그것을 내가 어떻게 할 수 없다 해도, 도구나 다른 프로그램을 다른 언어로 작성할 수 있거나 그렇게 해야 하는 경우가 종종 있다. 언어를 내장해야 한다면 (이것은 항상 생각해야 한다!) 언어를 선택할 때 사용자들의 문화를 많이 고려해야 할 것이다. 회사나 프로젝트에 기여하기 위해 그 일에 가장 적합한 언어를 사용하는 것의 장점을 잘 활용해야 하며, 이것을 통해 일이 더욱 흥미로워질 것이다.

프로그래밍 언어는, 그것을 배우는 것이 자연 언어를 배우는 것만큼 어려운 일이 전혀 아니라는 점에서, 표기법들(notations)이라고 부르는 것이 실제에 가깝다. 초보자들이나 외부인들에게는 "새로운 언어 배우기"가 멈칫하게 될 과제로 보인다. 하지만 세 가지 정도 언어를 체험해 보면, 그 일은 주어진 라이브러리들에 익숙해지는 문제일 뿐이다. 구성요소들이 서너 가지 언어로 되어 있는 큰 시스템이 있을 때 그것을 지저분하게 뒤범벅이 되어 있다고 생각할 수 있지만, 나는 그런 시스템이 한 가지 언어만으로 되어 있는 시스템보다 여러 면에서 더 튼튼한 경우가 많다고 하겠다.
  • 서로 다른 표기법으로 작성된 구성요소들은 필연적으로 결합도(coupling)가 낮아진다. (깔끔한 인터페이스는 없겠지만)
  • 각 요소들을 개별적으로 재작성함으로써 새로운 언어/플랫폼으로 발전시키기 쉽다.
  • 실제로는 어떤 모듈들이 최신의 것으로 갱신되었기 때문일 수도 있다. 

심리적인 효과일 뿐인 것도 있지만, 심리적인 것도 중요하다. 결국 언어에 대한 독재는 그것이 주는 유익보다 거기에 드는 비용이 더 크다.

4.2 현명하게 타협하기 

4.2.1 작업 일정의 압박과 싸우는 방법 

출시 시간(time-to-market)의 압박은 좋은 제품을 신속하게 내놓기 위한 압박이다. 이것은 재정적 현실을 반영하는 것이기 때문에 나쁠 것도 없고, 어떤 점에서는 건전한 것이다. 작업 일정의 압박은 내놓을 수 있는 시간보다 더 빨리 내놓기 위한 압박이며, 이것은 낭비적이고 건전하지도 않지만, 너무도 흔하다.

작업 일정의 압박은 몇 가지 이유로 존재한다. 프로그래머들에게 과제를 맡기는 사람들은 우리가 얼마나 강한 직업윤리를 갖고 있으며 프로그래머가 된다는 것이 얼마나 재미있는 일인지 충분히 인식하지 못한다. 아마도 그들은 자신의 행동 방식을 우리에게 그대로 비춰 보기 때문에, 더 빨리 하라고 요구하면 더 열심히 일하게 될 것이라고 믿는다. 이것은 어쩌면 실제로 사실일 수도 있지만, 그 효과는 매우 작으며 손해는 매우 크다. 게다가 그들은 소프트웨어를 만들기 위해 실제로 무엇이 필요한지 볼 수 있는 눈이 없다. 볼 수도 없고 스스로 만들 수도 없기 때문에, 그들이 할 수 있는 단 한 가지는 출시 시간의 압박을 보면서 프로그래머들에게 그것에 대해 떠들어대는 일이다.

작업 일정의 압박과 싸우는 열쇠는 그것을 출시 시간의 압박으로 바꿔 놓는 것이다. 이렇게 하는 방법은 가용 인력과 제품 사이의 관계를 잘 볼 수 있게 하는 것이다. 개입된 모든 인력에 대해 정직하고 상세하고 무엇보다도 이해할 만한 추정치를 내놓는 것이 이것을 위한 가장 좋은 방법이다. 이것은 직무의 조정 가능성에 대한 관리상의 의사결정을 잘 할 수 있게 해 준다는 추가적인 장점이 있다.

이런 추정을 통해 명백해지는 중요한 통찰은, 인력이 비압축성 유체(incompressible fluid)와 같다는 것이다. 그릇의 부피보다 더 많이 물을 눌러넣을 수 없듯이, 일정 시간 안에 더 많은 것을 우겨넣을 수 없다. 어떤 점에서 프로그래머는 '못 합니다.'라고 하기보다는, '원하는 그 일을 위해 무엇을 포기하겠습니까?'라고 해야 할 것이다. 추정을 명확하게 함으로써 프로그래머가 더욱 존중받게 되는 효과가 있을 것이다. 다른 직종의 전문가들은 바로 이렇게 행동한다. 이로써 프로그래머들의 고된 일이 눈에 보이게 될 것이다. 비현실적인 작업 일정을 잡았다는 사실도 고통스럽겠지만 모든 사람에게 분명히 드러날 것이다. 프로그래머들은 함부로 현혹할 수 있는 사람들이 아니다. 그들에게 비현실적인 것을 요구하는 일은 예의 없고 비도덕적인 일이다. 익스트림 프로그래밍(Extreme Programming)은 이것을 상세히 설명하고 있으며 그 과정을 확립해 놓고 있다. 나는 모든 독자들이 이 기법을 활용할 수 있을 만큼 운이 좋기를 바란다.

4.2.2 사용자를 이해하는 방법 

우리에게는 사용자를 이해하고, 또한 상사가 그 사용자를 이해할 수 있게 도와 줄 의무가 있다. 사용자는 우리처럼 제품 생산에 깊이 개입되어 있지 않기 때문에 다음과 같이 조금 특이하게 행동한다.
  • 사용자는 일반적으로 짧게 말하고 끝낸다.
  • 사용자는 자기 일이 따로 있다. 그들은 대개 제품이 크게도 아니고 약간 개선되었으면 좋겠다고 생각한다.
  • 사용자는 그 제품 사용자들 전체를 볼 수 있는 눈이 없다. 

우리는 그들이 원한다고 말한 것이 아니라, 정말로 그들이 원하는 것을 제공할 의무가 있다. 그래서 일에 착수하기 전에 이쪽에서 먼저 제안을 하고, 그것이 정말로 그들이 원하는 것이라는 동의를 얻는 것이 더 나을 수 있다. 하지만 그들은 이렇게 하는 것이 바람직하다는 것을 모를 수도 있다. 그것을 위한 자신의 아이디어에 대한 자신감의 정도는 경우에 따라 달라져야 한다. 고객이 정말로 무엇을 원하는지 아는 것에 대해, 자만심과 거짓 겸손, 둘 다 경계해야 한다. 프로그래머들은 설계하고 만들어내도록 훈련된다. 시장 연구자들은 사람들이 무엇을 원하는지 알아내도록 훈련된다. 이 두 종류의 사람들, 아니 한 사람 안에 있는 두 가지 사고방식은 함께 조화를 이룰 때 정확하게 통찰할 수 있는 최상의 조건이 된다.

사용자들과 시간을 많이 보낼수록 무엇이 실제로 성공적일지 더 잘 이해하게 될 수 있을 것이다. 가능한 한 많이 자신의 생각을 사용자들의 생각과 비교하여 검사해 봐야 한다. 할 수 있다면 그들과 함께 먹고 마시기도 해 봐야 한다.

가이 카와사키(Guy Kawasaki)는 사용자들의 말을 듣는 것에 더하여 그들이 무엇을 하는지 관찰하는 것의 중요성을 강조한 바 있다. <Rules>

내가 알기로, 의뢰인들이 진정으로 원하는 것이 무엇인지 그들 자신의 마음에 분명해지게 하는 일에 계약직 프로그래머나 컨설턴트들이 엄청난 어려움을 겪는 경우가 종종 있다. 컨설턴트가 될 생각이 있는 사람은 의뢰인을 선택할 때 그들의 수표책뿐만 아니라 그들의 머리 속이 얼마나 명료한지도 확인하라고 권하고 싶다.

4.2.3 진급하는 방법 

어떤 역할로 진급하고 싶다면, 그 역할을 먼저 실행하라.

어떤 직위로 진급하고 싶다면, 그 직위에 기대되는 것이 무엇인지 파악하여 그것을 행하라.

임금 인상을 원한다면, 정확한 정보로 무장하고 협상하라.

진급을 할 때가 지났다고 느껴지면, 상사에게 그것에 대해 이야기하라. 진급을 하기 위해 무엇을 해야 하는지 숨기지 말고 그들에게 질문하라. 진부한 이야기로 들리겠지만, 스스로 무엇이 필요하다고 인식하는 것과 상사가 인식하는 것이 상당히 다른 경우가 종종 있다. 또한 이것은 어떤 식으로든 상사에게 그 일을 확실히 못 박아 두는 것도 된다.

대부분의 프로그래머들이 자신의 상대적 능력에 대해 어떤 면에서는 과장되게 생각하는 것 같다. 하지만, 우리가 모두 상위 10%가 될 수는 없는 노릇이다! 그러나, 심각하게 진가를 인정받지 못하는 사람들도 많이 봐 왔다. 모든 사람의 평가가 항상 정확하게 실체와 일치할 것이라고 기대할 수는 없지만, 한 가지 단서가 있다면 사람들은 일반적으로 적당히 공정할 것이라고 생각한다. 자신의 일을 드러내 보여주지 않는다면 제대로 평가받을 수도 없다. 때로는 우연한 실수나 개인적인 버릇 때문에, 충분히 주목받지 못하기도 한다. 집에서 주로 일하거나 팀이나 상사와 지리적으로 떨어져 있는 것 때문에 이것이 특히 어려워지기도 한다.

4.3 팀을 위해 일하기 

4.3.1 재능을 개발하는 방법 

니체(Nietzsche)는 이렇게 과시하며 말했다. <Stronger>

나를 파괴하지 않는 것은 나를 강하게 하는 것이다. 


우리가 가장 많이 책임져야 할 대상은 우리 팀이다. 팀원들을 모두 잘 알아야 한다. 팀에게 도전적으로 요구하더라도, 지나치게 무거운 짐을 지워서는 안 된다. 그들이 긴장을 유지하는 방법에 대해 그들과 이야기해 봐야 할 것이다. 그들이 그것을 기꺼이 받아들인다면(buy in), 더욱 동기가 높아질 것이다. 모든 프로젝트, 또는 하나 건너 하나의 프로젝트마다 그들이 제안한 방법과 그들에게 좋을 것 같다고 생각되는 방법으로 긴장을 유지하게 해 줘야 한다. 그들에게 일을 더 많이 맡기는 것보다는, 새로운 기능을 알려주거나 더 좋게는 팀에서 능력을 발휘할 새로운 역할을 부여하여 긴장을 유지하게 하라.

다른 사람들은 물론 자기 자신도 간혹 일이 안 풀릴 수 있다는 것을 인정해야 하며, 일정대로 일이 진행되지 않을 경우를 대비한 계획을 세워 놓아야 한다. 항상 일이 잘 된다면, 모험은 아무 의미가 없을 것이다. 일이 안 풀리는 경우가 없다는 것은, 위험 부담 없이 편하게만 일을 하고 있다는 뜻이다. 누군가 일이 잘 안 됐다면, 그들이 성공한 것처럼 대우할 필요는 없겠지만, 최대한 부드럽게 대해야 한다.

모든 팀원들이 기꺼이 받아들이고 동기를 높일 수 있도록 노력하라. 팀원 각자에게 그들이 동기가 높지 않을 때 어떻게 해 주면 좋은지 터놓고 물어 보라. 그들을 불만족스러운 채로 내버려둬야 할 경우도 있지만, 각자가 바라는 것이 무엇인지는 알고 있어야 한다.

낮은 의욕이나 불만족 때문에 자기 몫의 짐을 일부러 지지 않는 사람을 무시해 버리거나 되는 대로 내버려 둘 수는 없다. 그들의 동기와 생산성을 높이도록 노력해야 한다. 참을 수 있는 한 계속 노력하라. 인내의 한계를 넘어섰다면 그들을 해고하라. 일부러 자기 능력 이하로 일하는 사람들을 팀에 계속 있게 할 수는 없다. 그렇게 하는 것은 팀에 공정한 일이 아니다.

능력 있는 팀원들에게는 그들이 능력 있다고 생각한다는 사실을 공개적으로 이야기함으로써 그 사실을 확인시켜 주라. 칭찬은 공개적으로, 비판은 사적으로 해야 한다.

능력 있는 팀원들은 자연적으로 능력이 모자라는 팀원들보다 더 어려운 과제를 맡는다. 이것은 아주 자연스러운 일이며, 모두가 다 열심히 일하는 한 아무도 이것 때문에 귀찮아하지 않을 것이다.

좋은 프로그래머 한 사람이 안 좋은 프로그래머 열 사람보다 생산성이 높은데도 그것이 봉급에 반영되지 않는 것은 이상한 일이다. 이것 때문에 미묘한 상황이 생긴다. 능력이 모자란 프로그래머가 길을 비켜 주면 일을 더 빨리 진행할 수 있는 경우가 사실 종종 있다. 그렇게 하면 실제로 단기간에는 더 많은 성과를 낼 수도 있다. 하지만, 부족(tribe) 전체로서는 여러 중요한 이득을 잃게 된다. 능력이 모자라는 팀원의 훈련, 팀 내 지식의 확산, 능력 있는 팀원이 없을 때 대신할 능력 등이 그것이다. 능력 있는 사람들은 이 점에 관해서는 너그러울 필요가 있고 그 문제를 다각도로 고려해야 한다.

능력 있는 팀원에게는 도전할 만하면서 범위가 잘 정의된 과제를 맡겨 보는 것도 좋다.

4.3.2 일할 과제를 선택하는 방법 

프로젝트의 어느 부분을 맡아 할 것인지 선택할 때에는 자신의 개인적 필요와 팀 전체의 필요 사이에서 균형을 잡아야 한다. 물론 가장 잘 하는 일을 선택해야겠지만, 일을 더 많이 하는 것보다는 새로운 기능을 발휘할 수 있는 것을 통해 스스로 긴장을 유지할 수 있는 길을 찾아보도록 하라. 지도력과 의사소통 기능은 기술적 기능보다 더 중요하다. 자신의 능력이 뛰어나다면, 더 어렵고 위험부담이 큰 과제를 맡고, 위험부담을 줄이기 위해 프로젝트에서 그 일을 최대한 빨리 처리하라.

4.3.3 팀 동료들이 최대한 능력을 발휘하게 하는 방법 

팀 동료들이 최대한 능력을 발휘하게 하기 위해서는, 단체정신을 키우고 팀원 모두가 개별적으로 도전을 느끼고 개별적으로 일에 몰두하도록 격려하라.

단체정신을 키우기 위해서는, 로고가 새겨진 옷이나 파티처럼 다소 진부한 것도 좋지만, 개인적으로 존중하는 것만큼 좋지는 않다. 모두가 모두를 존중하면 아무도 다른 사람을 깎아내리고 싶지 않을 것이다. 단체정신은 사람들이 팀을 위해 희생하고 자신의 이익보다 팀의 이익을 먼저 생각할 때 만들어진다. 팀장으로서 이 점에 대해 솔선해서 한 것 이상으로 다른 사람에게 요구할 수는 없을 것이다.

팀에 대한 지도력의 한 가지 열쇠는 모든 사람이 기꺼이 받아들일 수 있는 합의를 이뤄내는 것이다. 이것은 팀 동료들이 잘못된 일을 하는 것을 인정한다는 말이기도 하다. 즉, 그것이 프로젝트에 너무 큰 피해를 주지만 않는다면, 비록 나는 그렇게 하는 것이 잘못된 것이라는 분명한 확신이 있다 해도, 팀원 중 누가 자기 방식대로 일하는 것을, 합의에 따라 그렇게 하게 두어야 한다. 이런 일이 생길 때는, 찬성하지 말고 공개적으로 반대하되, 합의된 것은 받아들이라. 마음이 상했다거나 어쩔 수 없이 그렇게 한다는 식으로 말하지 말고, 그것에 반대하지만 팀의 합의를 더 중요하게 생각한다고 꾸밈없이 말하라. 이렇게 할 때 그들이 돌이키기도 한다. 그들이 돌이켰다면 그들에게 원래 계획대로 밀고 나가라고 고집하지는 말라.

그 문제에 대해 적절한 모든 관점에서 논의한 후에도 동의하지 않는 사람이 있다면, 이제 결정을 내려야 하며 이것이 나의 결정이라고 꾸밈없이 단언하라. 자신의 결정이 잘못되었는지 판단할 방법이 있거나 나중에 잘못된 것으로 밝혀진다면 할 수 있는 대로 빨리 돌이키고 옳았던 사람을 인정하라.

단체정신을 키우고 팀을 효과적으로 만들기 위해 어떻게 하는 것이 좋을지 팀 전체와 팀원 각자에게 물어보라.

자주 칭찬하되 분별없이 하지는 말라. 특별히 나와 의견이 다른 사람도 칭찬할 만할 때에는 바로 칭찬하라. 공개적으로 칭찬하고 사적으로 비판하라. 한 가지 예외는 있다. 과실을 바로잡아 가치가 증대된 것(growth)을 공개적으로 칭찬할 때에는 원래의 과실이 눈길을 끄는 난처한 상황이 될 수도 있으므로, 가치 증대에 대해서는 사적으로 칭찬하는 것이 좋다.

4.3.4 문제를 나누는 방법 

소프트웨어 프로젝트를 맡아서 각 사람이 수행할 과제들로 나누는 것은 재미있는 일이다. 이것은 초반에 해야 한다. 관리책임자들이 그 일을 수행할 각 사람들에 대해 고려하지 않아도 시간을 추정할 수 있다고 생각하는 경우가 있는 것 같다. 이것은 불가능한 일이다. 각자의 생산성은 아주 크게 차이가 나기 때문이다. 어떤 구성요소(component)에 대한 특정 지식이 있는 사람도 계속 변화해 가므로, 수행 능력에서 여러 배의 차이가 날 수도 있다.

지휘자가 연주할 악기의 음색을 고려하고 운동 경기 코치가 각 선수의 능력을 고려하는 것처럼, 경험 많은 팀장이라면 프로젝트를 과제들로 나누는 일을, 그 과제가 할당될 팀원들과 분리해서 생각하지는 않을 것이다. 이것은 수행 능력이 뛰어난 팀이 해체되어서는 안 되는 이유이기도 하다.

여기에도 위험이 다소 따르는데, 사람들이 능력을 쌓아가는 과정에서 따분해져서 약점을 개선하거나 새로운 기능을 배우려고 하지 않는 경우가 그것이다. 하지만, 전문화는 남용되지만 않는다면 생산성 향상에 매우 유용한 도구가 된다.

4.3.5 따분한 과제를 다루는 방법 

간혹 회사나 프로젝트의 성공에 결정적이기 때문에 과제가 따분해도 피할 수 없는 경우가 있다. 이런 과제들은 그것을 해야 하는 사람들의 사기를 실제로 떨어뜨릴 수 있다. 이것을 다루는 가장 좋은 기법은 래리 월(Larry Wall)이 말한 '프로그래머의 게으름의 미덕(virtue of Laziness)'을 불러일으키고 북돋아 주는 것이다. 자신이나 동료 대신 컴퓨터가 그 과제를 처리하게 하는 방법이 없는지 찾아보라. 수작업으로 한 주에 할 과제를 해결할 프로그램을 짜는 데 한 주가 걸린다 해도 이것이 더욱 교육적이고 필요하면 반복해서 쓸 수도 있으므로 더 큰 이득이 있는 것이다.

모든 방법이 수포로 돌아간다면, 따분한 일을 해야 하는 사람들에게 양해를 구해야겠지만 어떤 경우에도 그들이 혼자 하게 내버려 두지는 말라. 최소한 두 사람으로 팀을 짜서 그 일을 맡기고 그 일을 완수하기 위해 성실히 협력할 수 있도록 격려하라.

4.3.6 프로젝트를 위한 지원을 얻는 방법 

프로젝트를 위한 지원을 얻기 위해서는, 조직 전체가 추구할 실제적인 가치를 잘 드러내는 이상(vision)을 만들고 알려야 한다. 이상을 만드는 일에 다른 사람들도 동참하도록 노력하라. 이것을 통해 그들에게는 우리를 지원할 이유가 생기며 우리에게는 그들의 아이디어를 얻는 혜택이 생긴다. 프로젝트를 위한 핵심적인 지원 인사들을 개별적으로 모집하라. 갈 수 있는 곳이면 어디든 가서, 말만 하지 말고 보여주라. 할 수 있다면, 자신의 아이디어를 시연할 수 있는 시제품(prototype)이나 실물모형(mockup)을 만들라. 시제품은 어느 분야에서든 효력이 있지만 소프트웨어 분야에서는 글로 쓴 어떤 설명보다 훨씬 더 우세하다.

4.3.7 시스템이 자라게 하는 방법 

나무의 씨앗에는 어른 나무의 밑그림(idea)이 들어있지만 아직 그 형태나 능력이 완전히 발현되지는 않았다. 싹이 자라고 커진다. 점점 어른 나무를 닮아 가며 점점 더 쓸모 있게 되어 간다. 마침내 열매를 맺고, 그 후에는 죽어서 다른 생물을 위한 거름이 된다.

과장된 표현일 수도 있지만 소프트웨어도 그렇게 취급된다. 다리(bridge)는 그렇지 않다. 미완성 다리는 있어도 '아기 다리'는 없다. 다리는 소프트웨어에 비해 아주 단순하다.

소프트웨어가 자란다고 생각하는 것이 좋다. 그렇게 생각하면 머리 속에 완벽한 그림이 그려지기 전에도 훌륭히 전진해 갈 수 있기 때문이다. 사용자들의 반응을 듣고 소프트웨어의 성장을 바로잡아 줄 수 있다. 약한 가지를 쳐 주는 것도 건강에 좋다.

프로그래머는 전달받아 사용할 수 있는 완성된 시스템을 설계해야 한다. 그런데 고급 프로그래머는 그 이상을 할 수 있어야 한다. 완성된 시스템으로 귀결되는 성장 경로를 설계할 수 있어야 한다. 아이디어의 싹을 가지고 가능한 한 평탄한 경로를 따라 유용한 완성품이 만들어질 수 있게 하는 것이 우리가 할 일이다.

이를 위해서는, 최종 결과를 시각화하고 그것에 대해 기술팀이 흥미를 가질 수 있도록 전달해야 한다. 또한 현재 그들의 위치에서 그들이 원하는 위치까지 가는 경로를 비약 없이 잘 전달해야 한다. 나무는 그 기간 내내 살아 있어야 한다. 어느 순간에 죽었다가 나중에 부활할 수는 없다.

이런 접근 방법은 나선형 개발(spiral development)에 그대로 반영되어 있다. 그 경로에 따라 진도를 표시하기 위해 간격이 너무 멀지 않은 진도표(milestones)를 사용한다. 사업이라는 무한 경쟁의 환경에서는, 비록 잘 설계된 최종 목표와는 거리가 멀다 해도 진도별 배포판(milestone release)을 계속 내면서 최대한 빨리 돈을 버는 것이 상책이다. 프로그래머의 임무 중 하나는, 일정표에 명시되는 성장 경로를 현명하게 선택함으로써 즉각적인 이득과 미래의 이득 사이에 균형을 잡는 일이다.

고급 프로그래머는 소프트웨어와 팀과 개개인의 성장에 대한 3중의 책임이 있다.

독자인 롭 하퍼닉(Rob Hafernik)이 이 절에 대해 다음의 의견을 보내 왔는데, 전문을 인용하는 것이 가장 좋을 것 같다.

여기에서는 그 중요성이 덜 강조된 것 같습니다. 이것은 시스템만의 문제가 아니며, 알고리듬, 사용자 환경(user interface), 데이터 모형(data model) 등의 문제이기도 합니다. 이것은 대형 시스템의 작업을 할 때 중간 목표들을 향해 진도를 맞춰 가기 위해서는 정말로 대단히 중요합니다. 끝까지 다 가서야 전체가 전혀 작동하지 않는다는 사실을 알게 되는 공포 상황만큼 나쁜 것은 없을 것입니다. (보우터 뉴스 서비스(Voter News Service)가 최근 해체된 것을 보십시오. 역자 주: 보우터 뉴스 서비스는 미국 언론사들이 출구 조사를 위해 공동 설립한 기관으로, 2002년 11월 미국 중간 선거를 대비하여 1,000만 달러 이상을 투자하여 시스템을 새롭게 갖추었으나, 선거 당일에 총체적인 문제가 생겨 출구 조사 결과 발표를 포기하고 말았다. 이 기관은 2003년 1월 해체되었다.) 한 걸음 더 나아가 이것은 자연 법칙이라고까지 말하고 싶습니다. 대형의 복잡한 시스템은 무에서 시작하여 구현할 수 없습니다. 의도한 단계를 거쳐 가면서 단순한 시스템에서 복잡한 시스템으로 진화하는 것만 가능합니다. 


이 인용글에 대해서는 "빛이 있으라(Fiat lux)!" 하고 응답할 수밖에 없을 것이다.

4.3.8 대화를 잘 하는 방법 

대화를 잘 하기 위해서는 우선 그것이 얼마나 어려운 것인지 인식해야 한다. 이것은 기능 자체에 대한 기능이다. 대화할 대상자들이 결점이 있는 사람들이라는 사실 때문에 이 일은 더욱 어려운 일이 된다. 그들은 나를 이해하는 일에 별로 노력을 들이지 않는다. 그들은 말도 잘 못 하고 글도 잘 못 쓴다. 그들은 대개 과로하고 있거나 따분해하고 있으며, 지금 말하고자 하는 큰 문제들보다는 자기 자신의 일에만 초점을 맞추고 있는 것 같다. 개설되어 있는 강좌를 통해 글쓰기, 연설, 듣기 기능을 연습하면, 이것들을 잘 하게 될 때 문제가 어디에 있는지, 그것을 어떻게 고칠 수 있는지 더 쉽게 볼 수 있다는 장점이 있다.

프로그래머는 자기 팀과 대화하는 일에 생존이 달려 있는 사회적 동물이다. 고급 프로그래머는 팀 밖의 사람들과 대화하는 일에 만족이 달려 있는 사회적 동물이다.

프로그래머는 무질서에서 질서를 끌어낸다. 이것을 하는 한 가지 흥미로운 방법은 팀 밖에서 어떤 제안을 시작하게 하는 것이다. 이것은 뼈대(strawman)나 백지 형식으로, 혹은 단지 구두로 시작될 수 있다. 이렇게 이끌어 가는 것은 토론의 조건을 설정한다는 점에서 굉장히 큰 장점이 있다. 이를 통해 나 자신이 비판, 더 나쁘게는 거부와 무시에 내놓인다. 고급 프로그래머는 고유한 권한과 그에 따른 고유한 책임이 있으므로, 이것을 받아들일 각오를 해야 한다. 프로그래머가 아닌 사업가들은 여러 가지 점에서 지도력을 발휘하기 위해 프로그래머가 필요하다. 프로그래머들은 현실에 기초하여 아이디어와 현실을 이어주는 다리의 한 부분이다.

나도 대화를 잘 하는 일에 정통하지는 않지만, 현재 노력하고 있는 것은 네 갈래의 접근 방식이다. 이것은, 아이디어를 정돈하고 충분히 준비를 갖춘 다음, 구두로 이야기를 하고, 사람들에게 백지를 (실제 종이로든, 전자적으로든) 나눠주고, 시연을 하고, 인내심을 가지고 이 과정을 반복하는 것이다. 이런 어려운 대화 과정에서 충분히 인내심을 갖지 않는 때가 많다고 생각한다. 자기 아이디어가 즉각 받아들여지지 않는다고 해서 낙담해서는 안 된다. 그것을 준비하는 데에 노력을 들였다면, 그것 때문에 나를 하찮게 생각하는 사람은 없을 것이다.

4.3.9 사람들에게 듣고 싶어 하지 않는 말을 하는 방법 

사람들에게 그들을 불편하게 할 말을 해야 할 때가 있다. 이 일은 어떤 이유가 있기 때문에 하는 것이라는 사실을 기억하라. 그 문제에 대해 아무 것도 할 수 없다 해도, 그들에게 할 수 있는 한 빨리 말해서 그들이 그 사실을 숙지하고 있게 해야 한다.

누군가에게 문제점에 대해 말하는 가장 좋은 방법은 해결책을 동시에 제시하는 것이다. 두 번째로 좋은 방법은 그 문제점에 대해 도움을 요청하는 것이다. 그 사람이 믿지 않을 위험이 있다면, 그 말을 지지해 줄 사람을 모아 봐야 할 것이다.

해야 하는 가장 불쾌하면서 일상적인 말들 중 하나는 ‘예정일을 넘길 것 같군요.’라고 말하는 것이다. 양심적인 프로그래머라면 이런 말을 하기가 싫을 테지만, 그래도 최대한 빨리 해야 한다. 진도 날짜를 지나쳤을 때, 할 수 있는 것이 모든 사람들에게 그 사실을 알리는 일밖에 없다 해도, 대응이 지연되는 것보다 안 좋은 일은 없다. 이런 일을 할 때에는, 물리적으로 같이 하지는 못하더라도, 정신적으로라도 팀으로 같이 하는 것이 더 좋다. 지금의 위치와 그것을 해결하기 위한 일에 대해 팀원들의 의견이 필요할 것이며, 팀원들도 그 결과를 함께 직시해야 할 것이다.

4.3.10 관리상의 신화들을 다루는 방법 

신화라는 단어는 허구를 뜻하기도 한다. 하지만 좀 더 깊은 함축이 있다. 이것은 우주에 대해, 그리고 인류와 우주의 관계에 대해 설명하는 종교적으로 중요한 이야기를 뜻하기도 한다. 관리책임자들은 프로그래머로서 배운 것은 잊어버리고, 어떤 신화들을 믿곤 한다. 그 신화들이 거짓이라고 그들에게 설득하려고 하는 것은, 독실한 종교인에게 그들의 믿음에 대한 환상을 깨뜨리려고 하는 것처럼 귀에 거슬리고 성공 가능성이 없는 일이다. 그렇기 때문에 이런 신념들을 신화라고 인식해야 한다.
  • 문서는 많이 만들수록 좋다. (그들은 문서를 원하지만, 그들은 문서를 작성하는 데 시간을 쓰는 것을 원하지 않는다.)
  • 프로그래머들은 다 같다. (프로그래머들도 천차만별로 다르다.)
  • 지연되는 프로젝트에 새로운 자원을 투입해서 진척 속도를 높일 수 있다. (새로 들어온 사람들과 대화하는 데 드는 비용은 거의 항상 도움이 되기보다는 부담이 된다.)
  • 소프트웨어 개발 시간을 확실히 추정하는 것이 가능하다. (이론적으로도 불가능하다.)
  • 프로그래머의 생산성은 코드의 줄 수와 같은 간단한 척도로 측정될 수 있다. (간결한 것을 중시한다면 코드의 줄 수가 늘어나는 것은 좋은 것이 아니라 나쁜 것이다.) 

기회가 된다면 이러한 것들을 설명해 볼 수는 있을 것이다. 하지만 실패하더라고 기분나빠 하지 말고, 이런 신화들에 호전적으로 맞서다가 자신의 평판이 나빠지게 하지도 말라. 이러한 신화들 때문에 관리책임자들은 현재 진행되는 프로젝트에 대해서 실제로 통제력을 가지고 있다는 생각을 더욱 굳힌다. 결국 관리책임자가 좋은 사람이라면 도움이 될 것이고, 안 좋은 사람이라면 방해가 될 것이라는 것이 진리이다.

4.3.11 조직의 일시적 혼돈 상태를 다루는 방법 

조직이 짧은 시기 동안 큰 혼돈을 겪는 때가 종종 있다. 예를 들어, 근신(layoff), 기업 인수(buyout), 회사 공개(IPO, Initial Public Offering), 해고, 신규 채용 등이 그것이다. 이것은 모든 사람의 마음을 어지럽게 하지만, 자기의 지위가 아닌 능력에 근거하여 개인적 자부심을 가지고 있는 프로그래머는 어지러움이 조금 덜할 것이다. 조직의 혼돈은 프로그래머들이 자신의 마법의 능력을 시험해 볼 수 있는 좋은 기회이다. 나는 이 이야기를 끝까지 아껴 두었다. 이것은 우리 부족(tribe)의 은밀한 비밀이기 때문이다. 프로그래머가 아닌 사람은 이제 그만 읽기를 바란다.

기술자들은 만들고 유지하는 능력이 있다. 


전형적인 소프트웨어 회사의 경우, 비기술자들이 주변 사람들에게 지시할 수는 있지만, 기술자 없이는 아무것도 만들거나 유지할 수 없다. 이는 기술자가 일반적으로 제품을 팔거나 사업을 효과적으로 운영할 수 없는 것과 같다. 기술자들의 이 능력은 일시적인 조직의 혼란(mayhem)에 관한 거의 모든 문제들에 대해 버틸 수 있는 힘이 된다. 이런 능력을 가졌다면 이 혼돈을 완전히 무시하고 마치 아무것도 일어나지 않은 것처럼 행동하면 된다. 물론 자신이 해고되는 경우도 있겠지만 이 마법의 능력 때문에 곧 새로운 직장을 찾게 될 것이다. 더욱 흔하게는, 마법의 능력도 없이 스트레스를 받고 있는 사람이 내 자리에 와서 어떤 어리석은 일을 하라고 할 수도 있다. 그 일이 정말로 어리석다고 확신한다면 그 사람 앞에서 그냥 웃으면서 고개를 끄덕이고 회사를 위해서 가장 좋다고 생각되는 다른 일을 하는게 최선이다.

만약 팀장이라면, 팀원들에게도 같은 식으로 하라고 말해 주고, 다른 누가 무슨 말을 해도 무시하라고 말해 주라. 이런 행동 방식이 나 개인에게도 최선이고, 회사와 프로젝트에도 최선이다.

5 참고 문헌 

5.1 책 

<Rules00> Guy Kawasaki, Michelle Moreno, and Gary Kawasaki. 2000. HarperBusiness. Rules for Revolutionaries: The Capitalist Manifesto for Creating and Marketing New Products and Services.

<RDev96> Steve McConnell. 1996. Microsoft Press. Redmond, Wash. Rapid Development: Taming Wild Software Schedules.

<CodeC93> Steve McConnell. 1993. Microsoft Press. Redmond, Wash. Code Complete.

<XP99> Kent Beck. 1999. 0201616416. Addison-Wesley. Extreme Programming Explained: Embrace Change.

<PlanXP00> Kent Beck and Martin Fowler. 2000. 0201710919. Addison-Wesley. Planning Extreme Programming.

<Prag99> Andrew Hunt, David Thomas, and Ward Cunningham. 1999. 020161622X. Addison-Wesley. The Pragmatic Programmer: From Journeyman to Master.

<Stronger> Friedrich Nietzsche. 1889. Twilight of the Idols, "Maxims and Arrows", section 8.

5.2 웹 사이트 

<PGSite> Paul Graham. 2002. 그의 사이트에 있는 논설(article)들: http://www.paulgraham.com/articles.html 모두 읽을 만하지만, 특히 "Beating the Averages".

<Hacker> Eric S. Raymond. 2003. How to Become a Hacker. http://www.catb.org/~esr/faqs/hacker-howto.html.

<HackDict> Eric S. Raymond. 2003. The New Hacker Dictionary. http://catb.org/esr/jargon/jargon.html

<ExpCS> Edsger W. Dijkstra. 1986. How Experimental is Computing Science?http://www.cs.utexas.edu/users/EWD/ewd09xx/EWD988a.PDF

<Knife> Edsger W. Dijkstra. 1984. On a Cultural Gap.http://www.cs.utexas.edu/users/EWD/ewd09xx/EWD913.PDF

6 역사 (2003년 5월 현재) / History (As Of May, 2003) 

6.1 피드백 및 확장 요청 / Request for Feedback or Extension 

이 에세이에 대한 의견이 있다면 나에게 보내주십시오. 나는 모든 의견을 반영하려고 노력하고 있으며 많은 수의 의견들이 이 에세이를 발전시켰습니다.

이 에세이는 GNU Free Documentation License를 따릅니다. 이 라이센스는 에세이에만 적용되는 것이 아닙니다. 에세이는 보통 한 사람의 하나의 관점에 바탕을 두고 쓰여져서 특정한 주장에 집착하고 그것을 확신시키려는 경향이 있습니다. 나는 이 에세이가 쉽고 즐겁게 읽힐 수 있었으면 합니다.

또한 나는 이것이 교육적이었으면 합니다. 비록 교과서는 아닐지라도 이것은 많은 단락으로 나뉘어 있어서 쉽게 새로운 단락이 추가될 수 있습니다. 너무 한쪽 시각으로 편중되었다고 생각한다면 올바르다고 생각되는 쪽으로 이 에세이에 추가하십시오. 이것은 이 라이센스의 목적이기도 합니다.

이 문서가 확장될 가치가 있다고 생각하는 것이 너무 잘난 척 하는 것 같기도 하지만, 이것이 영원히 진화됐으면 합니다. 이것이 다음과 같은 방식으로 확장된다면 기쁘겠습니다.
  • 쉽게 읽을 수 있는 목록이 각 단락에 추가됨.
  • 더 많은, 더 좋은 단락이 추가됨.
  • 비록 단락 단위로 번역되는 한이 있더라도 다른 언어로 번역됨.
  • 틀린 점이나 보충할 것이 추가됨.
  • 팜(PDA의 한 종류) 문서나 더 나은 HTML 같이 다른 문서 형식으로 변환될 수 있게 됨. 

만약 이러한 일을 나에게 알려 준다면 이 라이센스(GFDL)의 목적에 따라서 다음 버전에 추가하겠습니다. 물론 이 라이센스에 나와 있는 대로, 나에게 알리지 않아도 이 문서에 대한 자기만의 버전을 만들 수 있습니다.

감사합니다.

로버트 L. 리드(Robert L. Read)

6.2 원본 / Original Version 

이 문서의 원본은 로버트 L. 리드(Robert L. Read)에 의해 2000년부터 시작되었고 2002년에 사미즈다트(Samizdat) 출판사에서 최초로 전자 문서로 출판되었다.(http://Samizdat.mines.edu) Hire.com의 프로그래머들에게 이 문서를 바친다.

2003년 슬래쉬닷(Slashdot)에서 이 기사가 언급되었고 약 75명의 사람들이 제안과 수정할 것들을 이메일로 나에게 보내왔다. 그것에 감사한다. 비록 많은 중복이 있지만 다음에 열거된 사람들은 커다란 제안을 했거나 문제점을 고치도록 도움을 준 사람들이다. 모건 맥과이어(Morgan McGuire), 데이빗 메이슨(David Mason), 톰 뫼르텔(Tom Moertel), 슬래쉬닷의 닌자 프로그래머(Ninja Programmer) (145252), 벤 비어크(Ben Vierck), 롭 하퍼닉(Rob Hafernik), 마크 하우(Mark Howe), 피터 파라이트(Pieter Pareit), 브라이언 그레이슨(Brian Grayson), 제드 A. 쇼어(Zed A. Shaw), 스티브 벤즈(Steve Benz), 막심 이오프(Maksim Ioffe), 앤드류 우(Andrew Wu), 데이빗 제쉬키(David Jeschke), 톰 코코런(Tom Corcoran).

마지막으로 크리스티나 밸러리(Christina Vallery)에게 감사를 드린다. 그의 수정과 사려깊은 읽기를 통해서 두번째 원고가 크게 발전했다. 그리고 웨인 알렌(Wayne Allen)에게 이 일을 시작하도록 격려해 준 것에 대해서도 감사 드린다.

6.3 원저자의 경력 / Original Author's Bio 

로버트 L. 리드(Robert L. Read)는 미국 텍사스주 오스틴에서 부인과 두 아이와 함께 살고 있다. 현재 Hire.com에서 4년 동안 총수석 엔지니어로 일하고 있다. 그전에는 제지 산업 분야에서 스캐너로부터 이미지를 읽어 그것의 품질을 조절해주는 도구를 생산하는 4R Technology를 설립하기도 했다.

그는 1995년 텍사스 주립 대학에서 데이터베이스 이론에 관한 연구로 전산 과학 박사 학위를 받았다. 1987년에는 라이스(Rice) 대학에서 전산 과학 학사 학위를 받았다. 그는 16세 때부터 직업 프로그래머로 일하고 있다.


원저자가 보내온 편지
Subject: RE: Your essay translated into Korean!
Date: Wed, 7 Jan 2004 09:28:48 -0600
From: <Read@hire.com>
To: <*******>

	Thank you!  I am thrilled and honored that this would be done.
I hope it benefits some Korean speakers who do not read English well
enough to enjoy the original.
	Unfortunately, I do not speak Korean---yet.  I do plan to study
it before I reach old age, but there are several other languages that 
I would like to master first.
	It is my understand that the Korean writing sysem (Han Gul?) is
a great acheivement of human invention and the Korean people.


-----Original Message-----
From: *******
Sent: Wednesday, January 07, 2004 7:49 AM
To: Rob Read
Subject: Your essay translated into Korean!


Thank you for your insightful essay, "How to be a Programmer."

Finally it's been translated into Korean on a Wiki site. You can read
it, if you can read Korean ;-), on
http://wiki.kldp.org/wiki.php/HowToBeAProgrammer
Posted by 모과이IT
,

김창준 (마이크로소프트웨어) 
2002/06/02       
 
우리 프로그래머들은 항상 공부해야 합니다. 우리는 지식을 중요하게 여깁니다. 하지만 지식에 대한 지식, 즉 내가 그 지식을 얻은 과정이나 방법 같은 것은 소홀히 여기기 쉽습니다. 따라서 지식의 축적과 공유는 있어도 방법론의 축적과 공유는 매우 드문 편입니다. 저는 평소에 이런 생각에서 학교 후배들을 위해 제 자신의 공부 경험을 짬짬이 글로 옮겨놓았고, 이번 기회에 그 글들을 취합, 정리하게 되었습니다. 그 결실이 바로 이 글입니다.
이 글은 공부하는 방법과 과정에 관한 글입니다. 이 글은 제가 공부한 성공/실패 경험을 기본 토대로 했고, 지난 몇 년간 주변에서 저보다 먼저 공부한 사람들의 경험을 관찰, 분석한 것에 제가 다시 직접 실험한 것과 그밖에 오랫동안 꾸준히 모아온 자료들을 더했습니다. '만약 다시 공부한다면' 저는 이렇게 공부할 것입니다.

부디 독자 제현께서 이 글을 씨앗으로 삼아 자신만의 나무를 키우고 거기서 열매를 얻고, 또 그 열매의 씨앗이 다시 누군가에게 전해질 수 있다면 더 이상 바랄 것이 없겠습니다.

이 글은 특정 주제들의 학습/교수법에 대한 문제점과 제가 경험한 좋은 공부법을 소개하는 식으로 구성됐습니다. 여기에 선택된 과목은 리팩토링, 알고리즘·자료구조, 디자인패턴, 익스트림 프로그래밍(Extreme Programming 혹은 XP) 네 가지입니다.

이 네 가지가 선택된 이유는 필자가 관심있게 공부했던 것이기 때문만은 아니고, 모든 프로그래머에게 어떻게든 널리 도움이 될만한 교양과목이라 생각하여 선택한 것입니다. 그런데 이 네 가지의 순서가 겉보기와는 달리 어떤 단계적 발전을 함의하는 것은 아닙니다. 수신(修身)이 끝나면 더 이상 수신은 하지 않고 제가(齊家)를 한다는 것이 어불성설인 것과 같습니다.

원래는 글 후미에 일반론으로서의 공부 패턴들을 쓰려고 했습니다. 하지만 지면의 제약도 있고, 독자 스스로 이 글에서 그런 패턴을 추출하는 것도 의미가 있을 것이기에 생략했습니다. 그런 일반론이 여기 저기 숨어있기 때문에 알고리즘 공부에 나온 방법 대부분이 리팩토링 공부에도 적용할 수 있고, 적용되어야 한다는 점을 꼭 기억해 주셨으면 합니다. 다음에 기회가 닿는다면 제가 평소 사용하는 (컴퓨터) 공부패턴들을 소개하겠습니다.

알고리즘·자료구조 학습에서의 문제
우리는 알고리즘 카탈로그를 배웁니다. 이미 그러한 해법이 존재하고, 그것이 최고이며, 따라서 그것을 달달 외우고 이해해야 합니다. 좀 똑똑한 친구들은 종종 "이야 이거 정말 기가 막힌 해법이군!"하고 감탄할지도 모릅니다. 대부분의 나머지 학생들은 그 해법을 이해하려고 머리를 쥐어짜고 한참을 씨름한 후에야 어렴풋이 왜 이 해법이 그 문제를 해결하는지 납득하게 됩니다.

그리고는 그 '증명'은 책 속에 덮어두고 까맣게 사라져버립니다. 앞으로는 그냥 '사용'하면 되는 것입니다. 더 많은 대다수의 학생은 이 과정이 무의미하다는 것을 알기 때문에 왜 이 해법이 이 문제를 문제없이 해결하는지의 증명은 간단히 건너뜁니다.

이런 학생들은 이미 주어진 알고리즘을 사용하는 일종의 객관식 혹은 문제 출제자가 존재하는 시험장 상황에서는 뛰어난 성적을 보일 것임은 자명합니다. 하지만 스스로가 문제와 해답을 모두 만들어내야 하는 상황이라면, 또는 해답이 존재하지 않을 가능성이 있는 상황이라면, 혹은 최적해를 구하는 것이 불가능에 가깝다면, 혹은 알고리즘을 완전히 새로 고안해내야 하거나 기존 알고리즘을 변형해야 하는 상황이라면 어떨까요?

교육은 물고기를 잡는 방법을 가르쳐야 합니다. 어떤 알고리즘을 배운다면 그 알고리즘을 고안해낸 사람이 어떤 사고 과정을 거쳐 그 해법에 도달했는지를 구경할 수 있어야 하고, 학생은 각자 스스로만의 해법을 차근차근 '구성'(construct)할 수 있어야 합니다(이를 교육철학에서 구성주의라고 합니다. 교육철학자 삐아제(Jean Piaget)의 제자이자, 마빈 민스키와 함께 MIT 미디어랩의 선구자인 세이머 페퍼트 박사가 주창했습니다). 전문가가 하는 것을 배우지 말고, 그들이 어떻게 전문가가 되었는지를 배우고 흉내 내야 합니다.

결국은 소크라테스적인 대화법입니다. 해답을 가르쳐 주지 않으면서도 초등학교 학생이 자신이 가진 지식만으로 스스로 퀵소트를 유도할 수 있도록 옆에서 도와줄 수 있습니까? 이것이 우리 스스로와 교사들에게 물어야 할 질문입니다.
 

왜 우리는 학교에서 '프로그래밍을 하는 과정'이나 '디자인 과정'(소프트웨어 공학에서 말하는 개발 프로세스가 아니라 몇 시간이나 몇 십 분 단위의, 개인적인 차원의 사고 과정 등을 일컫습니다)을 명시적으로 배운 적이 없을까요? 왜 해답에 이르는 과정을 가르쳐주는 사람이 없나요? 우리가 보는 것은 모조리 이미 훌륭히 완성된, 종적 상태의 결과물로서의 프로그램뿐입니다. 어느 날 문득 하늘에서 완성된 프로그램이 뚝 떨어지는 경우는 없는데 말입니다.

교수가 어떤 알고리즘 문제의 해답을 가르칠 때, "교수님, 교수님께서는 어떤 사고 과정을 거쳐, 그리고 어떤 디자인 과정과 프로그래밍 과정을 거쳐서 그 프로그램을 만드셨습니까?"하고 물어봅시다. 만약 여기에 어떤 체계적인 답변도 할 수 없는 분이라면 그 분은 자신의 사고에 대해 '사고'해 본 적이 없거나 문제 해결에 어떤 효율적 체계를 갖추지 못한 분이며, 따라서 아직 남을 가르칠 준비가 되어있지 않은 분일 것입니다. 만약 정말 그렇다면 우리는 어떻게 해야 할까요?

자료구조와 알고리즘 공부
제가 생각건대, 교육적인 목적에서는 자료구조나 알고리즘을 처음 공부할 때 우선은 특정 언어로 구현된 것을 보지 않는 것이 좋을 때가 많습니다. 대신 말로 된 설명이나 의사코드(pseudo-code) 등으로 그 개념까지만 이해하는 것이죠. 그 아이디어를 절차형(C, 어셈블리어)이나 함수형(LISP, Scheme, Haskell), 객체지향(자바, 스몰토크) 언어 등으로 직접 구현해 보는 겁니다. 그 다음에는 다른 사람이나 다른 책의 코드와 비교합니다. 이 경험을 애초에 박탈당한 사람은 귀중한 배움과 깨달음의 기회를 잃은 셈입니다.

만약 여러 사람이 함께 공부한다면 각자 동일한 아이디어를 같은 언어로 혹은 다른 언어로 어떻게 다르게 표현했는지를 서로 비교해 보면 배우는 것이 무척 많습니다.

우리가 자료구조나 알고리즘을 공부하는 이유는, 특정 '실세계의 문제'를 어떠한 '수학적 아이디어'로 매핑시켜 해결할 수 있는지, 그것이 효율적인지, 또 이를 컴퓨터에 어떻게 효율적으로 구현할 수 있는지 따지고, 그것을 실제로 구현하기 위해서입니다. 따라서 이 과정에 있어 실세계의 문제를 수학 문제로, 그리고 수학적 개념을 프로그래밍 언어로 효율적으로 표현해내는 것은 아주 중요한 능력이 됩니다.

알고리즘 공부에서 중요한 것
개별 알고리즘의 목록을 이해, 암기하며 익히는 것도 중요하지만 더 중요한 것은 다음 네 가지입니다.

①알고리즘을 스스로 생각해낼 수 있는 능력
②다른 알고리즘과 효율을 비교할 수 있는 능력
③알고리즘을 컴퓨터와 다른 사람이 이해할 수 있는 언어로 표현해낼 수 있는 능력
④이것의 정상작동(correctness) 여부를 검증해 내는 능력

첫 번째가 제대로 훈련되지 못한 사람은 알고리즘 목록의 스테레오 타입에만 길들여져 있어서 모든 문제를 자신이 아는 알고리즘 목록에 끼워 맞추려고 합니다. 디자인패턴을 잘못 공부한 사람과 비슷합니다. 이런 사람들은 마치 과거에 수학 정석만 수십 번 공부해 문제를 하나 던져주기만 하면, 생각해보지도 않고 자신이 풀었던 문제들의 패턴 중 가장 비슷한 것 하나를 기계적·무의식적으로 풀어제끼는 문제풀이기계와 비슷합니다. 그들에게 도중에 물어보십시오. "너 지금 무슨 문제 풀고 있는 거니?" 열심히 연습장에 뭔가 풀어나가고는 있지만 그들은 자신이 뭘 풀고 있는지도 제대로 인식하지 못 하는 경우가 많습니다.

머리가 푸는 게 아니고 손이 푸는 것이죠. 이렇게 되면 도구에 종속되는 '망치의 오류'에 빠지기 쉽습니다. 새로운 알고리즘을 고안해야 하는 상황에서도 기존 알고리즘에 계속 매달릴 뿐입니다. 알고리즘을 새로 고안해 내건 혹은 기존의 것을 조합하건 스스로 생각해 내는 훈련이 필요합니다.

두 번째가 제대로 훈련되지 못한 사람은 일일이 구현해 보고 실험해 봐야만 알고리즘 간의 효율을 비교할 수 있습니다. 특히 자신이 가진 카탈로그를 벗어난 알고리즘을 만나면 이 문제가 생깁니다. 이건 상당한 대가를 치르게 합니다.

세 번째가 제대로 훈련되지 못한 사람은, 문제를 보면 "아, 이건 이렇게 저렇게 해결하면 됩니다"하는 말은 곧잘 할 수 있지만 막상 컴퓨터 앞에 앉혀 놓으면 아무 것도 하지 못합니다. 심지어 자신이 생각해낸 그 구체적 알고리즘을 남에게 설명해 줄 수는 있지만, 그걸 '컴퓨터에게' 설명하는 데는 실패합니다. 뭔가 생각해낼 수 있다는 것과 그걸 컴퓨터가 이해할 수 있게 설명할 수 있다는 것은 다른 차원의 능력을 필요로 합니다.

네 번째가 제대로 훈련되지 못한 사람은, 알고리즘을 특정 언어로 구현해도, 그것이 옳다는 확신을 할 수 없습니다. 임시변통(ad hoc)의 아슬아슬한 코드가 되거나 이것저것 덧붙인 누더기 코드가 되기 쉽습니다. 이걸 피하려면 두 가지 훈련이 필요합니다.

하나는 수학적·논리학적 증명의 훈련이고, 다른 하나는 테스트 훈련입니다. 전자가 이론적이라면 후자는 실용적인 면이 강합니다. 양자는 상보적인 관계입니다. 특수한 경우들을 개별적으로 테스트해서는 검증해야 할 것이 너무 많고, 또 모든 경우에 대해 확신할 수 없습니다. 테스트가 버그의 부재를 보장할 수는 없습니다. 하지만 수학적 증명을 통하면 그것이 가능합니다. 또, 어떤 경우에는 수학적 증명을 굳이 할 필요 없이 단순히 테스트 케이스 몇 개만으로도 충분히 안정성이 보장되는 경우가 있습니다. 이럴 때는 그냥 테스트만으로 만족할 수 있습니다.


실질적이고 구체적인 문제를 함께 다루라
자료구조와 알고리즘 공부를 할 때에는 가능하면 실질적이고 구체적인 실세계의 문제를 함께 다루는 것이 큰 도움이 됩니다. 모든 학습에 있어 이는 똑같이 적용됩니다. 인류의 지성사를 봐도, 구상(concrete) 다음에 추상(abstract)이 옵니다. 인간 개체 하나의 성장을 봐도 그러합니다. 'be-동사 더하기 to-부정사'가 예정으로 해석될 수 있다는 룰만 외우는 것보다 다양한 예문을 실제 문맥 속에서 여러 번 보는 것이 훨씬 나을 것은 자명합니다. 알고리즘과 자료구조를 공부할 때 여러 친구들과 함께 연습문제(특히 우리가 경험하는 실세계의 대상들과 관련이 있는 것)를 풀어보기도 하고, ACM의 ICPC(International Collegiate Programming Contest: 세계 대학생 프로그래밍 경진 대회) 등의 프로그래밍 경진 대회 문제 중 해당 알고리즘·자료구조가 사용될 수 있는 문제를 같이 풀어보는 것도 아주 좋습니다. 이게 가능하려면 "이 알고리즘이 쓰이는 문제는 이거다"하고 가이드를 해줄 사람이 있으면 좋겠죠. 이것은 그 구체적 알고리즘·자료구조를 훈련하는 것이고, 이와 동시에 어떤 알고리즘을 써야할지 선택, 조합하는 것과 새로운 알고리즘을 만들어내는 훈련도 무척 중요합니다.

알고리즘 디자인 과정의 중요성
알고리즘을 좀더 수월하게, 또 잘 만들려면 알고리즘 디자인 과정에 대해 생각해 봐야 합니다. 그냥 밑도 끝도 없이 문제를 쳐다본다고 해서 알고리즘이 튀어나오진 않습니다. 체계적이고 효율적인 접근법을 사용해야 합니다. 대표적인 것으로 다익스트라(E. W. Dijkstra)와 워스(N. Wirth)의 '조금씩 개선하기'(Stepwise Refinement)가 있습니다. 워스의 「Program Development by Stepwise Refinement」(1971, CACM 14.4, http://www.acm.org/classics/dec95)를 꼭 읽어보길 바랍니다. 여기 소개된 조금씩 개선하기는 구조적 프로그래밍에서 핵심적 역할을 했습니다(구조적 프로그래밍을 'goto 문 제거' 정도로 생각하면 안 됩니다). 다익스트라의 「Stepwise Program Construction」(Selected Writings on Computing: A Personal Perspective, Springer-Verlag, 1982, http://www.cs.utexas.edu/users/EWD/ewd02xx/EWD227.PDF)도 추천합니다.

알고리즘 검증은 알고리즘 디자인과 함께 갑니다. 새로운 알고리즘을 고안할 때 검증해 가면서 디자인하기 때문입니다. 물론 가장 큰 역할은 고안이 끝났을 때의 검증입니다. 알고리즘 검증에는 루프 불변식(loop invariant) 같은 것이 아주 유용합니다. 아주 막강한 무기입니다. 익혀 두면 두고두고 가치를 발휘할 것입니다. 맨버(Udi Manber)의 알고리즘 서적(『Introduction to Algorithms: A Creative Approach』)이 알고리즘 검증과 디자인이 함께 진행해 가는 예로 자주 추천됩니다. 많은 계발을 얻을 것입니다. 고전으로는 다익스트라의 『A Discipline of Programming』과 그라이스(Gries)의 『The Science of Programming』이 있습니다. 특히 전자를 추천합니다. 프로그래밍에 대한 관을 뒤흔들어 놓을 것입니다.

알고리즘과 패러다임
알고리즘을 공부하면 큰 줄기들을 알아야 합니다. 개별 테크닉도 중요하지만 '패러다임'이라고 할만한 것들을 알아야 합니다. 이것에 대해서는 튜링상을 수상한 로버트 플로이드(Robert Floyd)의 튜링상 수상 강연(The Paradigms of Programming, 1978)을 추천합니다. 패러다임을 알아야 알고리즘을 상황에 맞게 마음대로 변통할 수 있습니다. 그리고 자신만의 분류법을 만들어야 합니다. 구체적인 문제들을 케이스 바이 케이스로 여럿 접하는 동안 그냥 지나쳐 버리면 개별자는 영원히 개별자로 남을 뿐입니다. 비슷한 문제들을 서로 묶어서 일반화해야 합니다.

이런 패러다임을 발견하려면 '다시 하기'가 아주 좋습니다. 다른 것들과 마찬가지로, 이 다시 하기는 알고리즘에서만이 아니고 모든 공부에 적용할 수 있습니다. 같은 것을 다시 해보는 것에서 우리는 얼마나 많은 것을 배울 수 있을까요. 대단히 많습니다. 왜 동일한 문제를 여러 번 풀고, 왜 같은 내용의 세미나에 또 다시 참석하고, 같은 프로그램을 거듭 작성할까요? 훨씬 더 많이 배울 수 있기 때문입니다. 화술 교육에서는 같은 주제에 대해 한 번 말해본 연사와 두 번 말해본 연사는 천지 차이가 있다고 말합니다. 같은 일에 대해 두 번의 기회가 주어지면 두 번째에는 첫 번째보다 잘 할 기회가 있습니다. 게다가 첫 번째 경험했던 것을 '터널을 벗어나서' 다소 객관적으로 볼 수 있게 됩니다. 왜 자신이 저번에 이걸 잘 못 했고, 저걸 잘 했는지 알게 되고, 어떻게 하면 그걸 더 잘할 수 있을는지 깨닫게 됩니다. 저는 똑같은 문제를 여러 번 풀더라도 매번 조금씩 다른 해답을 얻습니다. 그러면서 정말 엄청나게 많은 것을 배웁니다. '비슷한 문제'를 모두 풀 능력이 생깁니다.

제가 개인적으로 존경하는 전산학자 로버트 플로이드(Robert W. Floyd)는 1978년도 튜링상 강연에서 다음과 같은 말을 합니다.


제가 어려운 알고리즘을 디자인하는 경험을 생각해 볼 때, 제 능력을 넓히는 데 가장 도움이 되는 특정한 테크닉이 있습니다. 어려운 문제를 푼 후에, 저는 그것을 처음부터 완전히 새로 풉니다. 좀 전에 얻은 해법의 통찰(insight)만을 유지하면서 말이죠. 해법이 제가 희망하는 만큼 명료하고 직접적인 것이 될 때까지 반복합니다. 그런 다음, 비슷한 문제들을 공략할 어떤 일반적인 룰을 찾습니다. 아까 주어진 문제를 아예 처음부터 최고로 효율적인 방향에서 접근하도록 이끌어줬을 그런 룰을 찾는 거죠. 많은 경우에 그런 룰은 불변의 가치가 있습니다. … 포트란의 룰은 몇 시간 내에 배울 수 있습니다. 하지만 관련 패러다임은 훨씬 더 많은 시간이 걸립니다. 배우거나(learn) 배운 것을 잊거나(unlearn) 하는 데 모두.

수학자와 프로그래머를 포함한 모든 문제 해결자들의 고전이 된 죠지 폴리야(George Polya)의 『How to Solve it』에는 이런 말이 있습니다:

심지어는 꽤나 훌륭한 학생들도, 문제의 해법을 얻고 논증을 깨끗하게 적은 다음에는 책을 덮어버리고 뭔가 다른 것을 찾는다. 그렇게 하는 동안 그들은 그 노력의 중요하고도 교육적인 측면을 잃어버리게 된다. … 훌륭한 선생은 어떠한 문제이건 간에 완전히 바닥이 드러나는 경우는 없다는 관점을 스스로 이해하고 또 학생들에게 명심시켜야 한다.

저는 ACM의 ICPC 문제 중에 어떤 문제를 이제까지 열 번도 넘게 풀었습니다. 대부분 짝 프로그래밍이나 세미나를 통해 프로그래밍 시연을 했던 것인데, 제 세미나에 여러 번 참석한 분이 농담조로 웃으며 물었습니다. "신기해요. 창준 씨는 그 문제를 풀 때마다 다른 프로그램을 짜는 것 같아요. 설마 준비를 안 해 와서 그냥 내키는 대로 하는 건 아니죠?" 저는 카오스 시스템과 비슷하게 초기치 민감도가 프로그래밍에도 작용하는 것 같다고 대답했습니다. 저 스스로 다른 해법을 시도하고 싶은 마음이 있으면 출발이 조금 다르고, 또 거기서 나오는 진행 방향도 다르게 됩니다. 그런데 중요한 것은 이렇게 같은 문제를 매번 다르게 풀면서 배우는 것이 엄청나게 많다는 점입니다. 저는 매번, 전보다 개선할 것을 찾아내게 되고, 또 새로운 것을 배웁니다. 마치 마르지 않는 샘물처럼 계속 생각할 거리를 준다는 점이 참 놀랍습니다.

알고리즘 개론 교재로는 CLR(Introduction to Algorithms, Thomas H. Cormen, Charles E. Leiserson, and Ronald L. Rivest)을 추천합니다. 이와 함께 혹은 이 책을 읽기 전에 존 벤틀리(Jon Bentley)의 『Programming Pearls』도 강력 추천합니다. 세계적인 짱짱한 프로그래머와 전산학자들이 함께 꼽은 위대한 책 목록에서 몇 손가락 안에 드는 책입니다. 아직 이 책을 본 적이 없는 사람은 축하합니다. 아마 몇 주간은 감동 속에 하루하루를 보내게 될 겁니다.

리팩토링 학습에서의 문제
먼저, 본지 2001년 11월호에 제가 썼던 마틴 파울러의 책을 추천하는 글을 인용하겠습니다.

OOP를 하건 안 하건 프로그래밍이란 업을 하는 사람이라면 이 책은 자신의 공력을 서너 단계 레벨업시켜줄 수 있다. 자질구레한 술기를 익히는 것이 아니고 기감과 내공을 증강하는 것이다.

혹자는 DP 이전에 RF를 봐야 한다고도 한다. 이 말이 어느 정도 일리가 있는 것이, 효과적인 학습은 문제의식이 선행해야 하기 때문이다. DP는 거시적 차원에서 해결안을 모아놓은 것이다. RF를 보고 나쁜 냄새(Bad Smell)를 맡을 수 있는 후각을 발달시켜야 한다. RF의 목록을 모두 외우는 것은 큰 의미가 없다. 그것보다 냄새나는 코드를 느낄 수 있는 감수성을 키우는 것이 더 중요하다. 필자는 일주일에 한 가지씩 나쁜 냄새를 정해놓고 그 기간 동안에는 자신이 접하는 모든 코드에서 그 냄새만이라도 확실히 맡도록 집중하는 방법을 권한다. 일명 일취집중후각법. 패턴 개념을 만든 건축가 크리스토퍼 알렉산더나 GoF의 랄프 존슨은 좋은 디자인이란 나쁜 것이 없는 상태라고 한다. 무색 무미 무취의 무위(無爲)적 자연(自然) 코드가 되는 그 날을 위해 오늘도 우리는 리팩토링이라는 유위(有爲)를 익힌다.

주변에서 리팩토링을 잘못 공부하는 경우를 종종 접합니다. 어떤 의미에서 잘못 공부한다고 할까요? '실체화'가 문제입니다. 리팩토링은 도구이고 방편일 뿐인데, 그것에 매달리는 것은 달은 보지 않고 손을 보는 것과 같습니다. 저는 리팩토링 책이 또 하나의 (이미 그 병폐가 많이 드러난) GoF 책이 되는 현상이 매우 걱정됩니다.

리팩토링 공부
사람들이 일반적으로 생각하는 바와는 달리 리팩토링 학습에 있어 어떤 리팩토링이 있는지, 구체적으로 무엇인지 등의 리팩토링 목록에 대한 지식과 각각에 대한 메카닉스(Mechanics: 해당 리팩토링을 해나가는 구체적 단계)는 오히려 덜 중요할 수 있습니다. 더 기본적이고 유용한 것은 코드 냄새(Code Smell)와 짧은 테스트-코드 싸이클입니다. 이것만 제대로 되면 리팩토링 책의 모든 리팩토링을 스스로 구성해낼 수 있으며, 다른 종류의 리팩토링까지 직접 발견해낼 수 있습니다.

그 책에서는 테스트의 중요성이 충분히 강조되지 않았습니다. 하지만 테스트 코드 없는 리팩토링은 안전벨트 없는 자동차 경주와 같습니다. 그리고 테스트 코드가 리팩토링의 방향을 결정하기도 합니다. 양자는 음과 양처럼 서로 엮여 있습니다. 이런 의미에서 리팩토링은 TDD(Test Driven Development)와 함께 수련하는 것이 좋습니다. 훨씬 더 빨리, 훨씬 더 많은 것을 배울 수 있을 겁니다.


리팩토링을 공부할 때는 우선 코드 냄새의 종류를 알고, 왜 그것이 나쁜 냄새가 될 수 있는지 이해하고(그게 불가하다면 리팩토링 공부를 미뤄야 합니다) 거기에 동의할 수 있어야 합니다. 그런 다음, 대충 어떤 종류의 리팩토링이 가능한지 죽 훑어봅니다. 그 중 몇 개는 메카닉스를 따라가면서 실험해 봅니다. 이제는 책을 덮습니다. 그리고 실제 코드를 접하고, 만약 거기에서 냄새를 맡는다면 이 냄새를 없애기 위해 어떻게 해야 할지 스스로 고민합니다. 리팩토링 책의 목록은 일단 무시하십시오. 그 냄새를 없애는 것이 목표이지, 어떤 리팩토링을 여기에 '써먹는 것'이 목표가 되어선 안 됩니다. 이 때, 반드시 테스트 코드가 있어야 합니다. 그래야 '좋은' 리팩토링을 할 수 있습니다. 책을 떠나 있으면서도 책에서 떠나지 않는 방법입니다.

리팩토링을 하기 전에 초록색 불(테스트가 모두 통과)이 들어온 시점에서 코드를 일부 고치면 빨간 불(테스트가 하나라도 실패)로 바뀔 겁니다. 이게 다시 초록색 불이 될 때까지 최소한도의 시간이 걸리도록 하십시오. 현 초록색에서 다음 초록색까지 최소한의 시간을 소비하도록 하면서 코드와 테스팅을 오가게 되면 자기도 모르는 사이에 훌륭한 리팩토링이 자발공으로 터져 나옵니다. 여기서 목적지는 우선은 OAOO(Once And Only Once: 모든 것은 오로지 한 번만 말해야 한다)를 지키는 쪽으로 합니다. 그러면 OAOO와 짧은 테스트-코드 싸이클을 지키는 사이 어느새 탁월한 디자인이 튀어나옵니다. 참고로 저는 '모래시계 프로그래밍'이란 걸 가끔 합니다. 모래시계나 알람 프로그램으로 테스트-코드 사이클의 시간을 재는 것입니다. 그래서 가급적이면 한 사이클이 3분 이내(대부분의 모래시계는 단위가 3분입니다)에 끝나도록 노력합니다. 여기서 성공을 하건 실패를 하건 많은 걸 얻습니다.

리팩토링 수련법
제가 고안, 사용한 몇 가지 리팩토링 수련법을 알려드립니다.

①일취집중후각법: 앞에 소개한 본지 2001년 11월호에서 인용된 글 참조
②주석 최소화: 주석을 최소화하되 코드의 가독성이 떨어지지 않도록(혹은 오히려 올라가도록) 노력합니다. 이렇게 하면 자동으로 리팩토링이 이뤄지는 경우가 많습니다.
③OAOO 따르기: OAOO 법칙을 가능하면 최대한, 엄격하게 따르려고 합니다. 역시 자동으로 좋은 리팩토링이 이뤄집니다. 여기서 디자인패턴이 창발하기도 합니다. GoF 책을 한번도 보지 못한 사람이 디자인패턴을 자유자재로 부리는 경우를 보게 됩니다.
④디미터 법칙(Law of Demeter) 따르기: 디미터 법칙을 가능하면 지키려고 합니다. 어떤 리팩토링이 저절로 이뤄지거나 혹은 필요 없어지는가요?
⑤짝(Pair) 리팩토링: 함께 리팩토링합니다. 혼자 하는 것보다 더 빨리, 더 많은 걸 배우게 됩니다. 특히, 각자 작성했던 코드를 함께 리팩토링하고, 제3자의 코드를 함께 리팩토링해 봅니다. 사람이 많다면 다른 짝이 리팩토링한 것과 서로 비교하고 토론합니다.
⑥'무엇'과 '어떻게'를 분리: 어떻게에서 무엇을 분리해 내도록 합니다. 어떤 리팩토링이 창발합니까?

여기서 번, 짝 리팩토링은 아주 효과적인 방법입니다. 저는 이것을 협동적 학습(Collaborative Learning)이라고 부릅니다. 상대가 나보다 더 많이 아는 경우만이 아니고, 서로 아는 것이 비슷해도 많은 양의 학습이 발생합니다. 특히, 전문가와 함께 짝 프로그래밍을 하면 무서울 만큼 빠른 학습을 경험할 수 있습니다. 저와 짝 프로그래밍을 한 사람이 학습하는 속도에서 경이감을 느낀 적이 한두 번이 아닙니다. 문화는 사회적으로 학습되는 것입니다. 우리가 지식이라고 하는 것의 상당 부분은 문화처럼 암묵적인 지식(Tacit Knowledge)입니다. 전문가가 문제가 생겼을 때 어떻게 사고하고, 어떤 과정을 거쳐 접근하며, 어떻게 디버깅하고, 키보드를 어떤 식으로 누르는지, 사고 도구로 무엇을 사용하는지, 일 계획과 관리를 어떻게 하는지, 동료와 어떻게 대화하는지 등은 성문화되어 있지 않습니다. 그러나 이런 것들은 아주 중요합니다. 프로페셔널의 하루 일과의 대부분을 이루고 있기 때문입니다. 이런 것들은 전문가 바로 옆에서 조금씩 일을 도와주면서 배워야 합니다. 도제 살이(Apprenticeship)입니다. 진정한 전문가는 모든 동작이 우아합니다. 마치 춤을 추는 것 같습니다. 이 모습을 바로 곁에서 지켜보게 되면, 주니어는 한마디로 엄청난 충격을 받습니다. 그리고 스펀지처럼 빨아들이게 됩니다. 도대체 이 경험을 책이나 공장화한 학교가 어떻게 대신하겠습니까. 이와 관련해서는 레이브와 웽거(Jean Lave, Etienne Wenger)의 『Situated Learning : Legitimate Peripheral Participation』을 강력 추천합니다. 이 글을 보는 모든 교육 종사자들이 꼭 읽어봤으면 합니다. 이 협동적 학습은 두 사람만이 아니고 그룹 단위로도 가능합니다. 스터디에 이용하면 재미와 유익함 일석이조를 얻습니다.

이 외에, 특히(어쩌면 가장) 중요한 것은 일취집중후각법 등을 이용해 자신의 코드 후각의 민감도를 높이는 것입니다. 코드 후각의 메타포 말고도 유사한 메타포가 몇 가지 더 있습니다. 켄트 벡은 코드의 소리를 들으라고 하고, 저는 코드를 향해 대화하라고 합니다. 코드의 소리를 듣는 것은 코드가 원하는 것에 귀를 기울이는 것을 말합니다. 코드는 단순해지려는 욕망이 있습니다. 그걸 이뤄주는 것이 프로그래머입니다. 그리고 짝 프로그래밍을 할 때 두 사람의 대화를 코드에 남기도록 합니다. 주석이 아닙니다. 왜 이것이 중요한가는 본지 2001년 12월호 「허실문답 XP 강화」를 참고하기 바랍니다.


기학으로 우리 사상사에 큰 획을 그은 철학자요, '서울서 책만 사다 망한 사람'으로 이름을 날릴 정도로 엄청난 지식욕을 과시하던 조선시대 사상가 혜강 최한기는 그의 저술 『신기통』(神氣通)에서 '눈에 통하는 법(目通), 귀에 통하는 법(耳通), 코에 통하는 법(鼻通)' 등을 이야기하고 있습니다. 어떻게 하면 우리는 코드에 도통할 수 있을까요? 리팩토링을 공부하거나 혹은 했던 사람들에게 많은 영감과 메타포를 주는 책으로 일독을 권합니다. 필자가 기회가 닿는다면 프로그래밍을 혜강의 사상적 측면에서 조망한 글을 써보고 싶습니다.

앞서의 것들이 어느 정도 이뤄지고, 리팩토링에 대한 감이 오게 되면 그 때 비로소 리팩토링 책을 하나 하나 파헤치고 또 거기서 제대로 된 비판을 할 수 있게 됩니다.

디자인패턴 학습에서의 문제
잡지에 연재되거나 서적으로 출간된 혹은 세미나에서 진행되었던 디자인패턴 '강의'를 몇 가지 접했습니다. 훌륭한 강의도 많았지만 그렇지 못한 것도 있었습니다. 몇 가지 문제점을 지적하겠습니다.

◆패턴을 지나치게 실체화, 정형화해 설명한다.
◆컨텍스트와 문제 상황에 대한 설명이 없거나 부족하다. 결과적으로 문제를 해결하기 위해 패턴이 도입된 것이 아니라 패턴을 써먹기 위해 패턴이 도입된 느낌을 준다.
◆문제의식을 먼저 형성하게 하지 않고 답을 먼저 보여준 뒤 그걸 어디에 써먹을지 가르친다. 왜 이걸 쓰는 게 좋은지는 일언반구 언급이 없다. 독자는 '어린아이가 망치를 들고 있는 오류'에 빠질 것이다.
◆패턴이 어떻게 생성되었는지 그 과정을 보여주지 못한다. 즉, 스스로 패턴을 만들어내는 데 도움이 전혀 되지 않는다.
◆해당 패턴이 현실적으로 가장 자주 쓰이는 맥락을 보여주지 못한다. 대부분 장난감 문제(Toy Problem)에서 끝난다.

그런 패턴 강의를 하는 분들이 알렉산더(Christopher Alexander, 패턴언어 창시자)의 저작을 충실히 읽어봤다면 이런 병폐는 없을 것이라 생각합니다. 알렉산더의 저작을 접해보지 못 하고서 패턴을 가르치는 사람은 성경을 읽어보지 않은 전도사와 같을 것입니다. 알렉산더가 『The Timeless Way of Building』의 마지막에서 무슨 말을 하는가요?

이 마지막 단계에는 더 이상 패턴은 중요하지 않다. … 패턴은 당신이 현실적인 것에 대해 수용적이 되는 것을 가르쳐줬다.

패턴 역시 도구요, 방편일 뿐입니다. 패턴은 현실적인 것에 대해 수용적이 되도록 가르친다는 말은 결국 우리가 궁극적으로 추구하는 것은 패턴이 아니라 현실이어야 한다는 이야기입니다. 물론 처음 단계에는 교육적인 목적에서, 어느 정도 패턴에 얽매여도 괜찮다고는 해도, 나중에 패턴을 잊고 패턴에서 자유로워지려면 처음부터 패턴에 대해 도구적·방편적인 인식을 가져야 합니다.

미국 캘리포니아 주립대학의 교수 베티 에드워즈(Betty Edwards)가 쓴 책 중에 『Drawing on the Right Side of the Brain』이라는 유명한 베스트셀러가 있습니다. 사람의 뇌와 그림 그리기의 관계에 대한 탁월한 책입니다. 에드워즈는 자신의 그리기 실력을 향상시키기 위해 우뇌를 적극적으로 사용하는 구체적인 방법들을 가르쳐줍니다. 그 중 대표적인 것 하나가 대상을 뒤집어 놓고 그리는 것입니다. 지금 실험해 보길 바랍니다. 1000원권 지폐를 바로 놓고 그걸 비슷하게 그려보고, 이번에는 그걸 위아래가 거꾸로 되게 놓고 따라 그려보십시오. 아마 무척 놀랐을 겁니다. "아니 내가 이렇게 그림을 잘 그리다니! 그것도 거꾸로!" 그렇습니다. 우리는 자신의 머리 속 패턴에 얽매여 세상을 제대로 보지 못 할 때가 많습니다. 실체가 코에 약간이라도 비슷하게 보이면 우리는 그것을 이미 우리 머리 속에 추상적으로 갖고 있던 기하학적 '코'의 패턴으로 대체해버리는 것입니다.

디자인 패턴 공부
우선은 제 교육철학과 언어교습론, 그리고 공부론 이야기를 잠깐 하겠습니다.

기본적으로 교육은 교육자가 피교육자가에게 지식을 그대로 전달하는 행위가 아닙니다. 진정한 교육은 피교육자의 개인적 체험에 기반한 전폭적 동의에서 출발합니다. 저는 이를 동의에 의한 교육이라고 합니다.

제가 "주석문을 가능하면 쓰지 않는 것이 더 좋다"는 이야기를 했을 때 이 문장을 하나의 사실로 받아들이고 기억하면 당장 그 시점에는 학습이 일어나지 않는다고 봅니다. 대신 여러분이 차후에 여러 가지 경험을 하면서도 이 화두를 놓치지 않고 있다가 어느 순간엔가, "아! 그래, 주석문을 쓰지 않는 게 좋겠구나!"하고 자각하는 순간, 바로 그 시점에 학습과 교육이 이뤄지는 것입니다. 이는 기본적으로 삐아제와 비갓스키(Lev Vygotsky)의 구성주의를 따르는 것이죠. 지식이란 외부에서 입력받는 것이 아니고, 그것에 대한 모델을 학습자 스스로가 내부에서 구축할 때 획득할 수 있는 것이라는 사상이죠.


권법에서 주먹에 대해 달통한 도사가 '권을 내지르는 법'에 대한 규칙들을 정리해서 애제자의 머리 속에 아무리 쑤셔 넣는 데 성공한들 그 제자가 도사만큼 주먹이 나갈리는 만무합니다. 권을 내지르는 법을 유추해 내기까지 그 스승이 겪은 과정을 제자는 완전히 쏙 빼먹고 있기 때문입니다. 소위 '몸'이 만들어지지 않은 것이지요. 제자는 마당 쓸기부터, 물 긷기 등의 수련 과정을 겪어야만 하고 스승이 정리한 그 일련의 규칙에 손뼉을 치고 춤을 추며 기쁨의 동의를 할 수 있을 정도로 수련 과정이 축적된 이후에야 비로소 진정한 '가르침'이 이뤄지는 것이며, 청출어람의 가능성도 생각해 볼 수 있는 것입니다.

이런 동의라는 것은 학습자 자신만의 컨텍스트와 문제의식을 바탕으로 한 것입니다. 우리는 많은 경우, 어떤 지식과 동시에 그 지식의 필요성까지도 지식화해서 외부에서 주입을 받습니다. 하지만 진정 체화된 지식을 위해서는 스스로가 이미 문제의식을 갖고 있어야 합니다.

패턴도 마찬가지인데, 대부분 그 패턴의 필요성을 체감하지 못한 채 그냥 도식적 구조를 외우기에만 주력하는 사람이 많습니다만, 사실 그렇게 되면 어떤 경우에 이 패턴이 필요하고 어떤 경우에는 사용하면 안 되는지(GoF는 패턴을 정말 안다는 것은 그 패턴을 쓰면 안 될 때를 아는 것이라 했습니다) 등을 알기 힘듭니다. 설령 책에 나온 가이드를 암기했더라도요. 자신의 삶 속에서 문제의식이 구체적으로 실제 경험으로 형성되지 않았기 때문입니다.

GoF 중 한 명인 랄프 존슨(Ralph Johnson)은 다음과 같이 말합니다.

우리[GoF]는 책에서, 정말 그 패턴들이 필요하다는 것을 알만큼 충분한 경험을 갖기 전에는 그것을 [시스템 속에] 집어넣는 것을 피해야 한다고 말할 만큼 대담하진 못했다. 하지만 우리 모두는 그 사실을 믿었다. 패턴은 프로그램의 초기 버전이 아니고 프로그램 생애의 훨씬 나중에 가서야 비로소 등장해야 한다고 나는 늘 생각해 왔다.

결국은 어떤 패턴의 필요성을 자신의 경험 속에서 절감하지 못한다면 그 패턴을 제대로 아는 것이 아니라고 말할 수 있을 겁니다. 따라서 패턴 하나를 공부할 때는 가능한 한 실제 예를 많이 접해야 합니다. 그리고 패턴을 적용하지 않은 경우에서 그 필요를 느끼고 설명할 수 있게끔 다양한 코드를 접해야 합니다.

소프트웨어 개발에 푹 빠지기
패턴 중에 보면 서로 비슷비슷한 것이 상당히 많습니다. 그 구조로는 완전히 동일한 것도 있죠. 초보자를 괴롭히는 것 중 하나입니다. 이것은 외국어를 공부할 때 문법 중심적인 학습을 하면서 부딪치는 문제와 비슷합니다. '주어+동사+목적어'라는 구조로는 동일한 두 개의 문장, 즉 'I love you'와 'I hate you'가 구조적으로는 동일할지라도 의미론적으로는 완전히 반대가 될 수 있는 겁니다. 패턴을 공부할 때는 그 구조보다 의미와 의도를 우선해야 하며, 이는 다양한 실례를 케이스 바이 케이스로 접하면서 추론화 및 자신만의 모델화라는 작업을 통해 하는 것이 최선입니다. 스스로 문법을 발견하고 체득하는 것이라고 할까요.

DP는 사전과 같습니다. 이 책은 순서대로 소설 읽듯이 읽어나가라고 집필된 것이 아니고, 일종의 패턴 레퍼런스로 쓰인 것입니다. 역시 GoF의 한 명인 존 블리스사이즈(John Vlissides)는 다음과 같이 말합니다.

여기서 내가 강조하고 싶은 것은 디자인패턴, 즉 GoF 책을 어떻게 읽느냐는 것이다. 많은 사람들은 그 내용을 온전히 이해하기 위해서는 순서대로 읽어야 한다고 느낀다. 하지만 GoF는 소설이 아니라 레퍼런스 북이다. 독일어를 배우기 위해 독영 사전의 처음부터 끝까지 하나하나 읽으려고 하는 경우를 생각해 보라. 그렇게는 결코 배울 수 없을 것이다! 독일어를 마스터하기 위해서는 독일어 문화에 자기 자신을 푹 담궈야(immerse) 한다. 독일어로 살아야 하는 것이다. 디자인패턴도 똑같다. 그걸 마스터하기 이전에 소프트웨어 개발에 자신을 푹 담궈야 한다. 패턴으로 살아야 하는 것이다.
만약 꼭 그래야 한다면 소설 읽듯이 디자인패턴 책을 읽어라. 하지만 거의 아무도 그 방식으로 유창해지지 못한다. 소프트웨어 개발 프로젝트의 열기 속에서 패턴이 동작하게 하라. 실제 디자인 문제를 직면했을 때 그 패턴들의 통찰을 이용하라. 이것이 GoF 패턴들을 자신의 것으로 만드는 가장 효율적인 방법이다.

어떤 지식을 체화하기 위해선 그 지식으로 살아야 한다는 말을 확인할 수 있습니다. 영어를 배우려면 영어로 살고, DP를 배우려면 DP로 살라는 단순하면서도 아주 강력한 말입니다.

어떤 특정 문장 구조를 학습하는 데 최선은 그 문장 구조를 이용한 실제 문장을 나에게 의미 있는 실제 컨텍스트 속에서 많이 접하고 스스로 나름의 모델을 구축하여 교과서의 법칙에 '기쁨에 찬 동의'를 하는 것입니다.

주변에서 특정 패턴이 구현된 코드를 구하기가 힘들다면 이 패턴을 자신이 만지고 있는 코드에 적용해 보려고 노력해 볼 수 있습니다. 이렇게 해보고 저렇게도 해보고, 그러다가 오히려 복잡도만 증가하면 "아 이 경우에는 이 패턴을 쓰면 안 되겠구나"하는 걸 학습할 수도 있죠. GoF는 패턴을 배울 때는 한결 같이 "이 패턴이 적합한 상황과 동시에 이 패턴이 악용, 오용될 수 있는 상황"을 함께 공부하라고 합니다.

이런 식의 '사례 중심'의 공부를 위해서는 스터디 그룹을 조직하는 것이 좋습니다. 혼자 공부를 하건, 그룹으로 하건 커리프스키(Joshua Kerievsky)의 「A Learning Guide To Design Patterns」(http://www.industriallogic.com/papers/learning.html)를 참고하세요. 그리고 스터디 그룹을 효과적으로 꾸려 나가는 데는 스터디 그룹의 패턴 언어를 서술한 「Knowledge Hydrant」(http://www.industriallogic.com/papers/khdraft.pdf)를 참고하면 많은 도움이 될 겁니다. 이 문서는 뭐든지 간에 그룹 스터디를 한다면 적용할 수 있습니다.


LG2DP(「A Learning Guide To Design Patterns」) 뒷부분에 보면 DP를 공부하는 순서와 각 패턴에서 던질만한 질문이 같이 정리되어 있습니다. DP는 순차적으로 공부해야만 하는 것은 아닙니다. 효과적인 공부의 순서가 있습니다. sorry라는 단어를 모르면서 remorseful이라는 단어를 공부하는 학생을 연상해 보세요. 외국어 공부에서는 자기 몸에 가까운 쉬운 단어부터 공략하는 것이 필수적입니다. 이런 걸 근접 학습(Proximal Learning)이라고도 하죠. 등급별 어휘 목록 같은 게 있으면 좋죠. LG2DP에서 제안하는 순서가 그런 것 중 하나입니다.

랄프 존슨은 이런 순서의 중요성에 관해 다음과 같은 말을 했습니다.

… 하지만 나는 언제나 싱글톤 패턴을 가르치기 전에 콤포짓, 스트래터지, 템플릿 메쏘드, 팩토리 메쏘드 패턴을 가르친다. 이것이 훨씬 더 일반적인 것들이며, 대다수의 사람들은 아마도 이것들 중 마지막 두 가지를 이미 사용하고 있을 것이다.

마이크로패턴
그런데 사실 GoF의 DP에 나온 패턴들보다 더 핵심적인 어휘군이 있습니다. 마이크로패턴이라고도 불리는 것들입니다. DP에도 조금 언급되어 있긴 합니다. 이런 마이크로패턴은 우리가 알게 모르게 매일 사용하는 것들이고 그 활용도가 아주 높습니다. 실제로 써보면 알겠지만, DP의 패턴 하나 쓰는 일이 그리 흔한 게 아닙니다. 마이크로패턴은 켄트 벡의 『Smalltalk Best Practice Patterns』에 잘 나와 있습니다. 영어로 치자면 관사나 조동사 같은 것들입니다.

그리고 이런 마이크로패턴과 함께 리팩토링을 공부하는 게 좋습니다. 리팩토링은 패턴의 필요를 느끼게 해줍니다. 제가 리팩토링 공부에서도 언급했지만 OAOO를 지키면서 리팩토링을 하다보면 자연스레 디자인패턴에 도달하는 경우가 많습니다. 이 때는 지나친 엔지니어링(Overengineering)이 발생하지 않고, 오로지 필요한 만큼만 생깁니다. 이에 관해서는 커리프스키의 「Stop Over-Engineering!」(Software Development Magazine, Apr 2002, http://www.sdmagazine.com/documents/s=7032/sdm0204b/0204b.htm)의 일독을 권합니다. 리팩토링이 디자인패턴을 어떻게 생성해낼 수 있는지 보여주고 있습니다.

1980년대 이후 최근 알렉산더의 향방도 이런 쪽으로 가고 있습니다. 그는 자신이 발표한 기존 패턴들이 너무 크다고 생각해 그런 패턴들을 구성하고, 자동으로 만들어 내며, 또 관통하는 더 작은 원칙들을 발견하는 데 노력해 오고 있습니다. 코플리엔(James Coplien)은 컴퓨터계가 알렉산더의 최근 발전을 쫓아가지 못한다고 늘 이야기합니다.

제대로 된 패턴 구현을 위한 다양한 접근 시도하기
우리의 지식이라는 것은 한 가지 표현양상(representation)으로만 이뤄져 있지 않습니다. 사과라는 대상을 음식으로도, 그림의 대상으로도 이해할 수 있어야 합니다. 실제 패턴이 적용된 '다양한 경우'를 접하도록 하라는 것이 이런 겁니다. 동일 대상에 대한 다양한 접근을 시도하라는 것이죠. 자바로 구현된 코드도 보고, C++로 된 것도 보고, 스몰토크로 된 것도 봐야 합니다. 설령 '오로지 자바족'이라고 할지라도요(전 이런 사람들을 자바리안(Javarian)이라고 부릅니다. 자바와 바바리안(barbarian)을 합성해서 만든 조어지요). 이런 '오로지 하나만 공부하는 것'의 병폐에 대해서는 존 블리스사이즈가 쓴 「Diversify」(http://www.research.ibm.com/people/v/vlis/pubs/gurus-99.pdf)라는 글을 읽어보세요. 이렇게 다양화를 해야 비로소 자바로도 '상황에 맞는' 제대로 된 패턴을 구현할 수 있습니다. 패턴은 그 구현(implementation)보다 의도(intent)가 더 중요하다는 사실을 꼭 잊지 말고, 설명을 위한 방편으로 채용된 한 가지 도식에 자신의 사고를 구속하는 우를 범하지 않기를 빕니다.

이런 맥락에서 저는 DP를 공부할 때 GoF와 동시에 『Design Patterns Smalltalk Companion』을 필수적으로 읽기를 권합니다. 두 권은 말하자면 양날개입니다. 하나는 정적언어로 구현되었고(간간이 스몰토크 구현이 있긴 합니다), 다른 하나는 동적언어로 구현되어 있습니다. 언어와 패턴의 고리를 느슨하게 하고, 패턴을 여러 관점에서 신선하게 볼 수 있는 계기가 될 것입니다. 또, 한 쪽을 보고 이해가 잘 되지 않을 때 다른 쪽을 보면 쉽게 이해됩니다. 서로 상보적인 것이죠.

패턴도 결국 '문제해결'을 위한 한 가지 방편에 지나지 않습니다. 주변에서 "이 경우에는 무조건 이 패턴을 써야 합니다"하고 생떼를 쓰는 사람을 보면 씁쓸한 기분을 감출 수 없습니다.


디자인패턴 추천서
디자인패턴 책 중에 중요한 서적을 몇 권 소개하겠습니다.

◆『Design Patterns Explained』(Shalloway, Trott): 최근 DP 입문서로 급부상하고 있는 명저
◆『Design Patterns Java Workbook』(Steven John Metsker): DPE 다음으로 볼만한 책으로 쏟아져 나오는 시중의 조악한 자바 패턴 책들과는 엄연히 다르다. 워크북 형식을 채용해서 연습문제를 풀고 뒷부분의 답과 대조해 볼 수 있는 등 독학자가 공부하기에 좋다.
◆『Refactoring』(Martin Fowler): DP 공부 이전에 봐서 문제의식 형성하기(망치를 들면 모든 것이 못으로 보이는 오류 탈피)
◆『Design Patterns』: 바이블.
◆『Design Patterns Smalltalk Companion』: GoF가 오른쪽 날개라면 DPSC는 왼쪽 날개
◆『Pattern Hatching』(John Vlissides): DP 심화학습. 얇지만 밀도 높은 책.
◆『Smalltalk Best Practice Patterns』(Kent Beck): 마이크로 패턴. 개발자의 탈무드. 감동의 연속.
◆『Pattern Languages of Program Design』 1,2,3,4: 패턴 컨퍼런스 논문 모음집으로 대부분은 인터넷에서 구할 수 있음
◆『Pattern-Oriented Software Architecture』 1,2: 아키텍처 패턴 모음. 2권은 네트워크 애플리케이션의 아키텍처 모음.
◆『Concurrent Programming in Java』(Doug Lea): 컨커런트 프로그래밍에 대한 최고의 서적.
◆『Patterns of Software』(Richard Gabriel): 패턴에 관한 중요한 에세이 모음.
◆『Analysis Patterns』(Martin Fowler): 비즈니스 분석 패턴 목록. 비즈니스 애플리케이션 개발자에게 많은 도움이 됨.
◆『A Timeless Way of Building』(Christopher Alexander): 프로그래머들이 가장 많이 본 건축 서적. 패턴의 철학적·이론적 배경. '구약'('신약'은 올해 안에 출간 예정인 동저자의 『The Nature of Order』).
◆『A Pattern Language』(Christopher Alexander): 알렉산더의 건축 패턴 모음집.
◆『Problem Frames』(Michael Jackson): DP의 해결(solution) 지향식의 문제점과 극복 방안으로서의 문제 지향식 방법. 마이클 잭슨은 요구 사항 분석 쪽에서 동명의 가수만큼이나 유명.

DP를 처음 공부한다면, DPE와 DPJW를 RF와 함께 보면서 앞서의 두 권을 RF적으로 독해해 나가기를 권합니다(하버드 대학의 뚜웨이밍 교수는 요즘 칸트를 유교적으로 독해하고 있다고 합니다. 하나의 책을 다른 각도에서 독해하는 것, 여기서 배우는 것이 많습니다). 이게 된 후에는 GoF와 DPSC를 함께 볼 수 있습니다. 양자는 상호 보완적인 면이 강합니다. 이쯤 되어 SBPP를 보면 상당히 충격을 받을 수 있습니다. 스스로가 생각하기에 코딩 경험이 많다면 다른 DP 책 이전에 SBPP를 먼저 봐도 좋습니다.

이 정도의 책을 봤다면 POSA와 PLOPD 등에서 자신이 관심이 가는 패턴들을 찾아 읽는 것이 좋습니다. 그리고 동시에 알렉산더의 원저들을 꼭 읽기를 권합니다. 가브리엘의 책이 알렉산더의 사상 이해에 많은 도움이 될 것입니다.

패턴 공부를 해나가면서 남을 가르치는 것이 공부에 많은 도움이 됩니다(사실 자바 패턴 책 중에 어떤 것은 "내가 패턴을 처음 공부하면서 같이 쓴 것이다"라고 저자가 고백한 것도 있습니다). 보이스카웃에서는 보통 다음 과정을 통해 뭔가를 '학습'하게 한다고 합니다. 처음은 어떻게 하는지를 보여주고, 다음은 스스로 그것을 해보게 하고, 다음으로 그걸 남에게 가르치게 합니다. 이 때 중요한 것은 상대가 이해하지 못 하면 그 이유를 자기 자신에게서 찾는 것이 나에게 더 이득이 된다는 것입니다. "내가 설명을 잘못 했군"하고 생각하는 것이죠. 그러면 다음번에는 설명을 좀더 잘 할 수 있게 되고, 동시에 자기의 이해도 더욱 명료해지게 됩니다. 저는 'OOP 개념을 한 시간 만에 가르치기'나 '특정 언어 문법을 한 시간 만에 가르치기' 등을 하나의 도전으로 생각하고 즐깁니다. 가르치면서 동시에 배운다는 것은 정말 놀라운 경험입니다.

익스트림 프로그래밍 학습에서의 문제
앞의 경우와 비슷합니다. 익스트림 프로그래밍을 공부하는 사람들은 실제로 행해보지 않고 책만 들여다보면 안 됩니다. 그렇다고 책이 중요하지 않다는 말은 아닙니다. 하지만 자전거 타기는 자기 몸으로 직접 굴려봐야 합니다.

게다가 켄트 벡 스스로가 『XP Explained』를 만약 다시 쓴다면 뜯어고치고 싶은 부분이 상당히 된다고 말하는 것을 봐도 알 수 있듯이 초기 XP 이후 바뀌고 보완된 점이 상당수 있습니다. 따라서 책만으로 XP를 공부하기는 힘듭니다. 지금은 책 속의 XP가 사람들의 머리 속 XP에 한참 뒤쳐져 있습니다.

어찌 되었든 XP에는 무술이나 춤, 혹은 악기 연주 등과 유사한 면이 많습니다. 따라서 글을 보고 그것을 익히기는 쉽지 않습니다. 그나마 메일링 리스트 같은 '대화'를 보면 훨씬 더 많은 것을 얻을 수 있기는 하지만, 태권도 정권 찌르기를 말로 설명하는 것이 불가능에 가깝듯이 XP를 언어를 통해 익히기는 정말 어렵습니다. 우리의 언어는 너무도 성글은 미디어입니다(XP는 매 초, 매 순간 벌어지는 '일상적' 장면의 연속이 매우 중요합니다).

익스트림 프로그래밍 공부
XP를 이해하려면 다음 기본 자료에 대한 이해가 우선해야 합니다(본지 2001년 12월호 「허실문답 XP 강화」 참조).

◆『XP Explained』(Kent Beck): XP 선언서
◆『XP Installed』(Ron Jeffries et al): C3 프로젝트에 적용한 예, 얻은 교훈 등
◆『Planning XP』(Kent Beck, Martin Fowler): 계획 부분 설명(관리자, 코치용)
◆『Refactoring』(Martin Fowler): 리팩토링에 대한 최고의 책
◆『XP Applied』: 유즈넷과 메일링 리스트의 논의 등 최근 자료를 반영
◆『XP Explored』: 가장 쉽고 구체적인 XP 안내서


이 중에서 XPI나 XPX를 먼저 권합니다. XPE는 좀 추상적인 서술이 많아서 봐도 느낌이 별로 없을 수 있습니다(2001년 본지 11월호에 제가 쓴 리뷰 참고). 여유가 되면 다음 자료를 더 참고합니다.

◆『The Timeless Way of Building』: 패턴 운동을 일으킨 알렉산더의 저작. 현장 고객(On-site Customer), 점진 성장(Piecemeal Growth), 소통(Communication) 등의 아이디어가 여기에서 왔음.
◆『XP in Practice』(Robert C. Martin 외): 두세 사람이 짧은 기간 동안 간단한 프로젝트를 XP로 진행한 것을 기록. 자바 사용(중요한 문헌은 아님).
◆『XP Examined』: XP 컨퍼런스에 발표된 논문 모음
◆『Peopleware』(Tom DeMarco): 개발에 있어 인간 중심적 시각의 고전
◆『Adaptive Software Development』(Jim Highsmith): 복잡계 이론을 개발에 적용. 졸트상 수상.
◆『Surviving Object-Oriented Projects』(Alistair Cockburn): 얇고 포괄적인 OO 프로젝트 가이드라인
◆『Software Project Survival Guide』(Steve McConnell): 조금 더 전통적인 SE 시각.
◆『The Psychology of Computer Programming』(Gerald M. Weinberg): 프로그래밍에 심리학을 적용한 고전. 코드 공유와 짝 프로그래밍에 필수인 비자아적 프로그래밍(Egoless Programming)이 여기서 나왔다.
◆『Agile Software Development』(Alistair Cockburn): 전반적 애자일 방법론에 대한 개론서
◆『Software Craftsmanship』(Pete McBreen): 장인으로서의 새로운 프로그래머 상
◆『Agile Software Development with SCRUM』(Schwaber Ken): 최근 확장성(Scalability)을 위해 XP+SCRUM의 시도가 애자일 쪽의 큰 화두임.
◆『A Practical Guide to eXtreme Programming』(David Astels 외): 저자들이 직접 참여한 프로젝트를 따라가 보면서 배움. 자바로 구현. XPP보다는 스케일이 큼.
◆『Agile Modeling』(Scott Ambler): 애자일 쪽에서 모델링이 무시되는 느낌이 있을 수 있는데, 그쪽으로 깊게 천착한 사람이 앰블러임.
◆『Agile Software Development Ecosystems』(Jim Highsmith): 각각의 애자일 방법론에 대한 소개와 동시에 각 방법론의 대표자들 인터뷰가 백미.
◆『Test Driven Development』(Kent Beck): 곧(아마 올해 내에) 출간 예정인 최초의 TDD 서적. TDD를 모르면 XP도 모르는 것(TDD를 실제 적용하려면 적어도 반년 정도는 계속 훈련해야 함)
◆IEEE Software/Computer, CACM, Software Development Magazine 등에 실린 기사
◆『XP Conference, XP Universe 등의 논문들(특히 최근 것들)
◆유즈넷, 메일링 리스트, 오리지널 위키(http://c2.com)의 논의들

특히 유즈넷, 메일링 리스트, 오리지널 위키는 늘 가까이 하고 있어야 합니다. 이 세 곳을 살필 때, 특히 다음 사람들의 글은 꼭 읽어보고 항상 레이더를 열어두면 좋습니다(이 외에도 개발 경력 10년, 20년이 넘는 짱짱한 사람이 많으므로 눈 여겨 관찰하세요. 모든 글을 읽는 것은 무리이므로 그들의 대화를 일차적으로 읽어야 합니다).

켄트 벡, 론 제프리즈(Ron Jeffries), 워드 커닝엄(Ward Cunningham), 앨리스테어 코번(Alistair Cockburn), 마틴 파울러, 로버트 마틴 혹은 엉클 밥(Robert C. Martin aka Uncle Bob), 마이클 페더즈(Michael Feathers), 켄 아우어(Ken Auer), 윌리엄 웨이크(William Wake), 로이 밀러(Roy Miller), 데이브 토마스(Dave Thomas), 앤디 헌트(Andy Hunt), 랄프 존슨, 스카트 앰블러(Scott Ambler), 짐 하이스미스(Jim Highsmith), 조슈아 커리프스키(Joshua Kerievsky), 로렌트 보사빗(Laurent Bossavit), 존 브루어(John Brewer) 등

이런 자료들 외에, 기회가 된다면 주변에서 XP를 직접 사용하는 곳을 방문해서 하루만 같이 생활해 보기를 권합니다. 반년 공부를 앞당길 수 있습니다. 제가 공부할 때는 주변에 XP를 아는 사람이 없어서 혼자 공부했는데, 그것에 비해 XP를 직접 사용하는 상황에 처한 사람은 (제가 억울하리만큼) 더 적은 노력으로 몇 배 이상 빨리 몸에 익히는 것 같았습니다.

이게 힘들면 같이 공부하는 방법이 있습니다(앞서 언급된 스터디 그룹에 관한 패턴 참고). 이 때 같이 책을 공부하거나 하는 것은 시간 낭비가 많습니다. 차라리 공부는 미리 다 해오고 만나서 토론을 하거나 아니면 직접 실험을 해보는 것이 훨씬 좋습니다. 두 사람 당 한 대의 컴퓨터와 커대란 화이트보드를 옆에 두고 말이죠. 제 경우 스터디 팀과 함께 저녁 시간마다 가상 XP 프로젝트를 많이 진행했고, 짤막짤막하게 프로그래밍 세션도 많이 가졌습니다. 나중에 회사에서 직접 XP를 사용할 때 많은 도움이 되었습니다.

Refactor Me
제가 하고 싶은 말은 더 있지만 이 글은 일단 여기서 끝이 납니다. 서두에서 말씀드렸듯이 애초 쓰려던 '일반론'은 생략하고, 대신 독자들의 몫으로 남겨두려 합니다. 이 글 자체가 여러분의 리팩토링 수련의 연장(延長)이 되었으면 하는 바램입니다. 이 글과 함께 실생활에서 직접 실험을 해보면서 - 이 때 욕심 부리지 않고 한 가지씩 지긋이 해보는 느긋함과 음미의 정신이 필요할지도 모르겠습니다 - 자신의 경험을 축적해 나가고, 동시에 이 글을 적절히 리팩토링해서 자신만의 패턴을 차근히 만들어 나가길 바랍니다. 그렇습니다. 리팩토링은 대상에 대한 이해가 깊고 경험이 많을수록 더 잘할 수 있습니다.

이 글에 소개된 제 공부론은 어찌 보면 상당히 진부해 보이기도 할 것입니다. 하지만 저는 이런 상식적이고 일상적이며 심지어는 소소해 보이는 것들에서 많은 감동을 받아왔습니다. 이 글도 사실 제 감동의 개인사입니다. 저는 "만약 오늘 어떤 것에라도 감동한 것이 없었다면, 오늘은 뭔가 잘못 산 것이다"라는 신조를 갖고 있습니다. 그것이 컴퓨터이건 대화이건 상관없이 말이죠. 저는 날마다 감동하며 살려고 노력합니다. 그러나 이 감동에 뭔가 꼭 대단한 것이 필요한 것은 아닙니다. 저는 오히려 감동 받기 위해 스스로 대단해져야 할 필요를 느끼기도 합니다. '감동'이라는 것은 주어지는 것이 아닙니다. 나와 타자가 공조하여 만드는 대화입니다.

감동해야 체득할 수 있다고 생각합니다. 그리고 이 감동은 개인적 삶 속에서 자기가, 자신의 몸으로, 직접 얻는 것입니다. 工夫 열심히 합시다.

-출처 : www.ehclub.net


[출처] http://najsulman.tistory.com/
Posted by 모과이IT
,

프로그래머 경력 3년차, 이제 어디로 갈까? PC/개발

2003/11/13 02:36

프로그래머 경력 3년차, 이제 어디로 갈까?

35세 정년 과감하게 뛰어 넘는
경력 관리 해법 찾기

지금 다니는 직장에 몇 개월째 근무하고 있는가? IT 종사자들의 근무 주기가 점점 짧아지고 개발자들도 한 분야만 알아서는 경력 관리를 하기가 힘들어졌다. 평생 직장 개념은 이미 사라진지 오래. 프로그래머라는 직업을 갖고 언제까지 일할 수 있을지 자문해 보자. 프로그래머 정년이 35세라는 말이 공공연히 나돌면서 이제는 자신의 경력을 꼼꼼하게 관리해야 할 때가 왔다. 목표를 확실히 세우고 50세가 되어 있을 자신을 그려 보자. 
글·김영미 기자 kelly@pserang.co.kr   사진·권현진 기자 guswls 337@pserang.co.kr


중소 IT 업체에 근무하는 A씨는 요즘 아침에 출근해 컴퓨터를 켜면 암호로 잠궈 둔 이력서를 연다. 자신의 경력기술서를 주욱 보다가 한숨짓는 K씨. 프로그래밍이 좋아 IT 업계로 뛰어든지 어언 3년째, 회사에선 주임으로 승진도 했고 자리도 잡았다. 그동안 갖가지 프로젝트에 밀려 일주일에 서너 번은 밤을 새고 까다로운 클라이언트사의 비위도 맞춰 가면서 프로그래머 경력을 쌓아 왔지만 요즘은 왠지 모르게 자괴감이 밀려 온다.
프로그래머 정년 35세라는 주변의 이야기들을 차치하고서라도 지금하고 있는 업무를 언제까지 할 수 있을지 의문이기 때문이다. 실력이 뛰어난 후배들은 계속 밀려들어 오고 학교다닐 때처럼 계속 공부를 한다는 것도 심적으로 부담이다. K씨는 회사를 계속 다니고는 있지만 앞으로 어떻게 경력을 관리해야 할지 심각하게 고민 중이다.

프로그래머는 왜 이직율이 높을까?
취업 사이트인 인쿠르트의 통계에 따르면 IT 종사자의 이직 주기는 상당히 짧은 것으로 나타났다. 인크루트( www.incruit.com)가 1,982명의 IT 재직자를 대상으로 이직 동향에 대해 설문 조사를 실시한 결과 1~2년마다 회사를 옮기는 종사자가 38.4퍼센트(761명)에 달했다. 5년 이상 주기로 회사를 옮기는 종사자는 4.7퍼센트(94명)에 불과한 것으로 나타났다. 이직시 10~20퍼센트의 연봉을 올려 받는 것으로 드러났다.
‘2~3년마다 이직한다’는 대답은 31.4퍼센트, 3~5년 단위로 이직하는 경우는 13.6퍼센트, 1년 이하 주기로 이직하는 경우는 11.9퍼센트 등이었다. 전체 이직 주기로 보면, 1~3년마다 이직하는 비율이 전체의 69.8퍼센트에 달해 대다수 IT 종사자들이 1~3년 내에 다른 직장으로 옮기는 것으로 조사됐다.
이직 사유로는, ‘회사의 비전이 없기 때문’이라고 답한 응답자가 33.5퍼센트(664명)로 가장 많았고, 그 뒤를 이어 ‘자기 계발을 위해 이직한다’가 33.1퍼센트(655명)에 달해 직장 생활에서 회사 비전과 개인의 발전 가능성을 가장 중시하는 것으로 드러났다.
그렇다면 프로그래머들은 왜 이직을 자주 하는 것일까? 물론 고용 불안에서 오는 구직자들의 자발적 이직도 있지만 거꾸로 이야기하면 그만큼 기회가 많기 때문이라고 해석할 수도 있다.
잡서치코리아의 이기대 사장은 국내 2~3년차 프로그래머들의 문제점을 IT 산업 계층 구조에서 기인한다고 설명한다. 그는 “국내 IT 업체들은 산업 자체가 영세한데다 SI 업체가 많아야 프로그래머가 대접을 받는데 SM(시스템 운영) 업체들이 대부분이다. IT업체들이 2차, 3차로 하청을 주는데 이 하청 업체에 2~3년차 프로그래머들이 몰려 있다. 따라서 업무 환경도 열악하고 자기 개발할 여유도 없이 경력을 쌓게 된다. 노가다성 코딩 작업만 하다보니 자신의 능력을 업그레이드할 기회가 없어 슬럼프에 빠진다”고 말한다.

 

 

프로그래머 10년, 관리자 10년
국내 IT 환경에서 개발자들이 전산 업무를 10년 정도 하면 관리자로 승진하고 더 이상 개발자로 일하지 않는다. 이는 본인의 선택적인 측면이 많지만 장유유서(長幼有序)로 대변되는 사회분위기와 무관하지 않다. 또 30대 중반이 되면 아이들이 커가고 밤새고 일하는 것이 즐겁지 않다. 관리하고 싶은 마음이 생기는 것이다. 여기에서 프로그래머 ‘35세 정년’이라는 말이 나오기 시작한다.
개발자로서 수명이 다한 인력들은 다른 분야로 전직하거나 개발자들을 관리하는 매니저로 승진하는 것이 통상적인 국내 프로그래머들의 경력 지도이다. 일부 IT 컨설턴트라고 하는 개발자와 관리자의 중간 단계의 직종으로 자리를 옮기는 경우도 있지만 문과 출신이면서 IT 기업 근무 경력이 있고 경영학 석사 등 각종 학위로 무장한 이들에 밀려 빛을 보지 못하는 경우가 많다. 사정이 이렇다보니 서른만 넘겨도 의욕을 상실하는 프로그래머들도 생겨난다. 그렇다면 경력 관리는 언제, 어떻게 시작해야하는 것일까. 헤드헌팅 포털 HP존에 따르면 헤드헌터들은 이직 희망자들의 가장 큰 문제점을 경력 관리 미흡과 조직 생활 부적응을 꼽았다.
전문가들은 초보 개발자 시절부터 자신의 목표를 명확히 해야한다고 말한다. 삼성멀티캠퍼스 교육사업팀 오형석 과장은 “자신이 제너럴리스트로 성장할 것인지 스페셜리스트로 성장할 것인지에 대해서는 확실한 주관이 있어야 한다”고 말한다. 경력 관리에 기술적인 접근이 필요하다는 것.
계속 프로그래밍을 할 것인지, 개발 지식을 토대로 기술 영업을 할 것인지, 프로젝트 매니저가 될 것인지 2~3년차에 결정해야 한다는 인크루트 김현정 IT 담당 부장은 “취업 시장에서는 프로그래머의 수명은 약 20년이다. 이 중 순수하게 프로그래밍(코딩) 업무만으로 파악하면 약 10년 정도이다. 이는 다른 산업군에 비하면 상당히 길다. 프로그래밍 분야 즉, 코딩 작업을 할 수 있는 기간이 10년이라는 이유는 IT 트렌드가 끊임없이 바뀌고 있고 개발 언어 또한 계속 교체되기 때문”이라고 쐐기를 박는다. 그러나 이 기간 동안 프로그래머 업무에 충실하고 경력 관리를 제대로 하면 길을 얼마든지 있다.  
     
변화에 알맞는 경력 지도 그려야
올해 31세인 5년차 프로그래머 장윤기씨의 경우 현재 네 번째 직장에 다니고 있다. 이 중 1년씩 일한 직장이 2곳, 3년 동안 일한 업체를 거처 포스데이타라는 SI 업체에 안착했다. 그는 중소 IT 업체에서 경력을 쌓고 대기업으로 경력을 업그레이드 했다. 올해 30세인 권영민 시큐어소프트 과장의 경우 병역특례 경력을 합하면 프로그래머 경력만 7년째다. 비주얼 C에서 자바로 업그레이드하고 프로그래머로써 경력을 쌓다가 경력이 10년쯤되면 독자적인 프로젝트 매니저로 승부를 낼 생각이다.   
  프로그래머의 일반적인 경력 지도는 약 10여 년의 프로그래머 생활을 거친 후 기술 영업을 하거나 전산실 매니저가 되거나 프로젝트 매니저로 성장하는 방안을 들 수 있다. 기술적인 백그라운드가 있고 전문성이 있기 때문에 가능하다.
  이 중 프로그래머 실력을 기반으로 성장하고 싶은 개발자들은 프로젝트 매니저에 관심을 가져보자. 급변하는 IT 트렌드를 봤을 때 개발자가 2~3가지 프로그래밍 언어까지는 학습이 가능하지만 그 이상은 어려운 것이 현실이다. 메인프레임을 사용하던 개발자가 C/S 환경에서 웹으로 전환하기가 사실상 힘들기 때문이다.
프로젝트 매니저는 프로젝트 일정을 관리하고 전산 자원을 배분하여 프로젝트를 효율적으로 이끄는 역할을 하는 핵심 인력이다. 자신이 수행한 프로젝트로 경력을 인정받는 프로그래머는 금융이나 통신과 같은 산업 분야 별로 경력을 쌓거나 원가, 회계, 재무와 같은 직무별 커리어를 쌓는 것이 경력 관리에 도움이 된다.  
분야별 전문 지식을 토대로 관리 능력을 쌓아가는 것이 프로그래머 경력을 극대화시키는 방법 중 하나이다. 국내의 경우 ‘관리자=People Management’로 인식되는 경향이 있으나  점차 바뀌어가고 있다. 이는 우리나라 전산인들이 프로젝트 관리를 제대로 하지 않는다는 반성에서 비롯된다. 잡서치코리아 이기대 사장은 “프로그래머로 경력을 쌓고 관리자가 되면 피플 관리가 아닌 프로젝트 관리로 포지셔닝을 해야 한다. 건별 계약이든 기업의 전산 관리자로 있든 경력이 어느 정도 쌓이면 PM(Project Manager)역할을 할 수 있어야 하는데 국내에는 이러한 인력이 턱없이 부족하다. SI 인력도 적을 뿐더러 프로젝트 관리 능력이 떨어져 결과적으로 IT 결과물의 퍼포먼스가 떨어진다”고 말한다.
실제로 30대 중반의 프로젝트 매니저를 헤드헌팅업체에서 많이 찾는데 국내에서 찾기 힘들다는 것이 전문가들의 견해이다. 전반적인 기술이나 프로젝트에 대한 관리 능력을 갖춘 전문가가 시급하다는 것. 프로그래머는 많아도 관리자는 드문 것이 국내 전산 환경의 현 주소이다.
경력을 쌓아 교육 분야로 진출하는 것도 바람직하다. IT 교육 전문가가 턱없이 부족하기 때문이다. 대학이나 기업에서도 IT 분야를 가르칠 사람이 없어 애를 먹고 있다.
얼마 전 한 중견 IT 업체는 최근 호주 소프트웨어 회사의 수석 엔지니어를 초빙해 3일간 프로그램 교육을 실시했다. 강사료는 1,000만 원. 국내에서는 이같은 인력을 찾을 수 없었다는 업체 측의 전언이다. 노동연구원 조사 결과에서도 고급 인력이 절대적으로 부족한 직종 1위는 IT 교육 전문가이다. 지난해 보고서에 따르면 대학과 학원, 직업 훈련 기관의 부족한 IT 교원은 1,374명이었다. 1년차 개발자 100명 중 5년이 지나고 남는 개발자가 15명밖에 안된다는 말이 이를 반증해 준다.

조직 내 커뮤니케이션·리포팅 능력 중요
일반적으로 프로그래머의 특성을 살펴 보면 외곬수에 커뮤니케이션 능력이 약하다는 평가를 내리는 사람들이 많다. 한 대기업의 마케팅 부서 이사는 “자신의 의사를 적절히 표현하지 못하는 프로그래머들이 많다. 회의 시간에 한 마디도 못하거나 요점없는 이야기로 시간을 낭비하고 대답을 못하거나 의견을 제시하면 무조건 할 수 없다고 말하는 개발자들이 많아 현업에서 불만”이라고 이야기한다. 어려운 프로그래밍 서적만 보다보니 커뮤니케이션 능력이 상대적으로 떨어진다는 것.
인크루트 김현정 부장은 “프로그래머들은 업무 성향이 오기와 비슷한 독특한 특성이 있다. 커뮤니케이션 활동이 폐쇄적인 데다 오픈마인드를 갖고 있지 않다”고 평가한다. “IT 조직은 서비스 조직이라는 생각을 갖고 있어야 한다. 지원 조직이고 현업을 서비스하는 조직이라는 마인드를 갖고 있어야 한다. 프로그래머가 현업과의 커뮤니케이션에서 융통성을 발휘하고 서포팅을 잘하면 인정받기도 쉽다”고 조언한다. 그러나 프로그래머들이 현업을 이해가기가 만만치 않은 것이 현실이라고 말한다.
실제로 프로그래머들 중 상당수는 상사와의 갈등이나 동료와의 불협화음으로 이직을 하려는 개발자도 많다. 소규모 IT 기업에서 근무하던 개발자 B씨는 회사가 급성장 하면서 조직이 확대되어 개발 인력이 수십 명으로 불어났으나 이에 적응하지 못하고 실직한 경우다. 이전의 가족같은 분위기가 사라진 데다 새로 영입된 팀장의 업무 스타일에 적응하지 못한 것. 조직 내 커뮤니케이션이 프로그래머에게 큰 문제로 나타난다는 것이 전문가들의 의견이다. 이기대 사장은 “커뮤니케이션을 잘하는 가장 손쉬운 방법은 상대방이 하는 말을 주의 깊게 듣고 있다가 그 방식으로 그대로 설명하는 것”이라고 조언한다. 
프로그래머들에게 또 하나의 벽은 글쓰기와 프리젠테이션 능력이다. 자신의 생각을 표현해 내는 과정에서 타 부서인들의 이해를 구하려는 노력이 필요하다는 것. 권영민 시큐어소프트 과장은 “개발자들이 스케줄 관리와 다큐멘테이션에 약하다. 프리젠테이션 능력과 글쓰기 노력을 병행해야 한다. 자신이 가진 기술만큼 중요한 것이 생각을 표현해 내는 능력”이라고 말한다. 
 
장기계획 세우고 목표 확실히 설정
초보 개발자 시절부터 장래에 대한 계획을 확실히 세우고 꾸준히 계단을 올라 가면 더할 나위 없겠지만 안타깝게도 경력 관리에 대해 여유를 갖게 되는 것은 시간이 한참 흐른 후이다. 이번 기회에 다시금 자신을 되돌아보는 계기를 만들어 보자. 
여러 가지 이유 때문에 실직했다면 공백을 최우선으로 줄이는 것이 경력 관리에 흠을 없애는 방법이다. 무엇보다 공백 기간이 6개월 이상 장기화되지 않도록 노력해야 한다. 프로그래머에게 있어 반년 이상의 공백은 일을 안한다는 의미가 아니라 직무 능력이 떨어짐을 의미하기 때문이다. 따라서 실업이 장기화될 가능성이 있을 때는 차라리 직장 눈높이를 낮춰서라도 재직 상태를 유지하는 것이 좋다. 불가피하게 공백기를 가졌다면 업무의 연속성을 가져야 한다. 아르바이트를 하거나 커뮤니티 활동, 연구, 단기 프로젝트 활동을 할 수 있도록 노력해야 한다.
특히 유의할 점은 일을 놓고 싶더라도 목표없이 그만 둬서는 안된다. 업무를 진행하면서 주기적으로 휴식을 취할 수 있는 공간을 만들어야 한다. 또, 취업 정보를 꾸준히 받을 수 있는 상황인지 살펴 봐야 한다. 퇴직 준비를 하면서 정보 검색을 하지 않았다면 반성해야 한다. 프로젝트 매니저로서 대우를 받을 수 있는 경력은 5년차 이상일 때 옮기는 것이 좋다. 프로젝트 경험 많은 7년차가 가장 좋다.
슬럼프에 빠졌다면 보직이나 근무지를 바꿔 같은 일이라도 새로운 환경에서 일하도록 하는 것이 좋다. 업무와 관련된 교육 기회를 찾아 그간의 관점을 바꿀 수 있는 신선한 주제를 제공하여 분위기를 전환하는 것도 좋은 방법이다. 

Posted by 모과이IT
,

프로그래머 경력 3년차, 이제 어디로 갈까?

35세 정년 과감하게 뛰어 넘는 경력 관리 해법 찾기

지금 다니는 직장에 몇 개월째 근무하고 있는가? IT 종사자들의 근무 주기가 점점 짧아지고 개발자들도 한 분야만 알아서는 경력 관리를 하기가 힘들어졌다. 평생 직장 개념은 이미 사라진지 오래. 프로그래머라는 직업을 갖고 언제까지 일할 수 있을지 자문해 보자. 프로그래머 정년이 35세라는 말이 공공연히 나돌면서 이제는 자신의 경력을 꼼꼼하게 관리해야 할 때가 왔다. 목표를 확실히 세우고 50세가 되어 있을 자신을 그려 보자.

중소 IT 업체에 근무하는 A씨는 요즘 아침에 출근해 컴퓨터를 켜면 암호로 잠궈 둔 이력서를 연다. 자신의 경력기술서를 주욱 보다가 한숨짓는 K씨. 프로그래밍이 좋아 IT 업계로 뛰어든지 어언 3년째, 회사에선 주임으로 승진도 했고 자리도 잡았다. 그동안 갖가지 프로젝트에 밀려 일주일에 서너 번은 밤을 새고 까다로운 클라이언트사의 비위도 맞춰 가면서 프로그래머 경력을 쌓아 왔지만 요즘은 왠지 모르게 자괴감이 밀려 온다.
프로그래머 정년 35세라는 주변의 이야기들을 차치하고서라도 지금하고 있는 업무를 언제까지 할 수 있을지 의문이기 때문이다. 실력이 뛰어난 후배들은 계속 밀려들어 오고 학교다닐 때처럼 계속 공부를 한다는 것도 심적으로 부담이다. K씨는 회사를 계속 다니고는 있지만 앞으로 어떻게 경력을 관리해야 할지 심각하게 고민 중이다.

프로그래머는 왜 이직율이 높을까?

취업 사이트인 인쿠르트의 통계에 따르면 IT 종사자의 이직 주기는 상당히 짧은 것으로 나타났다. 인크루트( www.incruit.com)가 1,982명의 IT 재직자를 대상으로 이직 동향에 대해 설문 조사를 실시한 결과 1~2년마다 회사를 옮기는 종사자가 38.4퍼센트(761명)에 달했다. 5년 이상 주기로 회사를 옮기는 종사자는 4.7퍼센트(94명)에 불과한 것으로 나타났다. 이직시 10~20퍼센트의 연봉을 올려 받는 것으로 드러났다.
‘2~3년마다 이직한다’는 대답은 31.4퍼센트, 3~5년 단위로 이직하는 경우는 13.6퍼센트, 1년 이하 주기로 이직하는 경우는 11.9퍼센트 등이었다. 전체 이직 주기로 보면, 1~3년마다 이직하는 비율이 전체의 69.8퍼센트에 달해 대다수 IT 종사자들이 1~3년 내에 다른 직장으로 옮기는 것으로 조사됐다. 이직 사유로는, ‘회사의 비전이 없기 때문’이라고 답한 응답자가 33.5퍼센트(664명)로 가장 많았고, 그 뒤를 이어 ‘자기 계발을 위해 이직한다’가 33.1퍼센트(655명)에 달해 직장 생활에서 회사 비전과 개인의 발전 가능성을 가장 중시하는 것으로 드러났다.

그렇다면 프로그래머들은 왜 이직을 자주 하는 것일까? 물론 고용 불안에서 오는 구직자들의 자발적 이직도 있지만 거꾸로 이야기하면 그만큼 기회가 많기 때문이라고 해석할 수도 있다.
잡서치코리아의 이기대 사장은 국내 2~3년차 프로그래머들의 문제점을 IT 산업 계층 구조에서 기인한다고 설명한다. 그는 “국내 IT 업체들은 산업 자체가 영세한데다 SI 업체가 많아야 프로그래머가 대접을 받는데 SM(시스템 운영) 업체들이 대부분이다. IT업체들이 2차, 3차로 하청을 주는데 이 하청 업체에 2~3년차 프로그래머들이 몰려 있다. 따라서 업무 환경도 열악하고 자기 개발할 여유도 없이 경력을 쌓게 된다. 노가다성 코딩 작업만 하다보니 자신의 능력을 업그레이드할 기회가 없어 슬럼프에 빠진다”고 말한다.

프로그래머 10년, 관리자 10년
국내 IT 환경에서 개발자들이 전산 업무를 10년 정도 하면 관리자로 승진하고 더 이상 개발자로 일하지 않는다. 이는 본인의 선택적인 측면이 많지만 장유유서(長幼有序)로 대변되는 사회분위기와 무관하지 않다. 또 30대 중반이 되면 아이들이 커가고 밤새고 일하는 것이 즐겁지 않다. 관리하고 싶은 마음이 생기는 것이다. 여기에서 프로그래머 ‘35세 정년’이라는 말이 나오기 시작한다.

개발자로서 수명이 다한 인력들은 다른 분야로 전직하거나 개발자들을 관리하는 매니저로 승진하는 것이 통상적인 국내 프로그래머들의 경력 지도이다. 일부 IT 컨설턴트라고 하는 개발자와 관리자의 중간 단계의 직종으로 자리를 옮기는 경우도 있지만 문과 출신이면서 IT 기업 근무 경력이 있고 경영학 석사 등 각종 학위로 무장한 이들에 밀려 빛을 보지 못하는 경우가 많다. 사정이 이렇다보니 서른만 넘겨도 의욕을 상실하는 프로그래머들도 생겨난다. 그렇다면 경력 관리는 언제, 어떻게 시작해야하는 것일까. 헤드헌팅 포털 HP존에 따르면 헤드헌터들은 이직 희망자들의 가장 큰 문제점을 경력 관리 미흡과 조직 생활 부적응을 꼽았다.

전문가들은 초보 개발자 시절부터 자신의 목표를 명확히 해야한다고 말한다. 삼성멀티캠퍼스 교육사업팀 오형석 과장은 “자신이 제너럴리스트로 성장할 것인지 스페셜리스트로 성장할 것인지에 대해서는 확실한 주관이 있어야 한다”고 말한다. 경력 관리에 기술적인 접근이 필요하다는 것.

계속 프로그래밍을 할 것인지, 개발 지식을 토대로 기술 영업을 할 것인지, 프로젝트 매니저가 될 것인지 2~3년차에 결정해야 한다는 인크루트 김현정 IT 담당 부장은 “취업 시장에서는 프로그래머의 수명은 약 20년이다. 이 중 순수하게 프로그래밍(코딩) 업무만으로 파악하면 약 10년 정도이다. 이는 다른 산업군에 비하면 상당히 길다. 프로그래밍 분야 즉, 코딩 작업을 할 수 있는 기간이 10년이라는 이유는 IT 트렌드가 끊임없이 바뀌고 있고 개발 언어 또한 계속 교체되기 때문”이라고 쐐기를 박는다. 그러나 이 기간 동안 프로그래머 업무에 충실하고 경력 관리를 제대로 하면 길을 얼마든지 있다.

변화에 알맞는 경력 지도 그려야
올해 31세인 5년차 프로그래머 장윤기씨의 경우 현재 네 번째 직장에 다니고 있다. 이 중 1년씩 일한 직장이 2곳, 3년 동안 일한 업체를 거처 포스데이타라는 SI 업체에 안착했다. 그는 중소 IT 업체에서 경력을 쌓고 대기업으로 경력을 업그레이드 했다. 올해 30세인 권영민 시큐어소프트 과장의 경우 병역특례 경력을 합하면 프로그래머 경력만 7년째다. 비주얼 C에서 자바로 업그레이드하고 프로그래머로써 경력을 쌓다가 경력이 10년쯤되면 독자적인 프로젝트 매니저로 승부를 낼 생각이다.

프로그래머의 일반적인 경력 지도는 약 10여 년의 프로그래머 생활을 거친 후 기술 영업을 하거나 전산실 매니저가 되거나 프로젝트 매니저로 성장하는 방안을 들 수 있다. 기술적인 백그라운드가 있고 전문성이 있기 때문에 가능하다.

이 중 프로그래머 실력을 기반으로 성장하고 싶은 개발자들은 프로젝트 매니저에 관심을 가져보자. 급변하는 IT 트렌드를 봤을 때 개발자가 2~3가지 프로그래밍 언어까지는 학습이 가능하지만 그 이상은 어려운 것이 현실이다. 메인프레임을 사용하던 개발자가 C/S 환경에서 웹으로 전환하기가 사실상 힘들기 때문이다.

프로젝트 매니저는 프로젝트 일정을 관리하고 전산 자원을 배분하여 프로젝트를 효율적으로 이끄는 역할을 하는 핵심 인력이다. 자신이 수행한 프로젝트로 경력을 인정받는 프로그래머는 금융이나 통신과 같은 산업 분야 별로 경력을 쌓거나 원가, 회계, 재무와 같은 직무별 커리어를 쌓는 것이 경력 관리에 도움이 된다.

분야별 전문 지식을 토대로 관리 능력을 쌓아가는 것이 프로그래머 경력을 극대화시키는 방법 중 하나이다. 국내의 경우 ‘관리자=People Management’로 인식되는 경향이 있으나 점차 바뀌어가고 있다. 이는 우리나라 전산인들이 프로젝트 관리를 제대로 하지 않는다는 반성에서 비롯된다. 잡서치코리아 이기대 사장은 “프로그래머로 경력을 쌓고 관리자가 되면 피플 관리가 아닌 프로젝트 관리로 포지셔닝을 해야 한다. 건별 계약이든 기업의 전산 관리자로 있든 경력이 어느 정도 쌓이면 PM(Project Manager)역할을 할 수 있어야 하는데 국내에는 이러한 인력이 턱없이 부족하다. SI 인력도 적을 뿐더러 프로젝트 관리 능력이 떨어져 결과적으로 IT 결과물의 퍼포먼스가 떨어진다”고 말한다.

실제로 30대 중반의 프로젝트 매니저를 헤드헌팅업체에서 많이 찾는데 국내에서 찾기 힘들다는 것이 전문가들의 견해이다. 전반적인 기술이나 프로젝트에 대한 관리 능력을 갖춘 전문가가 시급하다는 것. 프로그래머는 많아도 관리자는 드문 것이 국내 전산 환경의 현 주소이다.

경력을 쌓아 교육 분야로 진출하는 것도 바람직하다. IT 교육 전문가가 턱없이 부족하기 때문이다. 대학이나 기업에서도 IT 분야를 가르칠 사람이 없어 애를 먹고 있다.

얼마 전 한 중견 IT 업체는 최근 호주 소프트웨어 회사의 수석 엔지니어를 초빙해 3일간 프로그램 교육을 실시했다. 강사료는 1,000만 원. 국내에서는 이같은 인력을 찾을 수 없었다는 업체 측의 전언이다. 노동연구원 조사 결과에서도 고급 인력이 절대적으로 부족한 직종 1위는 IT 교육 전문가이다. 지난해 보고서에 따르면 대학과 학원, 직업 훈련 기관의 부족한 IT 교원은 1,374명이었다. 1년차 개발자 100명 중 5년이 지나고 남는 개발자가 15명밖에 안된다는 말이 이를 반증해 준다.

조직 내 커뮤니케이션·리포팅 능력 중요
일반적으로 프로그래머의 특성을 살펴 보면 외곬수에 커뮤니케이션 능력이 약하다는 평가를 내리는 사람들이 많다. 한 대기업의 마케팅 부서 이사는 “자신의 의사를 적절히 표현하지 못하는 프로그래머들이 많다. 회의 시간에 한 마디도 못하거나 요점없는 이야기로 시간을 낭비하고 대답을 못하거나 의견을 제시하면 무조건 할 수 없다고 말하는 개발자들이 많아 현업에서 불만”이라고 이야기한다. 어려운 프로그래밍 서적만 보다보니 커뮤니케이션 능력이 상대적으로 떨어진다는 것.

인크루트 김현정 부장은 “프로그래머들은 업무 성향이 오기와 비슷한 독특한 특성이 있다. 커뮤니케이션 활동이 폐쇄적인 데다 오픈마인드를 갖고 있지 않다”고 평가한다. “IT 조직은 서비스 조직이라는 생각을 갖고 있어야 한다. 지원 조직이고 현업을 서비스하는 조직이라는 마인드를 갖고 있어야 한다. 프로그래머가 현업과의 커뮤니케이션에서 융통성을 발휘하고 서포팅을 잘하면 인정받기도 쉽다”고 조언한다. 그러나 프로그래머들이 현업을 이해가기가 만만치 않은 것이 현실이라고 말한다.

실제로 프로그래머들 중 상당수는 상사와의 갈등이나 동료와의 불협화음으로 이직을 하려는 개발자도 많다. 소규모 IT 기업에서 근무하던 개발자 B씨는 회사가 급성장 하면서 조직이 확대되어 개발 인력이 수십 명으로 불어났으나 이에 적응하지 못하고 실직한 경우다. 이전의 가족같은 분위기가 사라진 데다 새로 영입된 팀장의 업무 스타일에 적응하지 못한 것. 조직 내 커뮤니케이션이 프로그래머에게 큰 문제로 나타난다는 것이 전문가들의 의견이다. 이기대 사장은 “커뮤니케이션을 잘하는 가장 손쉬운 방법은 상대방이 하는 말을 주의 깊게 듣고 있다가 그 방식으로 그대로 설명하는 것”이라고 조언한다.

프로그래머들에게 또 하나의 벽은 글쓰기와 프리젠테이션 능력이다. 자신의 생각을 표현해 내는 과정에서 타 부서인들의 이해를 구하려는 노력이 필요하다는 것. 권영민 시큐어소프트 과장은 “개발자들이 스케줄 관리와 다큐멘테이션에 약하다. 프리젠테이션 능력과 글쓰기 노력을 병행해야 한다. 자신이 가진 기술만큼 중요한 것이 생각을 표현해 내는 능력”이라고 말한다.

장기계획 세우고 목표 확실히 설정
초보 개발자 시절부터 장래에 대한 계획을 확실히 세우고 꾸준히 계단을 올라 가면 더할 나위 없겠지만 안타깝게도 경력 관리에 대해 여유를 갖게 되는 것은 시간이 한참 흐른 후이다. 이번 기회에 다시금 자신을 되돌아보는 계기를 만들어 보자.

여러 가지 이유 때문에 실직했다면 공백을 최우선으로 줄이는 것이 경력 관리에 흠을 없애는 방법이다. 무엇보다 공백 기간이 6개월 이상 장기화되지 않도록 노력해야 한다. 프로그래머에게 있어 반년 이상의 공백은 일을 안한다는 의미가 아니라 직무 능력이 떨어짐을 의미하기 때문이다. 따라서 실업이 장기화될 가능성이 있을 때는 차라리 직장 눈높이를 낮춰서라도 재직 상태를 유지하는 것이 좋다. 불가피하게 공백기를 가졌다면 업무의 연속성을 가져야 한다. 아르바이트를 하거나 커뮤니티 활동, 연구, 단기 프로젝트 활동을 할 수 있도록 노력해야 한다.

특히 유의할 점은 일을 놓고 싶더라도 목표없이 그만 둬서는 안된다. 업무를 진행하면서 주기적으로 휴식을 취할 수 있는 공간을 만들어야 한다. 또, 취업 정보를 꾸준히 받을 수 있는 상황인지 살펴 봐야 한다. 퇴직 준비를 하면서 정보 검색을 하지 않았다면 반성해야 한다. 프로젝트 매니저로서 대우를 받을 수 있는 경력은 5년차 이상일 때 옮기는 것이 좋다. 프로젝트 경험 많은 7년차가 가장 좋다.

슬럼프에 빠졌다면 보직이나 근무지를 바꿔 같은 일이라도 새로운 환경에서 일하도록 하는 것이 좋다. 업무와 관련된 교육 기회를 찾아 그간의 관점을 바꿀 수 있는 신선한 주제를 제공하여 분위기를 전환하는 것도 좋은 방법이다.

Posted by 모과이IT
,

[출처] http://toby.epril.com/?p=418


작년 이맘 때쯤에 마소의 호랭이 정희용 편집장(그땐 정기자)의 압력으로 "개발고수 12인이 말하는 실전 노하우" 시리즈의 글을 하나 썼다. 글의 아이디어는 사실 정기자가 준 것이다. "나는 개발고수도 아니고 별 실전 노하우도 없다"고 저항을 했음에도, "큐브랑 개발과의 관계를 무조건 만들어 내서 글을 쓰라"고 계속 압박하는 바람에 맘 착한 나는 머리를 쥐어짜서 그동안 즐겨온 큐브와 역시 즐겨온 개발의 실력향상 관계를 만들어내야 했다. 막상 글을 쓰면서 생각해보니 역시 모든 원리는 다 비슷하다는 생각이 들었다. 재미삼아 읽어보면 나쁘지 않을 듯. 다른 것은 모르겠지만, 결론 - 고수편은 좀 진지하게 생각해온 것이다.


큐브 맞추기로 말하는 개발자 실력 향상 시나리오

소프트웨어 개발에는 끝이 없다는 말이 있다. 더 이상 수정할 필요가 없을 만큼 완벽하게 완성된 소프트웨어란 없다는 뜻이다. 마찬가지로 더 이상 실력향상이 필요 없을 만큼 완벽한 경지에 이른 개발자도 없다. 모든 개발자는 끊임없이 성장해야 한다. 하지만 모든 사람이 같은 속도와 성취도를 가지고 성장하지는 않는다. 효과적인 개발자의 실력향상과 성장에 대해 얘기해본다. 요즘 필자에게 취미를 묻는 사람이 있다면 필자는 주저 없이 ‘큐브 맞추기’라고 대답한다. 많은 사람들이 어릴 때 많이 가지고 놀았던 정육면체의 그 루빅스 큐브(Rubik’s Cube)이다. 큐브는 여섯 가지 색깔을 가진 총 26개의 블록을 이리 저리 회전시켜 모든 면의 색이 같아지도록 하는 간단한 놀이기구다. 기껏해야 6면을 가진 26개의 블록, 그중에서도 고정되어있는 가운데 6개를 제외한 20개의 블록을 움직이는 게임일 뿐이다. 하지만 큐브를 움직여 만들 수 있는 블록의 조합이 무려 43,252,003,274,489,856,000 가지나 된다는 사실을 아는지? 무려 4,000경이나 되는 조합의 수가 나온다는 것이다. 

그 많은 조합을 가진 다양한 방식으로 섞인 큐브를 모든 면이 같은 색을 가지도록 조합하는 것은 그리 간단한 일이 아니다. 그래서 많은 사람들이 큐브를 도전했다가 한 면 정도의 색을 맞춘 뒤 금방 포기하고 만다.알고 보면 큐브의 세계는 나름 심오하다. 그 조합의 수만큼 다양한 색을 맞추는 솔루션들이 있다. 많은 수학자들이 큐브에 담긴 수학적 원리를 연구하고 있기도 하다. 큐브를 자기만의 방식으로 더 빨리 또는 더 적은 횟수로 맞추는 대회가 우리나라를 비롯해 전 세계에서 매년 열리고 있다. 큐브관련 동호회와 카페에서 수만 명의 회원이 활발한 활동을 하고 있다. 최근 몇 년 사이에 불어 닥친 복고 게임의 열풍 덕분에 오래도록 잠잠했던 큐브의 인기가 전 세계를 다시금 강타했고, 급기야 지난해에는 아마존의 게임 베스트셀러 부문 1위를 차지하는 사건을 일으키기도 했다. 개발 노하우를 이야기해야 하는 이 코너에서 필자는 왜 갑자기 큐브 얘기를 하는 걸까? 필자가 보기에 큐브의 실력을 쌓아나가는 것과 개발자의 실력 향상 과정이 무척이나 닮아 있기 때문이다. ‘큐비스트’라 불리는 큐브 전문가가 되기 위해 노력하는 사람들의 모습과 개발자의 모습을 비교하면서 개발자의 실력 향상을 위해 필요한 자세가 무엇인지를 살펴보자.

큐브의 실력은 사용하는 큐브 기술에 따라 초급, 중급, 고급, 그리고 진정한 고수로 구분될 수 있다. 

초보자 – 기본개념 익히며 열심히 따라 하기

큐브 초보자들이 빠지기 쉬운 함정은 바로 처음부터 고수를 흉내 내려는 욕심이다. 고수들은 손이 보이지 않을 만큼의 빠른 회전으로 무작위로 섞여 있는 큐브를 10초대 초반의 짧은 시간 안에 맞춰낸다. 초당 7회전 이상의 빠른 손놀림과 중간에 버벅거림 없이 바로 다음 단계로 넘어가는 모습 등에서 우리는 감탄하게 된다. 그뿐인가. 한손으로 맞추기, 눈 가리고 맞추기, 심지어 발로 맞추기도 가능하다. 어떤 제약 조건과 환경에서도 아무런 주저 없이 척척 해내는 고수들의 모습을 보고 초보자들은 한편으로는 좌절하지만, 다른 한편으로는 강한 도전 욕구를 느끼게 된다. 문제는 어설프게 고수들의 손놀림이나 흉내 내려고 하는 사람들은 이 시점에서 대부분 실패한다는 것. 고급 큐비스트들이나 사용하는 솔루션과 알고리즘 자료를 모아다가 이해도 되지 않은 상태에서 억지로 적용해보려고 애쓰다보면 어느새 큐브에 대한 흥미는 점점 떨어지고 결국엔 그나마 초보자로서 느낄 수 있었던 최소한의 기쁨마저 맛보기 힘들어진다. 착실하게 초보의 단계를 밟아 나가는 사람은 그런 고수들의 어려운 기술보다는 자신에게 맞는 기초 내용에 충실하려고 노력한다. 일단 큐브에서 사용되는 각종 용어들과 기호들에 익숙해진다. 센터, 코너, 엣지 블록이라는 기본 구성요소를 익히고 각 블록의 특징을 이해한다. 큐브는 사실 어떤 면의 색을 맞추는 것이 아니라. 가운데 있는 블록을 제외하고는 2개 이상의 색을 가진 블록의 위치를 맞추는 것이다. 이런 개념과 함께 초보자용 솔루션을 공부하기 위한 회전 기호에 익숙해지도록 연습한다. 외울 것이 제법 많지만 그 장벽을 넘어야 한 시간이 걸려서라도 큐브를 한번이라도 맞춰보는 짜릿한 기분을 느낄 수 있다. 초보 개발자들도 마찬가지다. 어설프게 고급 개발자들이나 보고 연구하는 책을 구해 처음부터 어려운 주제로 폼을 잡으려는 개발자라면 이미 개발자로서의 첫 걸음을 잘못 내디딘 것이다. 일단 가장 기본이 되는 프로그래밍 언어와 기초 개념들을 충실하게 공부하는 것이 초보자의 바른 자세다. 기초는 대충 건너뛰고 바로 중급 이상의 기술로 넘어가려는 욕심은 결국 어느 단계에서 더 이상의 성장을 막는 장애물이 되고 만다. 초보 큐비스트는 일단 가장 기초가 되는 해법을 열심히 외워서라도 큐브 맞추기를 많이 해보는 것이 중요하다. 처음에는 잘 알지 
못한 채 무작정 따라 하기만 했던 솔루션이지만, 어느 단계에 이르면 솔루션 하나하나가 지닌 원리와 심오한 뜻이 무엇이었는지를 자연스레 알게 된다. 물론 초보자용은 좀 지루하다. 필수 회전수도 고급 큐비스트들이 사용하는 것의 2~3배 이상 된다. 하지만, 그것을 충실히 따라하면서 익히는 과정 없이는 결코 다음 단계로 나아갈 수 없다. 필자가 초급 개발자들에게 항상 강조하는 바는 일단 기초적인 내용의 코드라도 잘 만들어진 것을 열심히 분석하면서 흉내 내보라고 하는 것이다. 필자가 처음 프로그래밍을 배울 때는 마소나 컴퓨터 서적에 나온 모든 코드를 일일이 손으로 다 입력하고 그것을 흉내 내서 코딩하는 연습을 했었다. 그리고 그 중에 괜찮은 것이 있으면 그것을 잘 기억했다가 써먹으려고 노력했다. 자신의 실력을 과신하고 처음부터 자기 방식대로 하겠다고 욕심을 부리기보다는 일단은 고수들의 코드와 개발 방식을 겸허하게 받아들여 흉내내볼 필요가 있다. 물론 처음부터 고급 기술을 따라해 보라는 의미는 아니다. 가장 기초가 되는 코드들을 중심으로 그것들이 어떻게 만들어졌는지부터 하나씩 살펴보고 따라해 보는 것이 중요하다. 필자는 지금도 배우고 싶은 새로운 기술이 있다면 관련 서적이나 레퍼런스에 나오는 예제들을 빠짐없이 손으로 다 입력해서 실행해보고 그것을 숙지하려고 노력한다. 튜토리얼이나 예제에 등장하는 내용은 사실 그 기술을 만든 사람이 가장 핵심이라고 생각하는 내용을 간추리고 간추려 모아놓은 것이다. 그 내용과 순서를 완전히 숙지하지 않고 더 깊은 내용만 추구하려는 태도는 기술을 온전히 익히는 데 도움이 되지 않는다. 간단한 예제를 반복적으로 코딩 연습하는 것은 기초적이지만 핵심적인 내용을 빠르게 사용할 수 있는 훈련으로 적합하다. 그러면서 조금씩 원리를 깨닫게 되고, 머지않아 반복되는 패턴이 보이기 시작할 것이다. 기초에 충실하면서도 꾸준한 반복연습을 하는 것이 다음 단계로 나아가는 최적의 지름길이다. 큐브 초보자들은 초보 기술을 이용해 보통 양손으로 1분 이내에 큐브를 맞추는 단계가 될 때까지 연습한다. 처음에는 초보자용 솔루션을 보고 30분에 맞추던 것을 이제는 기초 공식을 보지 않고도 1분 이내에 맞추는 수준으로 올라간다. 처음에는 단순한 CRUD 코드를 작성하는 데도 예제를 봐야 하고 레퍼런스 매뉴얼을 뒤져가며 쩔쩔매다 며칠씩 보내곤 하지만, 이를 꾸준히 반복 연습하다보면 다소 응용된 CRUD를 몇 시간 내에 개발할 수 있는 실력을 얻게 된다. 이쯤 되면 슬슬 자신감이 붙기 시작하지만, 한편으로는 한계를 느끼게 된다. 지금까지 해온 것을 좀 더 빠르고 효과적으로 할 수 없을까라는 의문이 들기 때문이다. 바야흐로 이제 중급으로 올라갈 때다.

중급 – 다양한 응용기술에 관심 돌리기

초급 단계에서 이미 충분한 시간과 여유만 주어진다면 큐브를 다 맞출 수 있는 실력을 갖췄다. 하지만 여전히 그 하나하나 솔루션의 원리가 완전히 이해되진 않는다. 아무래도 기초적인 방법을 따라하면서 숙지하는 식으로 연습했기 때문이다. 그래서 중급이 되면 이제 반복되는 단순한 회전과 비효율적인 해법들을 좀 더 고급스러운 것으로 대치하기 시작한다. 흔히 말하는 각종 중급용 공식들과 팁들을 익혀나간다.
개발자도 마찬가지다. 기초를 충실히 갖춰 웬만한 프로그램은 시간만 충분히 주어진다면 만들 수 있겠지만 그래도 여전히 뭔가 부족하게 느껴진다. 고수들의 그것에 비하면 자신들의 개발 속도와 나오는 코드의 질이 뭔가 달라 보인다. 이제 기초를 넘어선 각종 응용기술과 개발 전략에 눈을 뜰 때이다. 이때 필요한 중요한 두 가지는 개념에 대한 깊이 있는 이해와 다양한 새로운 기술을 익히는 것이다. 자바라는 객체지향 언어를 배워 이제껏 잘 써왔지만 여전히 객체지향적 설계와 프로그래밍에 대한 깊은 이해가 없다면 이제 객체지향 원리들을 충실히 익힐 차례다. 또 개발자들이 부딪치는 많은 문제들에 대한 표준화된 솔루션을 정리해놓은 디자인패턴 같은 것도 공부해야 한다. 그러면서 기존에 그저 흉내 내기에 급급했던 코드들이 왜 그런 식으로 구성되었어야 했는지를 하나씩 깨닫게 마련이다. 중급 큐비스트들도 원리에 대한 이해가 점점 생겨나게 된다. 이전에는 회전을 더 많이 하더라도 가장 단순한 방법을 써서 맞추는 데만 충실했다면 이제는 그 각 회전이 가지는 의미를 알 수 있어야 한다. 큐브 공식에 가장 자주 등장하는 패턴인 ‘공식-역공식’ 패턴의 특성도 이해해야 한다. 또 방향(Orientation)과 조합(Permutation)이라는 큐브 맞추기의 중요한 원리도 이해해야 한다. 그런 것을 학습하면서 그동안 써왔던 기술들이 어떤 원리에 의해 만들어졌는지를 깨닫는 과정에 들어선다. 물론 중급 레벨에서 너무 많은 것을 기대해서는 안 된다. 다만, 이전에는 단순히 외우고 베끼고 따라 하기만 했던 것을 이제는 좀 더 깊이 들여다 볼 수 있도록 훈련하는 것이다. 중급에서 익혀야 할 또 한 가지는 속도의 향상이다. 중급 큐비스트라면 이제 양손으로 30초대에 진입하는 것을 목표로 해야 할 것이다. 초급에서는 사용하지 못했던 단축 솔루션들을 익히고 원리를 응용한 핑거 트릭(Finger Trick)이나 핑거 숏컷(Finger Shortcut) 등을 배우면서 속도의 향상에 힘쓴다. 개발자들은 생산성의 향상에 주목한다. 이제까지는 어떻게 만들던지 코드가 돌아가기만 하면 된다는 생각이었지만, 이제는 가능하면 빠르고 정확하게 동작하는 코드를 어떻게 효율적으로 작성할 수 있는지에 집중해야 한다. 초보 때는 원리를 배우기 위해서라도 가능한 한 직접 모든 것을 만들어 사용했다면 중급에서부터는 효율성을 중시해 다양한 라이브러리와 프레임워크를 도입해 보는 게 좋다. 너무 욕심을 부리지 않는 범위에서라면 새로운 기술을 익히고 그런 잘 만들어진 기술을 활용하는 즐거움에 빠져보기도 하자. 

고급 – 시간과 품질의 싸움

많은 큐비스트들이 큐브도 원하는 대로 맞출 수 있고, 제법 속도도 나는 중급 단계에서 그냥 주저앉는 경우가 많다. 더 이상의 고급 수준으로 가는 것에 대한 욕심이 없기 때문이기도 하고, 고급 실력을 갖추는 데는 사실 엄청난 노력이 필요하기 때문이기도 하다. 개발자들 또한 중급 정도의 실력이면 어디 가서나 눈치 안보고 나름의 실력을 뽐낼 수도 있고, 또한 주어진 일을 해내는 데도 무리가 없으므로 그 정도에서 만족하려는 경향이 있다. 어쩌면 그 가운데 소수의 사람들만이 도전하기 때문에 그 다음 단계가 고급이라고 불리는지도 모르겠다. 상당수의 중급 큐비스트들은 고급 난이도에 도전을 시도한다. 6면을 맞추는 데 30초 대 정도의 큐브 실력이면 어디에든지 충분히 실력을 뽐내 이목을 집중시킬 수 있다. 하지만 이제는 그런 차원이 아니라 진정한 자신에 대한 도전이 시작되는 것이므로 고급 기술을 익혀 시간을 20초대, 더 나아가 10초대 후반까지 도전하려고 한다. 그러기 위해서는 먼저 고급 기술들과 이론들을 익혀나가야 한다. 10대 때 이미 자신만의 고급 큐브 솔루션을 개발한 제시카 프리드리히 교수와 같은 천재적인 사람들에 의해 만들어진 고급 기술들은 초보자가 기억하고 알아야 하는 것보다 10~20배 이상의 공식을 암기하고, 또한 그것을 응용할 수 있는 수 백 가지의 케이스를 빠르게 파악할 수 있는 능력을 요구한다. 이는 며칠, 혹은 몇 주간의 노력으로는 도저히 도달할 수 없는 수준이므로 적어도 몇 달, 혹은 몇 년에 이르는 엄청난 노력이 필요하다. 하루에 12시간씩 연습한다는 사람들의 이야기도 종종 들어본다. 직장인인데도 틈만 나면 큐브를 손에 들고 연습하고 공식을 암기하고 다양한 응용케이스를 풀어보는 훈련을 한다. 그렇게 해서 큐브 맞추는 시간을 5초, 10초 단축하는 데 엄청난 노력을 들이는 것이다. 고급 개발자가 되는 길은 어떠한가? 역시 만만한 것은 아니다. 중급에서는 그저 기능 구현을 직접 하지 않고 남들이 만든 것을 가져다가 응용해 쓰는 훈련을 했다. 이제 고급 개발자가 되면 이제까지 해보지 않고 다루지 않았던 기술과 영역까지 받아 들여 생산성을 극대화 하고 전체 애플리케이션 구조의 효율을 따질 수 있다. 또한 품질과 유연성까지 고려한 개발이 이뤄지는 것이다. 이렇게 하기 위해서는 또한 새롭게 공부하고 훈련할 것이 많다. 품질의 향상과 궁극적인 생산성 극대화를 위해 다양한 툴을 익히고 사용한다. 이전에는 이클립스와 그 번들에만 충실한 채 썼다면 이제는 자신만의 효과적인 개발을 위한 각종 플러그인과 써드 파티 툴들을 익히고 익숙해진다. 또한 테스트 주도 개발처럼 개발의 스타일을 완전히 뒤집어버리는 큰 도전에도 과감히 뛰어들게 된다. 그것이 자신의 실력을 20~30%만 더 향상시켜 준다고 해도 기꺼이 도전할 의지가 있는 것이다. 반대로 기초의 더 아래까지 내려가 가장 깊은 원리를 파고들게 된다. 이전에는 그저 가져다가 잘 쓰기만 하면 됐다고 생각했던 각종 오픈소스 제품들을 이제는 소스코드 레벨을 들여다보며 그 원리를 파악하려고 노력한다. 어떤 개발자는 자바의 바이트코드까지 분석해가면서 성능 향상을 위해 노력하기도 한다. 고급개발자는 그저 개발 경험과 시간이 많다고 저절로 되는 것이 아니다. 부단한 노력과 함께 자신의 실력을 향상시킬 수 있는 
것이라면 무엇이든지 도전해보는 용기가 필요하다. 큐브의 고급공식을 적용하다보면 오히려 중급 때보다도 시간이 더 오래 걸릴 때가 있다. 아무래도 이전에 손에 익숙한 방식이 아닌 탓에 숙련이 되려면 그만큼 시간이 더 필요하다. 물론 충분한 연습이 따르면 이전에 사용하던 기술로는 도저히 따라올 수 없는 대단한 효과를 나타낸다. 고급개발자들이 새로운 프레임워크나 기술을 과감히 적용하려고 하다보면 자꾸 이전에 익숙하게 쓰던 방식이 더 편하지 않았는가라는 유혹에 휩싸일 수 있다. 하지만 그렇더라도 끝까지 포기하면 안 된다. 필자가 가장 넘기 힘들었던 단계는 오랫동안 익숙하게 사용해왔던 자바의 표준 기술 스택들인 JSP, EJB, JDBC 등을 버리고 스프링이나 하이버네이트 같은 프레임워크 기반의 기술을 사용하기 시작할 무렵이었다. 이전에 JSP Model1으로 개발할 때는 3시간이면 충분했던 웹 모듈이 SpringMVC로 개발할 때는 일주일이나 걸렸던 적도 있다. 십수년간 써와서 너무나도 익숙한 네이티브 SQL을 쓰지 않고 ORM이라는 다소 거추장스러워 보이는 기술을 쓰려니 다대다 관계의 테이블들을 읽어오는 것 하나를 하려 해도 매뉴얼을 뒤져야 했고, 또한 이게 맞나 싶어 자꾸 확인하면서 진행하려니 무척 답답했던 게 사실이다. 하지만 그때 포기하지 않고 끝까지 도전한 끝에 지금은 스프링과 하이버네이트 등을 이용해 누구보다도 빠르고 더 깔끔하게 우수한 코드를 작성할 수 있는 단계에 이르렀다고 생각한다. 또 하나 고급의 단계가 되기 위해 요구되는 것은 자신만의 기술과 응용력이다. 다양한 천재적인 큐비스트들에 의해 만들어진 고급 공식들이 있다. 그럼 고급 큐비스트들은 그것을 단순히 외울까? 현존하는 최고급 큐브 공식은 약 1,500개의 시퀀스를 가지고 있다. 각 시퀀스마다 적어도 5~10회전은 필요로 하니 우선 수만 개의 회전조합을 기억하고, 큐브의 상태를 딱 본 후 어떤 것을 어떻게 적용할지를 떠올릴 수 있어야 한다. 과연 그런 방식이 미련하게 암기한다고 되는 것일까? 절대 그렇지 않다. 오히려 그런 고급공식은 큐브의 개념과 원리를 완벽히 이해하고 있다면 자연스럽게 도출해 낼 수 있다. 고급 큐비스트들은 모두 자신만의 솔루션을 가지고 있고, 또 계속해서 그것을 개발해 낸다. 이전보다 조금 더 나은 회전을 할 수 있는 손동작이 있거나 회전 순서, 방식이 있다면 그것들을 끊임없이 찾아내고 자신의 것으로 만들려고 노력한다. 고급 개발자들도 또한 자신만의 노하우와 경험에서 나오는 다양한 팁과 기술들 보유하고 있고 끊임없이 자신만의 새로운 기술을 개발해낸다. 또한 그렇게 만들어진 자신의 기술을 남들과 나누는 것도 고급 개발자의 멋진 모습이 아닐 수 없다. 후배 개발자들에게 좋은 개발 팁과 기술을 알려주고 조언해주는 것, 또 자신이 작성한 좋은 코드를 오픈소스와 갈은 형태로 온라인에 공개해 많은 사람들이 배울 수 있도록 해주는 것. 그런 모습이 없이 진정한 고급 개발자라고 말할 수 있을지 의심스럽다. 이처럼 최고의 기술을 위한 부단한 노력과 자신만의 기술 창조를 위한 수고는 고급 개발자로서의 가치를 멋지게 드러내줄 것이다.

고수 – 고수에겐 끝이 없다

고급 개발자의 레벨을 넘어서서 언젠가는 최고의 경지에 다다른 고수의 길로 가는 사람들도 있다. 현재 3×3×3 큐브의 세계 챔피언은 20대 초반의 한국 청년이다. 그는 다른 사람들은 한 면도 채 맞추기 힘든 11초라는 짧은 시간에 큐브 6면을 모두 맞춰낸다. 그것도 어쩌다 한번이 아니라 여러 번 시도한 평균 시간이다. 그가 큐브를 맞추는 모습을 촬영한 동영상을 아무리 천천히 살펴봐도 그 회전을 제대로 볼 수 없다. 제대로 보려면 아마 초고속 카메라가 필요할 것 같다. 현재 그의 한글 블로그에는 전 세계의 수많은 큐비스트들이 방문해 글을 남기고 간다. 그만큼 인기가 높고, 따르는 사람이 많다. 그런데 그의 블로그를 계속 읽다보면 그 최고의 큐비스트는 그런 인기에 그다지 관심이 없음을 알게 된다. 대신 오늘도 0.1초를 더 줄이기 위해 더 나은 방법이 없을까를 고민하며 세계의 많은 큐비스트의 사이트 등을 뒤지고, 그 과정에서 좋은 것을 발견하면 그것을 연습하고 그 결과를 블로그 등에 공개하며 살고 있다. 물론 연습은 끝이 없다. 날마다 빠짐없이 자신의 기록을 측정하고 공개한다. 고수라는 것은 마치 도를 닦다가 뭔가 깨달음을 얻어 어떤 경지에 다다르는 것처럼 어느 순간 끝이 보이는 그런 위치로 가는 것을 의미하진 않는다고 생각한다. 과연 개발자의 끝이 있을까? 현재 세계 최고의 개발자라고 칭송받는 사람이 그대로 가만히 있어도 여전히 최고수의 자리를 지킬 수 있을까? 그렇지 않다. 오히려 최고의 개발자라고 불리는 사람일수록  꾸준히 자신의 실력을 향상시키고 새로운 기술과 좋은 전략을 배우기 위해 노력하고 있다. 세계적으로 유명한 개발자들을 만나 그의 강연이나 얘기를 듣다보면 다음과 같은 그들의 말에 종종 놀라게 된다. “저는 이곳 모임에서 여러 분들을 만나 이번엔 이런 것을 배울 수 있었습니다.” 그 들은 자신보다 실력이 부족하다고 생각되는 다른 개발자들에게서도 무엇인가를 끊임없이 배우려고 노력한다. 그 겸손한 자세야말로 그들을 진정한 고수의 자리에 올려놓은 힘이 아닐까 생각해 본다. 이처럼 최고의 큐비스트와 최고의 개발자들이 지닌 공통점은 결국은 겸손이 아닐까 싶다. 자신의 실력에 자만하지 않고 노력을 
게을리 하지 않으며, 끊임없이 배우려는 자세와 자신의 것을 남들과 공유하려는 마음가짐. 그것은 결국 모든 개발자가 지향해야 할 궁극적인 고수의 자세일 것이다.
Posted by 모과이IT
,

아키텍트로서 성장하기 위한 길은 막막하게 느껴지곤 한다. 누구에게 아키텍트로서 가야 하는 길을 물어야 할 것인가? 산전수전 다 겪은 나이가 지긋한 아키텍트로 활동 중인 사람을 만나기란 하늘의 별따기다. 따라서 필자는 업계 최고의 아키텍트들의 조언을 모아 가상의 인터뷰를 진행해 봤다. 이 인터뷰의 내용은 필자가 PLoP라는 패턴학회에서 만난 해외 거장들과의 토론과 조만간 출간될 번역서인 『아키텍트가 알아야 할 97가지』의 내용을 모아 만들었다.


손영수 안녕하십니까? 여러 선배님들. 아직 ‘Architecture’의 ‘A’자도 깨우치지 못했지만, 여러 선배님들에게 아키텍트로 성장하기 위한 방법과 또 아키텍트로서 올바른 아키텍처를 바라보는 방법들을 여쭤 보고자 합니다. 많은 이들이 궁금해 하는 질문일텐데, 여러 선배님들처럼 훌륭한 아키텍트가 되기 위해선 어떠한 것들을 준비해야 할까요? 실제 현업에서 아키텍팅할 때 어떠한 부분을 고려해야 할지 여러분들의 얘기를 듣고 싶습니다.

 

요구사항

 

Rick Kazman

실제 프로젝트는 요구사항 분석에서부터 시작한다고 할 수 있죠. 이때 아키텍트가 가져야 할 중요한 덕목은 소통과 협상 능력입니다. 설계 능력 못지않게 중요한 능력이 Social Skill입니다. 다양한 이해당사자들이 모두 만족할 수 있는 시스템을 만든다는 것은 어쩌면 불가능에 가까운 일입니다.

 

이해당사자들의 요구사항들이 서로 충돌하는 경우도 많이 경험했습니다. 빠른 메시지 전송뿐만 아니라 높은 보안 수준을 요구한다거나, 자원의 제약이 심한 임베디드 시스템에서 고성능 PC에서나 가능한 퍼포먼스를 요구하는 것들을 예로 들 수 있죠.

 

아주 적은 금액으로 모든 문제를 해결해 엄청난 효과를 누리려는 이해당사자에게 정말 기간 내 구현 가능하고 필요한 기능을 뽑아 현실에서 실현 가능한 상황에 대해 이해시키는 것이 중요합니다. 만약 여기서 이해당사자들과의 합의를 이끌어내지 못하거나, 정확한 요구사항을 파악하지 못한다면 프로젝트는 초창기부터 산으로 가게 됩니다. 그 만큼 소통과 협상 능력은 아키텍트에게 설계 능력만큼 중요한 요소라는 점을 기억해 주시길 바랍니다.

 

Mark Richards 저도 비슷한 사례를 말하고 싶네요. 전 프로젝트를 시작할 때 항상 꺼내는 이야기가 있습니다.  소프트웨어 아키텍트들이 알아야만 하고, 이해해야 하는, 그리고 고객, 동료와 함께 꼭 프로젝트 시작 전 나눠야 하는 이야기가 있습니다. 1620년대에 스웨덴과 폴란드의 전쟁에서 나온 ‘Vasa호’라는 배 이야기입니다.

 

스웨덴 국왕은 전쟁을 빨리 끝내고 싶어서 Vasa호라는 특별한 배를 만들라고 주문했습니다. 이 배가 갖춰야 했던 조건(요구사항)들은 그 당시의 어떤 배와도 비교할 수 없었습니다. 선체가 200피트 정도 더 길고, 2개의 갑판에 64개의 총을 적재할 수 있고, 300명의 군사를 안전하게 태워 폴란드로 가는 바다를 가로지를 수 있는 수송 능력을 가져야 했습니다. 배를 건조하는 데드라인(시간)을 엄수해야 했으며, 재정(자금)적으로도 여유롭지 않았습니다.

 

또한 배 설계자(아키텍트)는 이렇게 생긴 배를 이전까지는 설계한 적이 없었습니다. 크기가 작고 총을 실을 수 있는 갑판이 한 개만 있는 배를 만드는 것이 그가 주로 한 일이었습니다. 그럼에도 불구하고, 설계자는 그의 예전 경험을 기반으로 추정하고 Vasa를 설계하고 건조하기 시작했습니다. 그 배는 결국 설계대로 건조되었고 마침내 배를 띄우는 날이 왔습니다. 어떻게 되었을까요? Vasa호는 위풍당당하게 항구를 출항했지만 예포를 쏘고 난 뒤 바로 바다 저 밑으로 가라앉고 말았습니다.

Vasa호의 문제는 명확합니다.

 

그 어느 누구도 1600~1700년에 큰 전투함에서 갑판을 본적이 없었고 이러한 배의 갑판은 특히 전쟁 중에 붐비고 안전하지 않다는 것을 알았습니다. 전투함과 운송선 2개의 역할을 다하는 하나의 배를 건조하는 것은 큰 실수였죠. 국왕의 모든 소원을 충족하려고 한 배 설계자는 균형이 맞지 않고, 불완전한 배를 만들 수밖에 없었던 것입니다. 저희 소프트웨어 설계자들은 Vasa호로부터 많은 것을 배울 수 있습니다. 이와 같은 불행한 사건을 소프트웨어 아키텍처의 설계에 적용할 수도 있겠죠. 하지만 Vasa호와 같이 모든 요구사항을 충족시키려는 시도는 궁극적으로 아무것도 수행할 수 없는 불완전한 아키텍처를 만들게 됩니다.

 

 

손영수 정말 깊이 새겨야 할 교훈이네요. 그렇지만 많은 관리자나 고객이 수많은 요구사항들을 결국 쏟아내는데요. 이 사람들을 설득하고 요구사항 간에 균형을 맞추는 방법은 무엇일까요?

 

 

Rick Kazman 이해당사자들 간에 서로 상충되는 요구사항들을 우선순위화해서 아키텍처를 도출하는 ATAM(Architecture Tradeoff Analysis Method)이라는 방법이 있습니다. 이해당사자들 간에 제한된 투표권을 준 다음 정말 중요한 것 몇 개만 선택하게 하는 거죠. 그래서 정말 중요한 것들을 우선순위화할 수 있게 됩니다. 좀더 자세한 내용은 제가 쓴 『소프트웨어 아키텍처 이론과 실제(Software Architecture in Practice)』에 자세히 설명되니 읽어 보시길 바랍니다.

 

 

손영수 그 외에 요구사항을 파악할 때 더 주의해야 할 것은 없을까요?

 

Eben Hewitt 여러분에게 시스템 구축을 의뢰한 고객은 여러분의 진정한 고객이 아닙니다. 여러분의 고객의 고객이 진정한 고객이지요.

 

손영수 무슨 의미인지 정확히 이해되지 않는데요. 좀 더 자세히 설명해 주십시오.

 

Eben Hewitt

여러분이 전자상거래를 구축해야 한다면 여러분의 고객보다는 최종 웹사이트를 이용하는, 즉 웹사이트에서 물건을 구매하는 사람들에게 더 주의를 기울여야 합니다.

 

실제 웹사이트 사용자들은 전송 보안(transport security)을 필요로 할 것입니다. 그들은 저장된 데이터 암호화가 필요한 것입니다. 여러분의 고객은 이러한 요구사항을 언급하지 않을 수도 있습니다. 고객의 고객이 필요로 하는 것을 여러분의 고객이 빼먹은 것을 안다면, 왜 이러한 것들이 필요한지 언급하고 그 이유에 대해 자세히 설명해야 합니다.

 

만약 여러분의 고객이 실제 웹사이트 사용자에게 꼭 필요한 기능에 관심이 없다면, 프로젝트에서 잠시 물러서 제 3자의 입장에서 고려하십시오. 공격적인 고객(Sally Customer)은 매년마다 SSL에 대해 라이선스 비용을 치르기를 원하지 않고, 구축비용이 적게 든다는 이유만으로 그들의 신용카드 정보가 간단한 텍스트로 저장되기를 원할 수도 있습니다. 이미 알고 있는 나쁜 생각들을 실행하는 것에 여러분이 동의하게 되면, 여러분은 요구사항 수집에 실패한 것입니다.

 

손영수 그런 깊은 뜻이 있었군요. 앞으로 명심하겠습니다. ‘고객의 고객을 고려하라.’ 정말 의미 깊은 조언이었습니다. 그럼 계속해서 다른 이야기를 나눠 보도록 하죠. 아키텍트로서 고려해야 할 다른 것들이 있으면 조언 바랍니다.

 

프로세스와 팀 구축

 

 

James O. Coplien 전 프로세스와 조직에 대한 이야기를 꺼내고 싶습니다. 혹시 Conway의 법칙을 아시나요?

 

이는 여러분이 하나의 컴파일러를 만들기 위해 4개의 팀을 만든다면, 여러분은 4단계(four-pass) 컴파일러를 얻게 된다는 것입니다. 즉 조직구조에 의해 소프트웨어 구조가 정해진다는 얘기입니다.

 

이미 팀이 구성된 후 요구사항을 분석한다면, 팀 구조에 맞춰 분석이 이뤄지기 때문에, 팀 구조 그대로 소프트웨어 구조가 나올 수밖에 없습니다. 소프트웨어의 특성을 파악하기도 전에 소프트웨어의 큰 구조를 정하는 우를 범한 것입니다.

 

 

만약 팀 구성 후, 어느 팀도 맡기 애매한 요구사항을 발견했다면, 이 사각지대를 서로 맡지 않기 위해 여러 가지 복합적인 일들(정치, 책임회피 등)이 발생하게 됩니다. 이 경우 종종 프로젝트가 산으로 올라가게 됩니다. 그야말로 길을 잃는 것이지요. 그래서 팀을 구축하기 이전에 비즈니스 프로세스를 정제할 필요가 있습니다. 비즈니스 프로세스를 정제한 후에 조직을 구성해야 책임의 사각지대가 생기는 것을 막을 수 있죠.

 

 

손영수 그렇군요. 효율적으로 팀을 구축하기 이전에 어떻게 해야 할까요?

 

Krysztof Cwalina

프로젝트 관리자는 팀을 구성하기 이전에, 애플리케이션의 특성을 고려해 ‘땅콩버터나 마천루(적합한 프로세스)’를 선택해야 합니다.

 

땅콩버터(Peanut Butter)는 ‘Feature들이 중심이 되어 소프트웨어를 만드는 Bottom-Up 방식의 프로세스’를 말합니다. Bottom-Up 프로세스는 기존의 비교 대상도 없고, 전혀 새로운 소프트웨어를 만들 때 주로 사용하는 방법입니다. 이 방식은 견고하고 더디지만 모든 Feature들이 골고루 기능 향상을 가져올 수 있는 장점이 있습니다. 실제 땅콩버터처럼 모든 기능들이 골고루 퍼지고 진화할 수 있어서 땅콩버터 방식이라고 말합니다. 흔히 하위 레벨의 프레임워크나 저 수준의 라이브러리를 개발할 때는 이러한 방식이 선호됩니다.

 

만약 여러분의 소프트웨어가 고객의 요구사항들을 다수 받아들여야 하고 다양한 시나리오를 요구하는 경우인데도 Feature에 초점을 맞춘 땅콩버터 식의 프로세스와 조직을 구성하게 되면 어떻게 될까요? 위에서 언급한 것과 같이 새로운 시나리오가 탄생하면 많은 조직들이 협업해야 될 뿐만 아니라, 기능을 명쾌하게 나누기가 애매한 경우 많은 정치와 책임의 분배 문제 등이 발생됩니다.

 

이와 상반된 방식으로 마천루(Skyscraper) 방식이 있습니다. 시나리오가 마천루처럼 높이 솟아 전체 소프트웨어의 기능을 구현하기 위한 좋은 기준이 된다는 것입니다. 명백한 기준이 있다는 것은 많은 시행착오를 줄일 수 있을 뿐만 아니라, 고객의 관점에서 소프트웨어를 생각할 수 있는 장점을 가질 수 있습니다. 흔히 우리가 알고 있는 시나리오를 만들고 프로토타입(Prototype) 방식으로 개발해 나가는 것이라고 생각하면 됩니다. 바로 Top-Down 방식의 프로세스가 여기에 해당되죠.

 

여러분의 소프트웨어가 상위 레벨의 응용 소프트웨어로서, 많은 사람들에 의해 사용된다면 당연히 시나리오 기반(Sky scraper)의 방식으로 팀을 구성해야 합니다.

 

 

손영수 제가 알기론 마이크로소프트에서는 Feature Crew라는 이름으로 이미 시나리오 기반으로 팀원들이 구성되어 있다고 들었습니다. 또한 애자일(Agile)에서는 Cross-Functional Team이라고 부르기도 합니다. 정말 시나리오 기반의 애플리케이션을 개발하는 곳에서는 좋은 방법일 것 같습니다.

 

 

Rick Kazman 좋은 얘기를 해주셨네요. 우리가 설계하고자 하는 최종 소프트웨어를 고려한 형태로 조직과 프로세스가 선택되어야 합니다. 단순히 애자일의 바람이 불어서, 또는 RUP가 좋으니 이걸 사용하자는 식보다는 소프트웨어의 특성, 조직의 문화 등을 고려해 적용하는 것이 중요합니다. UML의 창시자 Ivar Jacobson 역시 RUP를 넘어 EssUP(Essential Unified Process)라는 새로운 것을 내놓았는데, 핵심은 조직과 소프트웨어 특성에 맞게 적합한 프로세스를 고려하라는 것입니다.

 

 

설계

손영수 그럼 설계 시 고려해야 할 것은 무엇입니까?

 

Kevlin Henney 여러분이 설계 시 둘 중 하나를 선택해야 한다면 대부분은 중요한 것을 선택합니다. 하지만 설계(소프트웨어 또는 다른 것들) 시에는 그렇게 해선 안 됩니다. 두 가지 선택사항이 존재한다는 것은 설계 시 불확실성을 고려할 필요가 있다는 것을 알려주는 지표(indicator)입니다.

 

A와 B 두 가지 중 하나를 결정하려고 시도하는 것보다는 A와 B 사이의 결정을 덜 중요하게 만들기 위해 어떻게 설계해야 할지를 고민해야 합니다. 흥미로운 것은 A와 B 사이의 (적절한) 선택이 존재한다는 것입니다. 설계 시 변경되는 결정을 쉽게 수용할 수 있는 분할(separation) 또는 캡슐화 기법을 고민할 필요가 있습니다.

 

 

손영수 그럼 좀 더 SoC(Separation of Concerns)와 캡슐화를 잘 하기 위해선 어떻게 해야 할까요?

 

Einar Landre

넬슨 제독이 1805년 트라팔가에서 프랑스와 스페인 함대를 격파한 이후, ‘분할 후 정복(Divide and Conquer)’ 또는 ‘걱정거리의 분리(Separation of Concern)’는 복잡하고 어려운 문제를 다루는 슬로건(상징)이 되었죠. 걱정거리의 분리로부터 우리는 캡슐화를 얻게 되고, 캡슐화로부터 우리는 경계와 인터페이스를 얻게 됩니다.

 

Kevlin Henney가 말하는 것처럼 아키텍트가 가장 크게 겪는 난제는 동작하는 시스템을 구축하기 위해 필요한 인터페이스를 정의하고 경계를 정하는 자연스러운 위치를 찾는 것이죠. ‘결합도는 낮추고 응집도는 높여라’와 ‘정보 교환이 자주 발생하는 영역들은 나누지 말라’와 같은 오래된 명언들이 몇 가지 지침을 제공하지만, 어떻게 이해당사자들에게 가능성 있는 해결방안과 문제들에 대해 쉽게 소통할 수 있는지는 알려주지 않습니다.

 

 

손영수 그렇군요. 결국 이해당사자들과 소통 속에서 적합한 균형을 찾아야 된다는 말씀이군요. 그럼 어떻게 하면 이러한 균형을 잘 찾을 수 있을까요?

 

 

 

Einar Landre

Eric Evans의 책인 『Domain-Driven Design』에 나온 Bounded Context(문맥 정합)와 Context mapping(문맥 맵핑)의 개념이 앞에서 언급한 이해당사자들과 소통의 문제를 잘 해결해 줍니다. Bounded Context는 모델이나 개념을 고유하게 정의하는 영역입니다. 그리고 우리는 Bounded Context를 설명부를 가진 구름 또는 거품으로 표현합니다. 이 설명부는 도메인에 가까운 모델 또는 개념의 역할과 책임을 정의합니다. 한 가지 예를 들면, 운송 시스템은 화물 운송, 화물 일정, 항구 이송과 같은 Context(문맥)를 포함합니다. 다른 도메인에서는 다른 이름들을 사용하는 게 적합할 것입니다.

 

Bounded Context들을 화이트보드 위에 식별하고 같이 그림으로써, Context 간에 연관관계를 그리는 것을 시작할 수 있습니다. 이러한 연관 관계들은 조직적, 기능적, 기술적 의존성을 설명하면 좋습니다. 이러한 행위의 결과로, Context 간에 인터페이스와 동일한 의미로 인식한 Context의 집합을 나타내는 Context Map이 생기게 됩니다.

 

Context Map은 아키텍트에게 무엇을 같은 걸로 볼지, 별개의 것으로 볼지 초점을 맞출 수 있고, 좀 더 현명하게 대화를 나눔으로써 분할 후 정복할 수 있는 강력한 도구를 제공합니다. 이런 지침을 통해 약한 결합, 높은 응집, 잘 설계된 인터페이스로 구성된 시스템으로 재설계할 수 있습니다.

 

 

손영수 결국 고객의 대화를 잘 이해함으로써 이러한 균형점을 찾을 수 있다는 정말 와 닿는 얘기입니다. 그럼 아키텍트가 설계 시 추가적으로 고려해야 할 사항은 무엇일까요?

 

 

 

Doug Crawford 변화의 충격을 이해할 필요가 있습니다. 뛰어난 아키텍트는 복잡도를 최소한으로 줄일 수 있어야 하며, 단단한 기본 구조를 취하면서도 급변하는 상황에 적절히 대처할 수 있는 실용적인 해결책들을 설계할 수 있어야 합니다.

 

뛰어난 아키텍트는 고립된 소프트웨어 모듈에서뿐만 아니라 사람과 사람 사이, 시스템과 시스템 사이에서 일어나는 변화의 충격을 이해해야 합니다. 변화는 기능 위주의 요구사항 변경, 요구사항의 진화, 수정된 시스템 인터페이스들, 팀원의 변동과 같은 다양한 형태로 나타날 수 있습니다.

 

소프트웨어 프로젝트 변화의 광범위함과 복잡함을 미리 추측한다거나, 모든 잠재적 문제를 미리 예측해 해결한다는 것은 불가능합니다. 하지만 아키텍트는 이러한 변화가 발생했을 때, 다른 객체나 모듈에 변화를 전파시키지 않고 변화의 충격을 완화시켜 수용할 수 있는 시스템을 구축해야 합니다. 이러한 변화를 완화하기 위한 도구나 기법으로는 다음과 같은 것들이 있습니다.

 

  • 반복 가능한 테스트 케이스를 만들고 자주 실행하기
  • 쉬운 테스트 케이스를 만들기
  • 의존성 추적하기
  • 조직적으로 행동하고 반응하기
  • 반복적인 태스크는 자동화하기

또한 위험을 미리 측정하는 Premortem은 어떠한 부분에 집중적으로 시간을 투자해야 할지 알려주는 유용한 도구입니다. 아키텍트는 프로젝트 범위의 관점에서 시간, 예산과 같은 변화의 영향을 미리 추정해야 하고 변화로 인해 엄청난 영향을 받는 부분에 더 많은 시간을 투자해야 합니다.

 

 

손영수 변화를 수용할 수 있는 구조, 소프트웨어 개발 생명주기의 관점에서 볼 때, 유지보수에 70%의 비용이 드는 관점으로 볼 때는 정말 중요한 말씀이군요. 저 같은 경우는 설계 시 실제 아키텍처를 검증하기 위해 몇 가지 프로토타입을 만들어 종종 검증합니다. 이것은 어떨까요?

 

 

Clint Shank

좋은 방법입니다. 애플리케이션 아키텍처를 구현하고 검증하고 진화시키는 유용한 전략 중 하나로 Alistair Cockburn이 이야기한 ‘걸어 다니는 해골(walking skeleton)이 있습니다. 걸어 다니는 해골은 종단(예를 들어 UI부터 DB까지) 간을 오가며 수행되는 시스템의 가벼운 구현체입니다. 모든 주요 아키텍처상의 컴포넌트는 전부 연결합니다.

 

모든 호출(Com munication) 경로를 실험할 수 있게 작동하는 작은 시스템부터 시작한다면, 옳은 방향으로 설계 및 개발해 나갈수 있습니다.

 

 

손영수 그럼 이제 개발 과정에서 아키텍트는 어떠한 일을 하는지 궁금합니다.

 

 

개발

 

 

Erik Doernenburg 아키텍트는 현재 개발하고 있는 소프트웨어가 얼마나 잘 개발되고 있는지를 파악할 수 있어야 합니다.

 

사용자에게 가치 있는 소프트웨어도 중요하지만, 내부적으로 좋은 품질을 유지하는 것도 중요하죠. 좋은 품질을 얻기 위해서는 쉽게 소프트웨어를 이해, 유지보수, 확장할 수 있어야겠죠. 그럼 소프트웨어가 잘 개발되고 있는지 매 순간 상황을 파악하기 위한 방법에는 어떤 것이 있을까요?

 

많은 이들이 UML로 그려진 아키텍처 다이어그램을 사용합니다. 하지만 아키텍처 다이어그램에서 작은 상자들은 전체 시스템을 나타내며 상자 간의 선은 시스템 간의 의존성, 데이터 흐름, 버스와 같은 공유자원 등 모든 것이 될 수 있습니다.

 

마치 비행기에서 보는 풍경과 같은 30,000피트 뷰입니다. 너무나 추상화되어 있는 관점이죠. 반면에 0피트, 즉 바닥 레벨의 뷰를 보기도 합니다. 즉 소스 코드를 보는 것이지요. 바닥 레벨의 뷰는 연관 있는 몇 개의 객체 구조도 보지 못할 정도로 너무나 많은 정보를 제공합니다.

 

즉 이 두 뷰는 소프트웨어 품질에 대한 많은 정보를 제공하지 못한다는 것이지요. 그래서 0피트와 30,000피트 사이에 적절한 뷰가 필요합니다. 바로 1,000피트의 뷰입니다. Dependency Structure Metrics로 모듈 간의 의존성을 파악할 수 있으며 Code Metrics를 이용해 클래스의 크기를 파악할 수 있습니다.

 

특정 클래스가 거대하다는 것은 너무나 많은 책임(역할)을 가지고 있다는 의미죠. 이러한 다양한 지표들(클래스 팬아웃, 메소드 개수, Circular Dependency 등)을 지원하는 사용 툴들(NDepend, XDepend, JDepend)을 이용하면 됩니다.

 

 

손영수 1,000피트의 뷰라니 정말 멋있는 표현입니다. 저 역시 리팩토링할 때 DSM과 Code Metrics를 즐겨 이용하는 편인데, 다행히 방향은 제대로 잡은 것 같습니다. 그럼 다른 조언도 부탁합니다.

 

 

Dave Quick

거울로 보이는 문제는 실제 보이는 것보다 클 수 있습니다. 많은 소프트웨어 프로젝트에 참여했던 그 동안의 경험에 비춰 보면, 각 팀의 구성원들은 팀이 예상한 것보다 더 많은 문제를 가지고 있습니다. 소규모의 팀은 이런 문제들을 초기에 확인할 수 있지만, 대부분 잊어버리거나 무시합니다. 그 이유는 프로젝트 초기에는 이 문제가 얼마나 프로젝트 후기에 큰 영향을 미치는지를 이해하지 못하기 때문입니다. 이러한 문제를 초기에 대처하기 위한 몇 가지 전략이 있는데 다음과 같습니다.

 

  • 리스크를 관리하는 조직화된 접근 방법을 만들어야 합니다. 리스크를 관리하는 간단한 방법은 여러분이 버그를 추적할 때와 같은 방식으로 리스크를 관리하는 것입니다. 누구나 리스크를 발견할 수 있고, 각각의 리스크가 더 이상 리스크가 아닐 때까지 추적할 수 있습니다.

그 후 리스크들에 우선순위를 매기고 리스크의 상태가 변화하거나 새로운 정보가 있을 때마다 리뷰를 합니다. 리뷰는 토론를 통해 감정적인 면을 배제하도록 도와주고 주기적으로 리스크를 재평가함으로써 쉽게 기억하도록 도와줍니다.

 

 

  • 주류의 의견에 반대할 때는 나머지 팀원들이 자신의 의견을 더 쉽게 이해하도록 만드는 방법을 찾아야 합니다. 반대 의견의 가치를 인식하고 모든 팀원에게 용기를 주십시오. 그리고 토론 시 팀원들이 중립적인 자세를 가지도록 하십시오.
  • ‘구린 냄새(Bad smells)’를 주의해야 합니다. 아직 명확한 근거가 없다면 사실을 확인할 수 있는 가장 간단한 테스트 방법을 찾으세요.
  • 지속적으로 팀과 고객에 대해 이해하는 내용을 테스트해 보세요. 사용자 이야기(user story)로 우선순위 목록을 정하는 툴의 도움을 받을 수 있지만, 정기적으로 고객과 대화를 나누는 열려 있는 자세를 대체할 순 없겠죠.
  • 맹점이란 그 말 의미 자체가 말해주듯이 스스로 인지하기 어렵습니다. 여러분이 필요로 할 때 말하기 힘든 사실을 말해주는 믿음직한 사람이 여러분의 귀중한 자산입니다.

 

 

손영수 개발 도중에도 아키텍처만 그려주고 사라지는 아키텍트가 아닌, 팀원 간 또는 이해당사자 간에 소통이 잘되는 문화를 만들고 잘못된 방향으로 흘러가면 가이드해서 바로 잡아야 한다는 조언이군요. 그럼 아키텍트가 가져야 할 자세에 대해서도 조언 바랍니다.

 

 

아키텍트로서 갖춰야 할 자세

 

 

Dave Quick 아키텍트는 자신이 최고라는 대문자 ‘I’보다는, 일원이라는 의미를 가지는 소문자 ‘i’의 자세가 필요합니다. 아키텍처를 수립할 때, 여러분 스스로가 최악의 적이 될 수도 있습니다. 여러분이 고객보다 요구사항을 더 잘 이해한다고 생각하거나, 개발자를 아이디어를 구현하기 위한 단순한 자원으로 보거나, 여러분의 생각에 도전하는 개발자나 팀원을 무시한 경험이 있습니까? 성공이나 사회적 지위로 인해 자만하거나 다른 사람들이 우리를 존경한다는 착각을 가지고 있고, 자신이 만든 설계에 도전하는 것을 여러분 자신의 인격에 대한 도전으로 받아들인 경험이 있을 것입니다. 이것은 과거의 성공에 빠져 여러분을 더 작은 한계에 가두는 짓입니다.

 

아키텍트로서 스스로 성장하고 성공하는 프로젝트를 만들기 위해서는 여러분의 마음가짐을 바꿔야 합니다. 전 후배 여러분들에게 다음과 같은 자세를 요구합니다.

 

  • 요구사항은 거짓말을 하지 않습니다. 요구사항이 제공하는 비즈니스 가치를 이해하기 위해 고객과 가까이 일하십시오. 아키텍처를 여러분이 이끌려 하지 말고 요구사항이 이끌도록 하십시오. 여러분은 최선을 다해 그들의 필요를 섬겨야 합니다.

 

  • 팀에 집중하십시오. 팀은 자원이 아닙니다. 그들은 여러분의 설계 협력자이자 여러분의 안전망입니다. 진가를 인정받지 못하는 사람은 보잘 것 없는 안전망을 만듭니다. 아키텍처는 팀의 것이지 혼자만의 것이 아닙니다. 여러분은 가이드라인을 제공하고 모든 사람이 협력해 함께 이끄는 것이라는 마음가짐을 가져야 합니다.

 

  • 여러분의 업무를 점검하십시오. 모형은 아키텍처가 아닙니다. 이것은 아키텍처가 동작하는 방법에 대한 여러분의 이해일 뿐입니다. 프로젝트 아키텍처가 각 요구사항을 어떻게 지원하는지 검증하는 테스트 항목을 정하기 위해 여러분의 팀과 함께 일하십시오.

 

  • 여러분을 돌아보십시오. 자기의 일을 방어하고, 이기적인 관심에 집중하고, 우리 자신을 방 안에서 가장 영리한 사람으로 여기는 우리의 본능과 싸워야 합니다. 매일 몇 분 동안 여러분의 행동에 심사숙고해 보십시오. 여러분은 모든 사람의 아이디어에 그들이 마땅히 받아야 할 존경과 인정을 주었습니까? 여러분은 선의의 참여에 부정적으로 대하지는 않았습니까? 누군가가 여러분의 접근 방법에 왜 불응했는지 이해하기 위해 노력해 보신 적이 있습니까? 자기 자신을 되돌아 볼 필요가 있습니다.

 

손영수 저도 그렇게 생각합니다. 제가 소문으로 들었던 몇몇 아키텍트들은 많은 반대에도 불구하고 자신의 생각을 관철시키곤 했습니다. 설계 자체의 옳고 그름을 떠나 개발자들과 소통 없이 일방적으로 자신의 생각을 강요했죠. 그 결과로 설계 따로, 개발 따로 하는 프로젝트가 되었다는 이야기를 들었습니다. 개발자를 이해하는 아키텍트, 그리고 아키텍트를 이해하는 개발자들이 모여야 정말 좋은 프로젝트로 갈 수 있을 것입니다. 마음가짐에 대한 또 다른 의견도 듣고 싶습니다.

 

 

David Bartlett    아키텍트는 쇼맨십을 뛰어넘는 가치 있는 청지기 의식(Stewardship)을 가져야 합니다.

 

아키텍트들은 프로젝트에 착수할 때, 자신의 가치를 입증하려는 갈망이 있죠.

소프트웨어 회사에서 아키텍트 역할을 맡는다는 것은 아키텍트의 기술적 리더십을 회사의 일부분으로 절대 신뢰한다는 의미입니다.

 

그런데 불행히도 자신의 가치를 입증하기 위해 개인의 기술적 탁월함과 쇼맨십으로 팀원들을 이끌어야 한다고 오해하는 아키텍트들이 있습니다. 사람들에게 어필하는 행동인 쇼맨십은 마케팅에서는 중요할지도 모릅니다. 하지만 소프트웨어 개발 프로젝트에 있어서는 역효과를 나타낼 뿐입니다.

 

아키텍트는 확고한 리더십으로 그들 팀의 존경을 얻어야만 하고 기술과 팀이 운영하는 비즈니스 도메인의 이해가 있어야 합니다. 책임지고 다른 이들을 돌보는 청지기 의식은 아키텍트에게 꼭 필요한 자질입니다. 아키텍트는 고객을 위해 최선을 다해야 하지, 고객의 요구를 이용하려고 해서는 안 됩니다.

 

소프트웨어 아키텍처는 고객의 요구들을 수행하는 것으로, 보통 탁월한 능력을 소유한 도메인 전문가의 방향 제시로 이뤄집니다. 성공적인 소프트웨어 개발을 추구하는 것은 아키텍트가 프로젝트에 주어진 시간과 노력에 대비해 구현의 복잡성과 비용 사이에 균형이 잡힌 절충된 솔루션을 만들게 합니다.

 

최신의 따끈따끈한 프레임워크나 기술 전문 유행어로 이뤄진 과도하게 복잡한 시스템은 비용 지출의 희생을 담보로 합니다. 아키텍트의 활동은 투자 브로커처럼 합리적인 ROI(투자 대비 수익률)를 창출할 수 있다는 전제 하에 고객의 돈을 사용하도록 해야 합니다. 여러분이 다른 사람의 돈을 사용하고 있음을 절대 잊어버려서는 안 됩니다.

 

손영수 아키텍트 명함을 가지고 다니는 사람들 중에는 신기술로 도배된 제품을 팔기 위한 비즈니스맨인지, 아키텍트인지 구분하기 힘든 이들이 있습니다. 청지기 의식이라는 것을 통해 많은 것을 되돌아보게 되었습니다.

지금까지 여러분의 소중한 조언을 들을 수 있었습니다. 설계만 잘하기 위한 공학적인 기법만큼 외부와 소통 및 협상하고, 팀원들을 이끄는 정신도 중요하다는 것을 깨우치는 시간이 되었습니다. 이 가상 인터뷰가 아키텍트를 꿈꾸는 많은 이들에게 유용한 시작점이 되었으면 합니다.

 


Posted by 모과이IT
,

30. 응용소프트웨어개발자(응용 프로그래머)

응용소프트웨어개발자는 각종 응용소프트웨어를 개발하는 프로그래머를 뜻한다.

응용소프트웨어개발자는 각종 응용소프트웨어를 개발하고 설계하는 사람을 뜻한다. 응용소프트웨어를 개발하는 과정은 곧 프로그램을 짜는 과정이므로 응용소프트웨어개발자는 프로그래머를 뜻한다. 일반적으로 특별한 조건 없이 프로그래머라고 말하면 응용소프트웨어를 개발하는 응용소프트웨어개발자를 뜻한다. 응용소프트웨어가 아닌 게임이나 모바일 프로그램을 개발할 경우에는 게임프로그래머 모바일프로그래머 등으로 좀더 세분화된 업무내용이 '프로그래머'라는 직업이름 앞에 붙는다.

과거에는 프로그래머의 영역이 컴퓨터로 한정되었기 때문에 프로그래머의 종류는 두 종류로 구분되었다. 시스템 관련 프로그램을 개발하는 시스템프로그래머와 응용 프로그램을 개발하는 응용프로그래머 두 종류로 크게 구분했다. 시스템 프로그램은 컴퓨터시스템에서 사용하는 프로그램으로 운영체제나 네트워크 프로그램, 각종 자료 입출력 프로그램과 같이 시스템을 움직이는데 필요한 기본적인 프로그램을 뜻한다. 응용프로그램은 시스템 프로그램 위에서 실행시키는 프로그램을 뜻하는데, 컴퓨터 사용자가 일반적으로 사용하는 프로그램이 여기에 속한다. 엑셀과 같은 표계산 프로그램, 한글 훈민정음 MS워드와 같은 글틀 프로그램, 포토샵 같은 그림 프로그램, 각종 게임 등이 응용프로그램에 속한다. 그러니까 우리가 흔히 사용하는 사무용, 교육용, 게임 프로그램이 응용프로그램에 속하고, 이런 프로그램을 개발하는 사람을 응용소프트웨어개발자라고 부르는 것이다. 보통 프로그래머라고 부르는 직종은 일반적으로 응용소프트웨어개발자를 가리킨다.

요즘은 응용소프트웨어의 분야가 넓기 때문에 게임을 개발하는 응용소프트웨어개발자는 게임프로그래머로 따로 분류하고, 모바일 관련 프로그래머는 모바일프로그래머로 따로 분류한다. 때문에 요즘 좁은 의미의 응용소프트웨어개발자는 주로 PC나 기업 전산망에서 사용하는 인사관리 회계관리와 같은 기업용 프로그램, 데이터베이스관리 프로그램, CAD 설비제어 등의 산업용 프로그램, 학습 교육 관련 프로그램 등을 개발하는 프로그래머를 가리킨다.

응용소프트웨어는 일반인에게 대량으로 판매하는 패키지 프로그램과 주문받아서 개발하는 주문 프로그램으로 나눌 수 있다. 엑셀, MS워드, 게임, 각종 교육용 CD롬타이틀은 패키지로 포장되어 판매되는 패키지 프로그램에 속한다. 반면 특정 기업의 업무에 최적화된 기업 인사관리, 회계관리 프로그램 등은 대부분 주문받아서 제작해주는 주문 프로그램이다. 어떤 프로그램을 개발하느냐에 따라서 프로그래머의 근무 환경이나 일하는 형태, 작업도구가 크게 달라진다. 주문 프로그램을 개발하는 프로그래머는 아무래도 촉박한 납기 시일 안에 프로그램을 완성시켜야 하므로 시간에 많이 쫓기고, 시간 대비 노동에 가까운 작업이므로 성장폭이 낮다. 대신 대기업이나 중견기업에 취업이 가능하므로 안정적인 생활이 가능하다. 물론 기업용 프로그램을 개발하는 프로그래머가 꼭 중소개발사에만 취업하는 것은 아니다. 대기업이나 중견기업, 공공기관의 전산실에 근무하면서 응용 프로그램을 개발하거나 전산 프로그램 개발을 맡는 경우도 많다.

패키지 프로그램을 개발하는 프로그래머는 여유도 있는 편이고, 개발한 상품이 성공했을 때 보상 효과도 큰 편이지만 대부분의 패키지 프로그램 개발회사가 영세한 편이라 보수나 근무 환경이 좋지 않다는 점이 단점이다. 따라서 안정성을 추구한다면 기업용 프로그램을 개발하는 기업이나 기관의 응용소프트웨어개발자로 취업하는 것이 좋다. 안정성보다는 모험을 추구한다면 패키지 프로그램 개발사에 취업해 독창적인 프로그램 개발에 몰두하기를 권한다.


스트레스가 심한만큼 성취욕도 강한 직종이다.

어떤 업무를 맡건 프로그램 개발 작업은 여러 명이 팀을 이루어 개발한다. 따라서 프로그램 개발 과정에 가장 어려운 부분은 팀원과 협력하는 일이다. 우선 자기 회사의 동료들과 호흡이 맞아야 한다. 이 과정에서 갈등을 일으킬 경우 일하기 매우 어렵다. 하청업체로 주문받아 개발하는 경우에는 프로그램 발주업체 직원과도 적절한 조화를 이루어야 하는데, 업무과정에서 호흡을 맞추기란 의외로 어렵다. 이 때문에 프로그래머가 가장 힘들어하는 부분은 사람관계가 된다.

개발자라는 업무 특성 때문에 작업 시간은 불규칙한 편이다. 개발 기간에 맞추다보면 며칠 밤을 지새는 일도 허다하다. 이 때문에 의외로 체력이 많이 요구된다. 그렇지만 '프로그래머 생활 1년이면 느는 것은 뱃살'이라는 말처럼, 하루 종일 책상에 앉아 컴퓨터와 씨름하는 프로그래머 직업의 특성 상 체력을 유지하며 건강을 챙기기는 쉽지 않다. 그래서 프로그래머가 되면 가장 신경 써야 할 부분이 자신의 건강을 챙기는 일이다.

일반적으로 응용소프트웨어개발자가 되기 위해서는 대학교에서 컴퓨터나 전산, 정보, 통신 관련 학과를 전공하면서 프로그래밍 기술을 배워 취업하는 것이 일반적이다. 하지만 프로그램 실력만 뛰어나다면 전공이나 학벌 불문하고 취업이 가능하다. 응용소프트웨어개발자 중에는 고졸 이하의 학력을 가진 사람도 12%가 넘는데, 학벌의 영향을 적게 받는 직종 중 하나다. 어느 정도의 학벌 부족은 프로그래밍 실력으로 충분히 뛰어넘을 수 있는 직종이다. 따라서 비전공자라도 책을 통한 독학이나 학원과정을 통해 프로그래밍 실력을 익힌 후에 프로그래머로 취업할 수 있다.

관련자격증으로는 정보관리기술사, 정보처리기사,정보처리산업기사, 정보처리기능사, 전자계산기조직응용기술사, 전자계산기조직응용기사, 전자계산기조직응용산업기사, 정보기술산업기사 등이 있지만 실질적으로 이런 자격증과 취업의 연관성은 매우 적다. 응용소프트웨어개발자로 취업할 때 가장 중요한 기준은 해당 언어에 대한 숙련도(실력)다.

응용소프트웨어개발자가 되려면 C/C++ 언어를 잘 하는 것이 가장 좋다. VC++, MFC와 같은 MS사 계열의 언어를 잘 해도 좋다. 자바를 배워도 응용소프트웨어개발자로 취업할 수 있지만 C++ 계열 언어에 비하면 경쟁력이 약하다. ASP와 같은 스크립트 언어를 배워서는 응용소프트웨어개발자로 취업하기 어렵다.

응용소프트웨어개발자의 절반 이상이 30인 이하의 소규모벤처기업에서 일하고 있다는 상황에서 알 수 있는 것처럼 응용소프트웨어개발자의 근무환경은 좋지 않으며 연봉도 높지 않다. 응용소프트웨어개발자는 평균 200만원 정도를 받고 있는데 신입이나 경력이 많지 않은 경우, 중소기업에서 일하는 경우에는 월 130만원 정도의 적은 급여를 받으며 일하고 있다. 대신 40대나 50대의 나이에도 응용소프트웨어개발자로 근무하는 사람이 꽤 될 정도로 수명이 긴 직종 중 하나다. 또한 IT의 기본이자 꽃이라는 프로그래밍 기술을 가지고 있기 때문에 다른 직종으로 이직하기에 가장 좋은 직종이기도 하다.

응용소프트웨어 분야는 IT 분야 중에서 아직까지 가장 많은 부분을 차지하는 부분이며 앞으로도 가장 높은 비중을 차지할 분야다. 따라서 일자리가 가장 풍부한 직종이며, 프로그래밍 실력만 갖춘다면 취업하기 가장 쉬운 직종이라 할 수 있다.

응용소프트웨어개발자는 개발과정에서 정신적 육체적으로 많은 스트레스를 받는다. 하지만 자신이 원하는 기능을 구현하고 자신이 개발한 것이 상품화되거나 사람들이 사용하는 것을 보면서 큰 성취감을 느낀다. 이런 성취감이 있기 때문에 응용소프트웨어개발자 즉, 프로그래머의 길을 가려는 사람들이 많은 것이다.

또한 응용소프트웨어개발자는 독창적인 프로그램을 개발해 세계적인 기업으로 키우겠다는 희망을 품을 수 있는 직종이다. 언젠가는 자신의 힘으로 멋진 응용프로그램을 만들어 회사를 성장시키겠다는 희망을 가질 수 있기에 힘이 들어도 프로그래머라는 직업은 도전해볼 가치가 큰 매력적인 직업이다.


Posted by 모과이IT
,