본문 바로가기
Programming

프로그래머의 숙명 - 버그편 Part. I

by BITINITIALIZE 2009. 5. 7.
728x90




프로그래머와 버그의 관계를 가장 적절하게 보여주는 이미지입니다.
또 지랄이네ㅡㅡ; 뭐 표현의 선택이야 어찌되었든 프로그래머라면 누구나 공감할 것 입니다.


1. 버그, 정체성편.

버그란 무엇일까요? 쉽게 말해 소프트웨어에 포함된 오류입니다.
제 아무리 멋지고 뛰어난 프로그램이라 할지라도 결국 사람의 생각과 손으로 만드는 것, 오류는 반드시 존재합니다.

아 물론,

#include <stdio.h>
void main(void)
{
   printf("Hello World~");
}

이런 간단한 프로그램에서는 버그가 없습니다. 있을리가 없고 있어서도 안되겠지요.

프로그램(소프트웨어)은 짧게는 수십개에서 많게는 수 천/수 만가지의 온갖 논리로 똘똘 뭉쳐있습니다.
논리의 취약점, 잘못된 언어 사용, 생각하지 못했거나 잘못된 가정 등으로 인해서 결국은 버그가 발생합니다.

처음부터 버그없이 만들면 되잖아요?

최고 출력으로 코딩하는 프로그래머는 방대한 양의 논리구조, 자료구조, 복잡한 알고리즘,
자신이 만든 클래스와 메소드,
유틸리티성 함수와 온갖 잡다한 변수명, 심지어 각종 서브 폴더명까지
수만가지 사항을 머리속에 한꺼번에 유지하고 
컴퓨터 앞에 앉아 오랜 시간동안 프로그램을 만듭니다.

프로그래머의 책상에는 두꺼운 명세서나 설계문서는 있을지언정 버그없이 프로그램을 만드는 법이나 절차는 
존재하지 않습니다.
다만, 코드의 질을 높이기 위한(결국은 버그를 줄인다는 것과 같은 맥락이기도 하죠) 방법론은
많이 존재합니다.
그럼에도 불구하고 사람의 머리와 손에서 나오는 실수는 없앨 수 없는 법입니다.

따라서 현재의 방어적인 프로그래밍 관점은 처음부터 버그없이 만드는 것이 아니라 버그를 최소화하고,
버그를 쉽게 고칠 수 있도록 하는 것 그리고 버그가 발생했을 때도 유연하게 대처하는데 그 의도가 있습니다.


2. 버그, 존재의 이유편.

그렇다면 버그가 생기는 이유는 무엇일까요?

 01. 프로그래머가 모른다

 많은 경우 버그는, 프로그래머(개발자)가 알지 못하기 때문에 발생합니다.
 이것은 다른 사람이 버그를 쉽게 찾는 이유이기도 한데, 대개 개밥을 먹지 않아서 발생합니다.
 (개밥먹기 : 자신이 만든 프로그램을 본인이 직접 사용하는 것, Eating one's own dog food, dogfooding)

 잠깐만요. 어떤 프로그램이 있고 그것을 만든 사람이 있는데, 만든 사람이 사용하지 않는다구요? 그래서 모른다구요?

 네, 맞습니다.
 대개 많은 프로그래머들이 이러저라한 기능들을 만들어서 자신의 프로그램에 넣지만 정작 만든 사람 스스로는
 사용하지 않는 경우가 꽤 있습니다. 따라서 너무 쉬워보이는 기능들도 가끔은 버그가 있게 마련입니다.

 프로그래머는 급한대로 어떤 기능을 구현하고 다 만들어졌다고 생각되면 한번 사용해봅니다.
 잘되네? 생각되면 다른 부분으로 넘어갑니다. 그럼 이 경우 버그가 존재할 확률이 존재합니다.


 02. 빈약한 테스트

 프로그래머는 의식적으로 그리고 무의식적으로 자신이 만든 프로그램의 취약하거나 빈약한 부분을 알고 있습니다.
 따라서 해당 부분을 빈약하게 테스트하거나, 테스트를 건너뛰는 경우가 있습니다.

 버그의 존재 가능성에 대해서 프로그래머가 암시적 또는 묵시적으로 알고 있다고 하더라도 개발자가 침묵을 지키면
 별 무리없이 다음 프로세스로 넘어가게 되며 소프트웨어의 출시 후 엔드 유저들에게 발견될 확률이 높습니다.

 규모가 큰 회사의 경우 QA팀(Quality Assurance)이 별도로 있고 QA팀이 있는 경우 개발자가
 만든 버그를 그대로 출시할 확률이 적겠지만 우리나라의 모든 소프트웨어 회사들이 모두 QA가 있는 건 아닙니다.

 03. 정말 몰라

 정말 모르는 경우도 있습니다. 도저히 해결할 수 없는 매우 어려운 기술적인 문제에 봉착하게 되는 경우입니다.
 버그를 알게 되더라도 해결하지 못하는 경우에는 문제가 발생되지 않도록 우회하거나 해당 기능을 없애야 합니다.
 물론 나 자신이 못고친다고 해서 다른 사람이 수정하지 못할 이유가 없겠지요.

 04. 버그가 아니야

 간혹 사용자들이 어떤 부분에 버그가 있다고 말하는데 실제로 버그가 아닌 경우가 있습니다.
 예를 들어, MP3 플레이어가 있고 파일열기로 MP3를 엽니다. 사용자는 OGG를 불어들이려고 시도합니다.
 OGG를 불렀지만 재생은 안됩니다. 사용자는 개발자에게 재생이 안된다고 버그가 있다고 항의합니다.

 이러한 경우 버그가 아닙니다. 파일열기에서 OGG를 불어올 수 있었다면 개발자는 OGG를 불어올 수 없도록
 막거나 OGG를 재생기능을 포함하거나 둘 중의 하나입니다. 이 경우 Bug Fixed가 아닌 Enhancement가 됩니다.

 05. 디버깅 교육에 대한 부재

 버그를 수정하는 일련의 절차를 디버깅(Debuggin)이라 합니다.
 저의 경우 대학교에 다니면서 프로그래밍 수업중 디버깅을 교육받은 적은 없습니다. 요즘도 비슷할 것 같군요.

 대한민국 개발자 대부분이 빠르고 효율적인 코드를 작성하도록 교육을 받지만 디버깅에 대해서는 배우지 않습니다.
 어찌보면 다소 무리수일 수 있을지 모르겠지만 대학교에서도 체계적으로 디버깅 학습법을 가르쳐야 할 필요가 있습니다.

 소프트웨어 공학론 수업중에 이론적으로 소프트웨어의 품질과 관련되어 몇 가지 방법론을 배우기는 하지만
 실제 디버깅 업무에는 도움이 되질 않습니다. 디버깅은 수많은 실습의 시간이 필요하기 때문입니다.

 대다수의 프로그래머들은 코드 작성에 많은 노력을 할애하지만 디버깅에 대한 학습은 여전히 뒷전이며
 비로소 실무 업무에 투입되거나 당해봐야(?) 그 중요성을 깨닫고 학습하게 됩니다.
 빠른 코드와 최적화 기법은 프로그래머에게 흥미롭지만 디버깅은 골치아픈 문제가 되버렸습니다.


3. 버그, 그 악마의 이름

프로그래머는 그들의 추론을 제한하기 위한 데이터를 항상 사용하지 않는다.
그들은 사소하고 불합리한 변경 작업을 수행하고, 종종 잘못된 변경 내용을 돌려놓지도 않는다. - Iris Vessey.



버그가 발생했을 때 잘못된 그리고 올바른 대처방법에 무엇이 있을까요?


잘못된 추측. 감으로 해결하기.


결함을 찾기 위해서 프로그램을 조금씩 변경하거나 프로그램 전체 또는 버그가 발생되는 부분에 대해서
마구잡이식으로 출력문을 남발하며 이와 동시에 올바른 결과가 나올 때까지 조금씩 코드를 바꿔봅니다.

이것은 프로그래머가 프로그램 또는 코드를 이해하지 못하는 상황에 비롯되는데 이 경우 코드를 바꾸며
무언가 동작하는 것처럼 취하려는 코드가 해가 될 수 있음은 물론입니다.

궁극적으로 이러한 대처법은 버그를 수정하기 위해서 또 다른 버그를 양산해 낼 수 있습니다.



미신을 믿어요.

"컴파일러도 사람이 만든거고 프로그램이야. 버그가 있을 수 있어. 
 그건 내 코드의 버그가 아니라 컴파일러의 실수란말야." from Newbie Programmer

정말이지 가끔은 컴파일러가 내가 의도하지 않은대로 코드를 생성할 수 있습니다.
그렇다고 해서 버그를 수정하지 않아도 되는 것은 아닙니다. 

컴파일러 또는 Third-Party에 있는 버그일지라도 버그의 수정은 여전히 우리가 해야 하는 것입니다. 
버그가 발생되었음을 알리는 징조가 있다면 어떤 경우를 막론하고 나의 실수로 가정하는 것이
정신건강에도 좋고 자기 자신을 위해서도 득이 됩니다.

있을 수 없는 버그가 발생했다면 어떻게 대처하시겠습니까?

1. 나의 실수로 인정하고 버그를 수정한다 : 알고보니 코드는 정상이지만 써드파티의 문제 또는 컴파일러의 문제로
판명되었다. 버그가 발생할 수 없도록 수정했고 나의 가치는 인정받을 수 있다.

2. 그럴리가 없다고 반문한다 : 무조건 내 잘못은 아니라고 박박 우긴다. 팀은 침체되며 사기는 저하된다.
써드파티 문제든 컴파일러 문제든 결국은 수정해야 하기 때문이다. 알고보니 내가 우긴대로 컴파일러나 써드파티 제품의
문제가 아니라 내 코드에 버그가 있었다! 이제 변명거리를 찾아야 한다.

컴파일러/써드파티부터 의심하느냐 원인 규명부터 할 것인가의 선택은 여러분의 몫입니다.


그 부분은 내가 코딩하지 않았어

대개 버그(오류)가 발생하는 부분에 대해서 자신이 작성한 것이 아니라 같은 팀원이 작성한 것일지라도
자신의 결함으로 인정하고 대처하는 것이 현명합니다. 

그 이유는 자신의 코드에 오류가 없다고 가정하는 경우 오류를 찾아내기가 더욱 힘들어지기 때문입니다.  



4. 오류 빨리 찾기

시간은 흘러가며 버그 수정에는 지체되고 있습니다.
마감 시간은 다가오고 어서 빨리 버그가 수정된 릴리즈 버전을 고객 또는 사용자에게 배포해야 합니다.
답답한 팀장은 내 등 뒤를 왔다갔다 하며 눈치를 주고 있으며 여러분의 손은 떨리기 시작합니다.
그 이유는 여러분이 어느 부분을 수정해야 할지 감을 못잡고 있기 때문입니다.


잠시 숨을 고르자

버그를 수정하기에 앞서 잠시동안의 여유를 가지도록 합니다.
시간적인 압박에 쫓기는 경우 성급하게 에디터부터 열고 버그를 수정하려 하지 말고 잠시 숨을 고르는게 좋습니다.
대개의 경우 시간적인 압박으로 버그를 수정하게 되면 또 다른 버그를 만드는 코드를 만들 수 있습니다.


오류의 재생산, 그리고 관찰


버그가 발생했다면 버그를 다시 관찰할 필요가 있습니다.
개발자의 PC에서 버그를 다시 구현하기 어렵다면 버그를 수정한다고 한들 수정된 것인지 확신할 수 있습니까?

먼저 어떻게 해야만 버그가 발생되는지 정확한 프로세스 다시 확인해 볼 필요가 있습니다.
개발팀에서 버그를 구현하기 어렵다면 버그의 수정 역시 힘들어집니다.


버그를 수정하기 위한 몸부림

[버그씨, 당신 지금 어디에 숨어있어요?]

가장 먼저 해야할 일은 짧게는 수 천, 수 만에서 길게는 수 십만 라인에 이르는 소스 코드에서 버그가 발생되는
코드 영역을 찾는 일입니다.

역시 가장 처음 해볼만한 시도로는 Debug Mode로 소프트웨어를 실행하고 관찰하는 일입니다.

규모가 큰 코드에서 버그를 발견하는데 시간이 오래 걸리거나 버그를 재생산하기 위해 다양한 작업을
선행해야할 경우 코드의 일부를 주석처리하고 빌드하는 것도 도움이 됩니다.

이러한 일련의 작업을 통해서 하고자 하는 일은 의심되는 영역을 좁히는 일이며 그 다음으로
Pointer, Register, Call Stack, Stack, Heap 등을 중점으로 확인합니다.


[필요한 모든 데이터를 확보하고 테스트하자]

컴퓨터 프로그램(소프트웨어)은 일반적으로 다양하고 많은 데이터를 처리합니다.
간단하게는 파일 입출력부터 소켓으로 송수신되는 데이터까지 다양하기 그지없습니다.
많은 데이터를 처리한다면 특정한 데이터에서만 발생하는지 확인할 필요가 있습니다.

거의 모든 데이터에서 잘 동작하고 특정한 데이터를 처리하다가 오류가 발견된다면
문제가 되는 코드에 대해서 찾기가 수월해집니다. 또한 어떠한 데이터 처리라도
문제가 발생되지 않는다면 데이터를 처리하는 코드에서는 문제가 없다고 확신할 수 있게 됩니다.


[공격적 디버깅]

- 전체 코드에 대한 리뷰를 진행한다
- 문제가 규명되었다면 해당 부분을 버리고 처음부터 다시 시작한다
- Assert, Print, Trace, Log 등 동원할 수 있는 모든 수단을 사용해서 완전한 디버깅 정보를 생성한다
- 컴파일러의 경고 수준을 최대한 높인 후에 발생되는 모든 경고에 대해서 수정한다
- 단위 테스트를 사용한다
- 반복문에서 간단하고 쉽게 보이는 부분일지라도 직접 순차 실행해본다
- 디버깅 후킹 함수를 만든다
- 버그를 수정하기 위한 별도의 예외처리 툴을 사용하거나 만든다




TO BE CONTINUED...


728x90

'Programming' 카테고리의 다른 글

카카오톡 브레이커  (4) 2021.02.04
AeroShake 구현하기  (1) 2010.04.21
HTML 에디터 구현  (19) 2008.10.01
온라인 업데이트 이야기  (2) 2008.08.09
예외처리 꼭 필요한가?  (10) 2008.05.08

댓글