본문 바로가기
개발, IT

프로젝트의 성공 & 無야근 두 마리 토끼 잡기3

by Nabi™ 2009. 1. 15.



구현단계의 출력 - 실행파일, 설치본에서의 결함 제거

지난 원고에서 기획서나 요구사항 명세서 검토에 대해서 알아보았다. 입력단계에서 아무리 명백하고 명료하게 정리를 하였다 하더라도 구현 단계에서 역시 문제점과 결함은 나타나기 마련이다. 구현단계에서 프로젝트 개발자들이 해야 할 일에 대해서 알아본다.

앞에서 언급한 것처럼 발견되는 결함의 50%정도는 다음 그림과 같이 구현단계에서 발생한다. 중소 규모의 개발팀에서 구현단계는 설계과정을 포함하기 마련이기 때문에 이 단계에서 발생하는 결함의 양은 연구결과 보다 더 많기 마련이다. 구현단계에서 인간에 의해서 만들어지는 산출물은 소스코드이고, 이를 기계가 빌드하여 설치본을 생성한다. 일반적인 경우 기계는 오류를 내지 않으므로 구현단계에서의 생성되는 결함은 순전히 개발자의 책임이다.


그림 1 각 단계에서 발생하는 오류 - Code Complete

구현 시에 발생하는 결함에 대해서 다음과 같은 조사결과가 있다.

- 시간당 5~8개의 결함을 삽입한다. (Humphrey 1997)
- 보고된 전체의 오류 중 95%가 프로그래머에 의한 것이었다. (Brown & Sampson 1973, Ostrand & Weyuker 1984)
- 3백만 라인의 비행역학S/W에서 의 오류 중 18%가 오타에 의한 것이었다. (Card 1987)
- 구현오류의 수정이 요구사항이나 설계오류의 수정 보다 비용이 적게 들긴 하지만(평균 20~50%), 전체 구현오류의 수정비용은 설계오류의 것보다 1~2배 더 많다. (Grady 1987)
- 업계 평균적으로 출시된 S/W에서 1000라인당 1~25개의 결함이 존재한다. MS의 응용프로그램 부서의 경우 내부 테스트 시 1000라인당 10~20개 출시 이후 0.5개의 결함을 경험한다.
--- Code Project---

구현 시 발생하는 오류는 완벽하지 못한 인간이기 때문에 어쩔 수 없이 만들어 지는 것 들이다. 이는 신이 아닌 이상 숙련된 개발자도 피할 수 없는 부분이다. 기획서에 있는 오타는 별 문제가 없지만, 코드에 있는 오타는 바로 크래시로 나타난다. 더 심각한 문제는 이 결함을 고치면서 또 다른 결함을 만들어 낸다는 것이다. 다음은 결함의 수정에 따른 결함의 발생에 대한 조사 결과이다.

- 결함의 수정은 다른 변경에 비해 실패를 도입할 가능성이 크다. (Mockus & Weiss, 2000)
- 한줄 짜리 변경의 4%가 새로운 결함을 만든다.(Purushothaman & Perry, 2004)
- 새로 작성된 코드에 결함이 있을 확률은 오래된 코드보다 2.5배이다. (Ostrand & Weyuker, 2002)
- 처음에 결함이 잘못 수정될 확률이 50% 이상이다.(Yourdon, 1986)
--- Code Complete ---

아래는 각 결함감지 기법 별 감지 비율이다. 소규모의 개발팀은 보통 개발팀 자체적으로 통합테스트를 수행하고 QA와 함께 시스템 테스트를 수행하고 소량 베타테스트를 수행 할 것이다. 이 와 같이 테스트를 했을 때 아래 표에서 살펴보면 통합테스트(35%) + 시스템테스트(40%) + 소량베타 테스트(35%) = 105%가 된다. 아래 표는 각 기법 별로 감지되는 비율로 중복 합산 되기 때문에 위와 같이 세가지 테스트를 수행한다고 해도 실제로는 60%정도의 결함만 감지된다. QA를 아무리 하고 출시해도 결함이 끊임 없이 보고되는 이유가 바로 이것이다. 게다가, 통합테스트 이후 시점에 결함이 발견되면 이를 수정하기 위해서 너무 큰 비용이 든다. 왜냐하면 이때 수정하면 일정지연, 결함의 수정에 의한 결함의 발생, QA 반복, 그리고, 수정하기 위해서 설계 변경이 필요한 경우 등이 발생하기 때문이다.

표 1결함 감지 기법 별 결함 감지 율 - Code Complete


위 표1에서 비형식적 설계(코드) 검토는 개발자 스스로 여러 사람을 모아 두고 라인 단위로 검토해 나가는 것을 말한다. 형식적 설계(코드)검토는 해당 코드를 작성한 사람이 아닌 제 3자가 사전 설명 없이 코드를 보고, 다른 사람에게 설명하는 것을 말한다.

필자의 회사에서는 비형식적 설계(코드) 검토를 수행하고 있다. 여기서는 주로 사소한 실수 들 중 일부가 발견된다. 위 표에 나타난 것처럼 오류를 잡아내는 데는 큰 몫을 하지 못한다. 하지만, 아무래도 내가 작성한 것들에 대해서 다른 사람들이 검토를 하기 때문에, 코드 한 줄을 써도 신경 써서 하기 마련이다. 게다가, 교육적인 목적과 설계 또는 구현된 모듈에 대한 공유는 덤으로 얻어진다.

구현단계에서 결함을 줄이는 방법은 먼저 좋은 코드가 작성되어야 하고, 결함을 조기에 발견하고, 결함을 고치면서 다른 결함을 만들어 내지 않는 것에 초점을 맞춰야 한다.

좋은 코드를 작성하는 것은 역시 개인적인 노력과 연륜이 쌓여야 하는 부분이다. 코드 리뷰나 Pair Programming기법이 도움이 된다. 그러나, 이는 조직 문화가 바뀌어야 하는 부분이므로 도입이 쉽지 않다. 안철수연구소에서 코드리뷰가 정착되기 까지 몇 년이 소요되었다.

결함을 고치면서 다른 결함을 만들어 내지 않는 거의 유일한 방법은 자동화된 테스트 밖에 없다. 결함을 고치고 나서 자동화된 테스트를 수행함으로써 결함이 전파되지 않았는지 확인하는 것이다. 그러나, 이 자동화 테스트는 UI에는 적용하기 비용이 많이 들기 때문에 개발자 선에서 수행하려면 단위테스트를 만드는 수 밖에 없다. 이 단위테스트 또한 교육과 몇 번의 실패를 거쳐야 팀 내에서 실무에 도입할 수 있다. 쉽지 않은 일이다. 필자가 생각하는 단위테스트의 마지노선은 UI나 타 시스템에 제공되는 컴포넌트 인터페이스에 대해서 Use Case나 요구사항 명세서에 기술되어 있는 시나리오에 대한 것만 최소한으로 테스트를 만드는 것이다. 이는 팀에 큰 부담이 되지는 않으면서 상대적으로 효과는 좋다. 좀 더 노력한다면 복잡한 알고리즘을 수행하는 함수나 클래스에 대해서 추가적으로 테스트를 만들 수도 있다.

다행스러운 것은 조기에 결함을 발견하는 것은 자동화할 수 있는 툴들을 사용하는 것이기 때문에 팀에 적용하기에 용이하다. (전사적으로 하려면 이 또한 어려운 일이다.)

첫 번째는 Daily Build 이다.

이는 SVN이나 소스세이프와 같은 소스 관리 시스템과 함께 적용되어야 한다. Daily Build는 매일 새벽 3시에 소스관리시스템으로부터 소스를 꺼내서 자동 빌드 하는 것이다. 새벽 3시인 이유는 혹시 라도 야근을 하는 사람이 있을 때를 배려하는 것이다. 중요한 것은 출근했을 때 빌드가 되어 있으면 된다. 팀은 매일 아침에 새로 빌드 된 최신 설치본은 손에 넣을 수 있다. 이를 통해서 팀원 전체가 항상 안정적으로 빌드되는 동기화된 소스를 가질 수 있다. 소스관리시스템은 대부분 사용하고 있을 테니, 적당한 머신을 구하고 날 잡아서 자동 빌드 되도록 구성만 한번 하면 된다.

Daily Build에 대한 자세한 내용은 아래에 있는 조엘의 글을 참고.
Daily 빌드가 당신 곁에 있습니다 - 조엘
http://korean.joelonsoftware.com/Articles/DailyBuildsAreYourFriend.html

두 번째는 Runtime Check도구의 적용이다.

Bounce Checker와 같은 Numega제품이나 MS가 제공하는 Application Verifier, Driver Verifier 등이 바로 그것이다. Runtime Checker들은 실행시간 중에 메모리 누수가 있는지, 데드락이 발생하는지, 메모리를 덮어 쓰는지, 기타 제한된 동작을 수행하는지에 대해서 보고한다. 이런 오류 들은 그냥 사람이 테스트해서는 발견하기 쉽지 않다. 메모리를 일부분 덮어쓰는 경우 결함의 영향이 뒤늦게 엉뚱한 부분에서 나타나는 경향이 있기 때문이다. 개발자 테스트나 자동 테스트를 수행 할 때 이들을 통해서 테스트를 하면, 이런 오류를 빨리 잡아 낼 수 있다.

마지막으로 세 번째는 Static Check 툴의 도입이다.

Static Check는 작성된 소스코드를 빌드하기 전에 검토해 주는 툴이다. MS Word에 맞춤법 검사기와 비슷하다고 생각하면 될 것이다. 이는 소스코드를 분석하여 파라메터의 개수와 같이 단순한 것부터 보안 취약점이나 기타 특이사항들을 분석해 낸다. Static Check의 최대 장점은 테스트 케이스와 상관없이 전체 코드에 대해서 분석을 한다는 것이다. 테스트 케이스가 없는 코드나 에러처리와 관련된 코드는 테스트 되기 어려운데 이 툴들은 이 부분에 대해서 어느 정도 검증을 해 준다. Static Check 툴로는 다음과 같은 것들이 있다.

* Prevent - Coverity
* K7 - Klocwork
* CodeSonar - GrammaTech
* PREfast - Microsoft
* Airac - 서울대
* Lint(splint) - 오픈소스


그림 2 Static Check 툴 PREFast 동작 방식 - Microsoft

맨 위에 있는 Coverity사의 Prevent 제품은 MySQL의 소스를 분석해서 알려지지 않는 결점을 잡은 것으로 유명하다. 이 중에서 손쉽게 구해서 실무에 적용해 볼 수 있는 것은 Microsoft의 PREFast가 거의 유일하다. FREFast는 C/C++의 기본적인 코딩 에러를 탐지하며 160여개 항목을 탐지해 낸다. WDK(Window Driver Kit)에 포함되어 있으며, Driver 개발할 때 주로 사용된다. 라이선스상 문제가 있긴 하지만, 일반적인 C/C++ 어플리케이션도 검증해 볼 수 있으며 실제로 Visual Studio 2008 Team Suite의 Static Analysis 기능으로 PREFast가 들어간 것으로 알려져 있다.


그림 3 Visual Studio 2008 Team Suite에 포함된 Static Check 기능

이들 Static Check툴은 각 개발자의 빌드 프로세스나 Daily 빌드 머신에 설치해 놓고 매번 빌드 시에 한 번씩 자동으로 실행되도록 설정만 해두면 그 효과는 즉시 볼 수 있다. 또, 효과도 매우 좋다. 필자의 팀을 고생시킨 버그가 있었는데, 원인은 printf류의 가변 파라메터를 가지는 함수에 파라메터 개수가 잘못 들어간 것이었다. 이 버그는 코드리뷰, 통합테스트, QA 를 거치면서 전혀 발견되지 않았고, 증상은 가끔 알 수 없는 이유로 크래시가 발생하는 것이었다. 원인을 찾은 후에 유사한 오류가 더 있는지 수동으로 직접 확인했었는데 한 두 개가 발견된 것이 아니었다. 우리 팀이 이 도구를 사용하고 있었더라면 피할 수 있었던 버그였다.

지금까지 일정을 준수하고, 프로젝트를 성공시키기 위하여 어떻게 해야 할지에 대해서 개발팀의 입장에서 생각해 보았다. 또, 구현단계로 들어오는 입력과 나가는 출력을 검토하여 결함을 제거하는 방법을 살펴보았다. 여기서 언급된 내용이 만병통치는 아니지만 프로젝트의 성공과 삶의 질 향상 이라는 두 마리 토끼를 잡기 위한 첫 시발점이 되기에는 충분할 것이라 생각한다.

- 출처 : 안철수연구소 -
좋은정보가 되셨다면 아래 한번 클릭해주세요^^


댓글