http://agile.egloos.com/2970034

테스팅에 관련된 글중 최근에 많이 회자되었던 글입니다. 두시간 후에 수술에 사용될 프로그램에 대한 테스트 플랜을 작성하라는 내용입니다. 수술 대상은 바로 자신입니다. 안정성을 검토하는 테스트 자체에 대한 검증문제죠.

만약 저에게 이런 문제가 주어진다면 저는 이렇게 답할지 모릅니다.
그냥 두시간 남은 인생 밖에서 놀다 오렵니다.
너무 무책임한가요?

제가 소프트웨어를 개발함에 가지는 기초적인 관념중 하나는 "결점 허용 모델"입니다.

이 모델을 가지게 된 것은 몇년전의 경험때문이기도 합니다. 대부분의 포인터 어레이가 null로 초기화 되어야 하는데 어느날 갑자기 동작중에 잘못된 메모리 참조를 일으키는 것이었습니다. 포인터 값도 이상한 것이었습니다. 몇시간을 디버깅을 해보다가(일단 포인터 연산부터 조사했죠) 해당 메모리 영역을 직접 보니 광활한 0의 영역에 비트 하나가 튀어 있는 것이었습니다. 심지어 0으로 수정하려고 해도 안됩니다. 이름하여 메모리 비트 하나가 물리적 오류가 일어난 것이었습니다. 컴퓨터를 껐다 켜니 잘 되더군요. 아마 메모리 방전 회로에 문제가 생겼나 봅니다. 서버용 메모리에 왜 ECC를 쓰는지 대충 이해도 가더군요.

즉 설사 코드 자체로는 완전 무결하다 하더라도 생각치 못한 요소에 의해 오동작을 할 수도 있다는 점을 알게 되었습니다. 게임 프로그램 정도쯤 되면야 고객센터로 대충 커버가 됩니다. (물론 유저들은 욕을 하지만) 허나 의료용 기계라던가, 핵발전소쯤 되면 이야기가 달라지는 거죠.

사람이 직접 손으로 하는 것이 아닌 기계와 소프트웨어로 동작되는 시스템의 경우 관리자와 그 관리자를 위한 강제 정지 버튼을 주는 것이 일반적입니다. 가끔 영화에서 비행기의 컴퓨터가 미쳐버리면 총으로 쏴버리고 수동 조정을 하는 것도 비슷합니다. 예기치 못한 상황이 발생하였을 때 수퍼 울트라 에러복구 프로시져가 동작하는 것입니다. 뉴럴 네트워크로 움직이는 사람이란 모듈이죠. 물론 이 모듈도 안정성에 심각한 문제가 있긴 하지만요.

위의 문제로 돌아가서, 프로그램이 동작하고 그 프로그램에 따라 집도의가 수술을 할 것입니다. 프로그램이 오류를 일으켰습니다. 저의 상태에 문제가 생겼습니다. 이때 필요한 것이 복구모듈인 의사인 것입니다. 단지 프로그램만으로 저의 목숨이 결정된다면, 안전장치인 의사도 소용없다면 그 수술은 너무나 위험해서 그냥 두시간동안 행운을 바라는 수밖에 없다라고 보는 것입니다.

전형적으로 테스팅은 고려되는 상황만이 반영됩니다. Coverage라고도 하는데 테스트의 능력에 의해 동작이 보장되는 환경이 결정이 됩니다. 테스트에 대해 충분히 오류를 검증하였다 하더라도 그것은 테스트가 커버한 환경에서만 그런 것입니다. 테스트 집단이 보유한 지식에 의해 제한이 된다는 것이죠. 반대로 이 세상은 무한한 것입니다. 가령 Windows XP에서 잘 돌던 프로그램이 Vista에서는 뜨지도 못하는 것이죠. (동작 환경에 대한 요구사항이긴 하지만.. 그냥 예제로 받아주세요) 개발하던 당시에는 Vista란 존재하지 않았은까요.

제가 만드는 소프트웨어를 디자인 하거나 검증할때는 일반적인 정상적인 동작 외에도 하나를 더 요구합니다. 잘못된 인풋이 들어왔을때 시스템을 폭파시키지는 않는지 검증하죠. 인풋의 출처가 같은 시스템내의 다른 모듈 혹은 그 자신일 때도 포함됩니다. 버그가 존재할 가능성이 있기 때문이죠. 버그가 하나도 없이 깨끗한 코드란 존재를 증명하기 어렵다고 보기 때문입니다. 존재할 수는 있겠지만 그 존재를 증명하긴 거의 불가능 하다는 것이죠. 그래서 가끔 오동작 하고 미쳐버릴 수 있다고 가정을 해 버리고, 그랬을때 보호/복구 모듈이 동작하거나 최악엔 사람이 개입하여 극단적인 상황은 피할 수 있는지를 확인합니다. 당연히 코드만의 영역은 아닙니다. 해당 프로그램과 관련된 모든 것들이 조사대상입니다.

테스트 커버리지는 Cost(비용)과 연관이 있으므로 적당한 선에서 끝나게 됩니다. 이때 정상 동작에 관련된 커버리지는 약간 낮추는 한이 있어도 세이빙 된 Cost를 모두 위의 항목에 투자합니다. 예상 가능한 최악의 상황에도 살아 남을 수 있는가. 물론 그 예상을 넘어서는 경우엔, 죽어야죠. 그래도 살기 위해 최선을 다하는 것입니다. 잘 동작하는지 확인도 중요하지만 삐그덕 했을때도 문제가 없는가에 대한 고려는 상당히 중요합니다.

일전에 A모 메타사이트가 과전압에 서버가 사망한 후 복구에 몇시간이 걸린 사건을 보더라도, 이 세상의 위험 요소는 거의 무궁무진 합니다. IDC에 전기가 나간게 아니라 복구 과정에서 문제가 생길줄이야!

  1. Commented by CK at 2007.02.14 14:21

    자신의 수술을 위한 프로그램을.. 꼭 짜야 하나? ㅋ
    나도 그냥 두시간 동안 놀다올래~~

  2. Commented by 형기의 자료공간 at 2007.02.22 03:12

    저도 님과 비슷한 경험을 한적이 있습니다.

    기본 API에도 버그가 있을 수 있다는 경험이었습니다.
    물론, 아주 특별한 경우에 해당하는데요..

    폰개발 프로젝트의 경우 폰에 올려서 확인하는 과정이 많이 걸리기 때문에..
    Simulation해 볼 수 있는 Layer를 만들고, Windows환경에서 먼저 확인한 후 폰에 포팅하게 됩니다.

    그러던 중 Windows에서 fread함수에 버그가 있었습니다.
    대부분의 경우에는 잘 되었는데, 특정 데이터 파일의 경우에는 fread를 하던 도중 1byte를 건너뛰는 것이었습니다. ㅠㅠ
    (fread란 녀석이 버퍼를 공유해서 쓰게 되는데 버퍼를 쓰는부분에 문제가 있었던 것으로 보여집니다.)

    나중에 Win32 API로 변경하니 정상동작 하였습니다.
    아직도 왜 그 data파일에서 fread로 읽어들일때 1byte가 건너뛰게 되는지 이해할 순 없습니다.

    물론 내부적으론 이때에도 예외처리를 하여 폭파되거나 하는일은 없었지만..
    아직도 이해가 안되는 기억으로 남아있습니다.

    디버깅을 할때에는 원점에서 검토하는 습관이 있습니다.
    심지어는 API수준까지도..