신현묵 오픈헬스데이터 이사가 블로그에 게재한 글을 편집한 뒤 모비인사이드에서 한 번 더 소개합니다.
대부분의 프로젝트는 실패한다.
처음 세웠던 계획대로 진행되는 경우는 거의 본적 없다.
원숭이도 나무에서 떨어지고, 아키텍트도 당연히 실패를 자주 만나게 된다. 그리고, 프로젝트는 언제나 성공하지 않는다. 성공과 실패를 거듭할 뿐이다. 여기서 실패를 어떻게 다루느냐에 따라서 아마추어와 프로의 차이는 극명하게 구분된다.
아마추어는 실패를 변명하기에 급급하지만, 프로는 실패를 냉정하게 인정하고, 실패를 하게 된 이유를 찾고, 똑같은 실패를 반복하지 않기 위해서 실패의 원인에 대해서 분석하고 리뷰한다.
많은 실패를 거듭할수록 전문가가 된다. 전문가는 실패를 반복하지 않기 위해 언제나 실패에 대해서 필요한 리뷰 스킬을 높이게 된다. 이번 이야기에서는 필자가 지켜보았던 미니 프로젝트를 기준으로 실패에 대한 이야기를 해보도록 하겠다.
여기서 이야기하는 프로젝트는 처음부터 실패가 될 것으로 예견되었다. 그리고 결과대로 실패했다. 결론적으로 해당 팀이 해체됐고, 관련된 개발자들은 흥미를 잃고 해당 업체를 떠나게 되는 상황까지 진행됐다.
문제가 더욱 심각한 것은 이러한 실패의 이유에 대해서 문제를 지적하고, 향후 그 처리방안을 경영진에게 제시했지만, 결론적으로 회사의 리더의 생각이 변화하지 않았기 때문에 ‘실패에서 주는 경험’이 제대로 전파되지 못했다. 하지만, 아키텍트는 이러한 실패에 대해서 분명하게 기록해두고, 다시 그러한 실패를 하지 않도록 준비하는 것이 전문가로 성장하는 가장 중요한 버릇 중의 하나라고 이야기하겠다. 아키텍트가 아니라고 해도 개발자는 자신만의 노트로 ‘실패’를 기록해야 한다.
어떤 실패한 프로젝트에 대한 리뷰
실패에 대해서 정의할 수 있는가? 이 기준에 대해 느슨하게 적용하면 대부분의 프로젝트는 실패할 이유가 없어지며, 매우 엄격하게 적용하면 대부분의 프로젝트는 실패라고 기록될 것이다.
필자는 프로젝트의 성공과 실패의 요소에 있어 가장 중요한 것은 ‘비용’이다. 계획보다 많이 투자되면 그 프로젝트는 ‘실패’라고 평가한다. 가능하다면, 아키텍트를 목표로 하고 있는 개발자라면 모든 프로젝트의 기준과 투입 인력, 시간과 하드웨어 리소스 등을 모두 ‘비용’으로 환산하는 방법을 터득하는 것이 좋다.
가능하다면, 필자는 이 기준으로 프로젝트를 평가한다.
이 기준에 따라서 필자가 지켜본 미니 프로젝트를 평가해보자. 소프트웨어 개발자가 실제 일하는 것이 모두 비용이고, 그들이 투입되고 생각하고, 무언가를 하는 행위들은 대부분 모두 ‘비용’으로 환산할 수 있다. 이러한 비용을 기준으로 프로젝트의 기준을 세우는 원칙은 다음과 같다.
소프트웨어 디자인과 기획에 30%, 실제 개발에 50%, 테스트에 20%를 투여하는 법칙이다. 다만, 이 수치에서 약간의 차이는 투입되는 팀원이나 회사의 사정에 따라서 조금씩 달라지기는 하지만, 가능하면 저 수치를 지키려 한다.
그동안의 필자의 경험으로 느껴지는 저 수치는 약간의 조정이 있을 수 있으나, 국내의 프로젝트에서는 대부분 일치하거나 근사치로 정의될 것이다. 이번 이야기에서 언급하려는 프로젝트는 2013년도에 필자가 실패한 프로젝트의 사례에 해당한다.
이 규칙에서 기획에 30%의 투자가 있었어야 했는데, 실제 초기 기획에 2%도 안 되는 투자 후 실제 개발이 진행되면서, 프로젝트가 제대로 진행되지 않는 케이스가 발생했다.
물론 이번 사례는 작은 스타트업에서 매우 작은 외주 프로젝트를 진행하는 일이었는데, 실제 프로젝트에 참여할 팀원의 구성이나 팀워크, 주된 목표치에 대한 설정 등이 제대로 서술되지 못하면서 기획이 제대로 진행되지 못했다.
작은 모바일 프로젝트였고, 필자가 판단하기에 4주면 넉넉하게 해결될 프로젝트가, 필자의 계산착오로 4개월간 뒤틀린 프로젝트로 벌어지게 된 것이다. 필자는 왜 이런 실수를 하게 된 것일까?
기본적으로 ‘린 개발 방법’이나 ‘에자일 방법’과 같은 방법론의 문제가 아니라. ‘초기 기획’이 부정확한 상태에서, 팀워크도 갖추어지지 않고, 소통이 안 되는 팀원들의 보고체계가 붕괴된 상태로 프로젝트가 지속되면서 팀 자체가 와해되어 버린 아주 엉터리같이 진행된 프로젝트가 됐다.
목표도 불확실한 상태에서 기획이 제대로 진행되지 않았고, 서버 개발자의 능력 부족과 아이폰, 안드로이드 앱 개발자의 자기 멋대로 전횡과 서버 개발자가 이중으로 서버 인터페이스를 구현하면서 보고체계까지 제멋대로 진행된 아주 최악의 프로젝트가 진행되었다는 것을 프로젝트 후반부에 가서야 알 수 있었다. 말 그대로 전형적인 실패사례가 된 것이다.
가장 먼저 이야기한 ‘기획’이란 팀 빌딩과 목표 수립과 같은 부분에 대해 제대로 된 접근을 수행했어야 했는데, 이 부분에 대한 고려와 협의 없이 진행되면서 프로젝트가 일정에 떠밀려 진행됐다.
어떻게든 중간에 올바른 방향으로 유도하려고 했으나, 언제나 입버릇처럼 말하듯이 ‘한번 기본이 뒤틀린 경우, 다시 바로 잡을 수 없다’가 정답이고, 그 여파로 인해 많은 비용과 시간적인 소모, 정력적인 소비까지 매우 불유쾌하게 진행된 프로젝트였다.
결과적으로 이 프로젝트는 마무리 됐지만, 이 프로젝트를 참여하게 된 팀원들은 모두 해산됐고, 서버 개발자만 빼고는 모두 팀에서 해체가 됐다. 물론, 해당 문제들을 보완한 이후 프로젝트를 본래의 궤도로 올려놓긴 했지만, 명세화가 절실하게 필요하고, 이를 리뷰해야 한다.
이 프로젝트의 가장 큰 원인은 개발에 참여한 개발자나 디자이나, 기획자나 PM의 문제가 아니라, 전체적인 개발의 틀을 만들어 주어야 하는 ‘개발회사의 경영진’이 가장 큰 문제였다. 말 그대로 ‘인사’ 문제였다. 그중에 몇 가지의 문제들에 대해서 언급해보자.
개발자의 의사소통의 문제
후반부에 개발과 관련된 보고체계의 문제점은 서버 개발자와 클라이언트 개발자 사이에 숨겨왔던 문제가 드러났다. 가장 큰 원인은 ‘보고’를 제대로 하지 않았다는 것이다.
안드로이드와 iOS의 앱 개발을 동시에 진행했는데, PM이 인터페이스를 ‘동일’하게 추상화해서 구현하라는 방향성에 대해 클라이언트 개발자들과 서버 개발자들이 서로 협의한 것이 아니라, 서버 개발자가 클라이언트 개발자들의 요구조건을 모두 받아들여, 인터페이스가 두배로 늘어나고, 테스트와 관련된 처리 방안들이 모두 증가하게 된 것이다.
실제, 클라이언트에서 구현해야 하는 상당 부분의 기능들을 서버에서 구현하게 한 것은 향후 Web개발을 일부 처리하기 위한 방안이었는데, 이 부분들이 모두 무시된 채로, 클라이언트 개발자들 간에 자신이 하고 싶은 개발을 추진하면서, 서버 개발자가 의지 없이 끌려다닌 결과물이 됐다.
개발 일정이 늘어나고, 테스트도 진행되지 못하면서, 품질이 저하되는 것뿐만 아니라, 전체적인 프로젝트가 모두 붕괴됐다. 참으로 애통스러운 상황을 지켜봐야 하는 마음은 참으로 아픈 경험이다.
그래도, 최악의 프로젝트였지만, ‘테스트’가 좀 더 명쾌했다면 이 프로젝트는 초기에 문제를 잡을 수 있는 가능성이 있었다. 그래서, ‘테스트’에 대해서 몇 가지 더 정리해봤다.
테스트, 그 계획과 실행의 전부
과연, 테스트의 적정선은 어느 정도 인가? 소프트웨어 개발에 있어서 테스트에 투입되는 비용이나 기간에 대해서 근접한 수치를 보여주거나 적절한 경험성을 부여하는 경우가 매우 드물다. 다만, 경험자의 직관에 의존하는 경우가 많거나, 각 개발사의 프로세스에 따라서 정형화되어 있는 경우가 많다.
실제 자기 자신에게 다음의 화두들을 던져보자.
– 정말로 테스트 커버리지 100%의 테스트란 존재하는가?
– 제품 개발 시간과 테스트 코드의 비율은 어느 정도가 적정한가?
– 개발에 착수하기 전에 테스트를 얼마나 준비해야 하는가?
– 통합 테스트는 매번 해야 하는가?
– 테스트 전담자는 있어야 하는가?
– TDD는 비용 합리적인가?
– 과도한 테스트란 어떤 것을 의미하는가?
– 실제 개발환경에서 테스트란 무엇인가?
– 현장 품질 커버리지란 무엇인가?
위의 질문에 대해서 독자들은 얼마나 명쾌하게 답변을 할 수 있을까?
테스트에 대해 유명한 ‘Kent Beck’의 말을 인용해보자.
I get paid for code that works, not for tests, so my philosophy is to test as little as possible to reach a given level of confidence (I suspect this level of confidence is high compared to industry standards, but that could just be hubris). If I don’t typically make a kind of mistake (like setting the wrong variables in a constructor), I don’t test for it.
나는 코드가 작동하는지에 대해 보수를 받지, 테스트를 위해서는 보수를 받지 않는다. 그래서 나의 철학은 신뢰할 수 있는 수준에 도달하기 위해 가능한 한 테스트를 적게 한다는 것이다.(신뢰할 수 있는 수준이라는 것은 업계 표준에 비해 높다. 조금 거만한 들릴지 모르지만). 만약 전형적인 실수(생성자에서 다른 변수를 설정하는 것 같은)를 하지 않는다면, 나는 테스트하지 않는다.
소프트웨어 개발자들에게 ‘테스트 환경과 테스트 조직, 테스트 문화에 대해서 강요하는 것이 바람직한가?’라는 물음에 필자는 이렇게 이야기하고 싶다. ‘개발자’에게 ‘테스트’를 강요하지 말고, ‘테스트한 경과’를 제시하고 ‘수정’과 ‘제대로 된 결과’를 강조하라.
일반적인 소프트웨어 개발에 대해 무지한 사람들의 반복적인 질문은 ‘소프트웨어 개발자들은 왜 테스트를 소홀하게 하는가?’라는 질문을 버그가 발생할 때마다 이야기 한다. 대부분의 소프트웨어 개발은 ‘목표’가 불명확하기 때문에 ‘버그’가 발생한다고 생각한다.
아마도, ‘개발자’에게 사용자의 ‘제약사항’과 ‘하지 말아야 할 행위’에 대한 언급이 없었다면, 개발자는 문제 해결을 위해 상당 부분 위험요소를 건너뛰거나 넘어서게 된다. 물론, 적절한 여유시간과 풍부한 리소스를 제공한다면, 튼튼한 소프트웨어를 만들기 위해서 노력한다. 하지만, 일정이 정해지고, 목표가 명확한 SI성의 프로젝트 경우에는 ‘목표’를 향해서 가장 빠른 코드 만들기를 강요하기 때문에, 이때에 만들어지는 ‘버그’의 대부분은 개발자의 실수이기보다는, ‘요구사항’에 대한 부정확한 전달 때문이다.
별 요구사항이 없는 것 같은 ‘DataGrid’를 만들어 달라고 이야기했지만, 사실 고객은 엑셀 정도의 기능을 원하고 있다. 하지만, 일정과 비용상의 문제 때문에 단순 데이터의 표현을 위한 ‘DataGrid’인 것처럼 요구를 하는 경우가 대부분이다.
이때에 개발자는 당연한 것처럼 최소한의 제약사항과 요구사항을 통해서 ‘숫자’만을 처리할 수 있는 ‘DataGrid’를 만들지만, 고객은 개발에 착수함과 동시에 다양한 요구사항들을 요구한다. 문자열을 처리해달라, 날짜, 함수 등등… 그리고, 종이 출력도 자연스럽게 되게 해달라고 한다.
개발자는 중간에 발생한 요구사항과 제약사항에 최대한 맞추려고 기능들을 구현하다 보면, 당연한 것처럼 특정 이슈만 처리하는 기능으로 구현되고, 다른 프로세스에서는 당연한 듯이 버그와 같은 현상을 발생시킨다.
그럴 때에 고객은 이야기하고, 개발회사의 사장도 이야기한다. ‘개발자가 테스트도 없이 소프트웨어를 만들고 있다’고. 이것이 현실이다.
대부분 소프트웨어 개발에 대해서 무지하기 때문에, 이런 일이 반복된다. 필자도, 이러한 경험을 최소한으로 하려고 했지만, 역시. 회사의 대표가 되어서 프로젝트의 계약부터 관여하기 전에는 이러한 문제들을 모두 해결할 수 없는 게 정답일 것이다.
필자는 단언한다. ‘소프트웨어 개발자에게 넉넉한 일정과 풍부한 리소스를 제공하지 못한다면, 소프트웨어 개발자가 모든 것을 해결할 것으로 기대하지 말아라’. 다만, ‘소프트웨어 개발자들이 보다 원활하게 개발에 전념할 수 있도록 다음과 같은 필수조직이 따라붙어야 한다.
하나. 요구사항에 대해서 고객과 꾸준하게 소통할 수 있는 담당자나 조직
둘. 정해진 일정에 맞추어 기능이 동작할 수 있게 하는 테스트 담당자나 조직
하지만, 보통의 스타트업이나 작은 SI를 전담하고 있는 기업의 경우 위의 가장 중요한 두 조직이나 담당자들이 대부분 부재중이거나 기능이 모호한 경우가 많으며, 위의 두 가지 기능을 모두 담당 개발자의 책임으로 귀속시킨다.
만일 이러한 기능이나 리소스를 모두 담당 개발자에게 귀속시키고 있는 회사나 조직에 있다면, 조직을 다시 만들거나, 해당 기업을 빠른 시일에 빠져나가는 것이 가장 현명한 방법일 것이다. 대부분 소프트웨어 개발에 무지한 경우 이 두 기능을 너무 소홀하게 하고, 개발자들이 대부분 야근과 휴일 근무를 밥먹듯이 하게 되는 경우가 이에 해당된다.
실제 필자 또한 경험이 풍부했지만, 실제 기업의 인사권과 경영권이 없었기 때문에 이에 대해서 해결할 수 없는 경우를 또 만났기 때문이다. 그래서, 또 실패했다. 아무리 경험 많은 사람이라고 하더라도, 이미 알고 있는 내용이라고 하더라도 그것을 실제 바꾸지 못한다면, 필패한다는 것이 소프트웨어 개발의 현장이다.
그래서, 필자도 크게 실패한 경험을 또 하나 기록에 남기게 됐다.
체계적인 품질관리 지표
개발과정에서 발생되는 요구사항의 지표에 대해서 NIPA의 ‘SW Visualization’을 참조하면 요구사항 추적성, 요구사항 달성률, 요구사항 커버리지의 3가지 지표에 대해서 서술하고 있다. 여기서 달성률과 커버리지는 100% 처리가 되는 것을 목표로 움직이는 정략적인 지표로 보면 되고, 실제 개발현장에서 주목할 부분은 요구사항 추적성을 주목해야 한다.
개발 공정별로 요구사항의 일관성이 어떻게 유지되고 있는지 확인하면서, 형상관리가 등록된 내용의 변경률과 비교하면서 요구사항의 변화된 추이를 꾸준하게 주목해야 한다. 대부분, 이 부분 때문에 개발이 뒤틀리는 진입점을 제공하게 된다.
품질검증에서 사용되는 정적인 테스트는 ‘코딩 표준 준수율’과 ‘메트릭 만족률’, ‘정적 분석 이행률’을 기반으로 진행된다. 대부분 이 정적인 테스트는 ‘자동화 도구’를 사용하여 코드의 룰과 만족 여부를 확인하기 때문에 결국은 ‘개발 비용’을 얼마나 투자하느냐에 달려있는 부분이라고 할 수 있다. 특히, ‘정적 분석 이행률’과 같은 SW 실행 전에 잠재적인 결함을 분석하는 것은 이러한 투자 없이는 대부분 이룰 수 없는 수치이다. 그래서, 보통 ‘정적 테스트’는 제대로 갖추어진 개발 조직이 아니라면 성립하기 어려운 지표가 된다.
보통, 이 ‘정적 테스트’ 지표를 얼마나 진행하고 있느냐에 따라서, 소프트웨어 개발 조직의 성숙도를 체크할 수 있으며, 소프트웨어 개발 조직에 얼마나 투자를 하고 있느냐에 대해서 알 수 있는 지표이기도 하다.
보통은 품질검증에서 동적 테스트로써 요구사항 검증방법과 구조 검증방법이 진행되는데, 마찬가지로 구조 검증인 구조적 커버리지 또한 Basic path, Statement, Branch, MD/DC Coverage 등을 선택해야 하므로, 이 또한 개발 조직의 투자 없이는 이루어지기 힘들다. 그래서, 대부분의 개발 조직 현장에 가보면 기능 검증, 비기능 검증, 정형 검증, 사용자 검증 중에 기능 검증과 사용자 검증만을 취해서 품질검증을 하는 경우가 대부분이다.
소프트웨어 개발자에게 ‘품질검증’을 제대로 요구하기 원하는 조직이라면, ‘정적 테스트’를 수행할 수 있는 투자나 일정, 준비 또는 품질 관련 조직이 세팅되어 있어야 한다. 이러한 단계 없이, 개발자에게 ‘테스트’를 제대로 하지 않는다고 강요하는 개발회 사는 정말 크게 잘못된 케이스라고 보면 된다. 그런 회사는 배울 것도 없으니, 피하는 것이 최선이다.
또한, 기능 검증이나 비기능 검증 또한 테스트 케이스에 대한 자동화된 방법들을 사용하지 않는 다면, 이 또한 개발자에게는 상당히 모호한 테스트들만이 존재하게 된다.
좌우지간, 소프트웨어 개발의 시각화
소프트웨어 개발의 경험자라고 하더라도, 소프트웨어 개발 현장에서 일어나는 일들을 모두 파악할 수 있는 방법은 ‘직감’ 밖에 없을 것이다. 그래서, 소프트웨어 개발에 있어서 적정한 범위까지 개발의 과정을 ‘시각화’하는 기준이 필요하다.
하지만, 이 ‘시각화’는 말 그대로 ‘과비용’으로 책정되거나, 소프트웨어 개발을 하기도 어려운 일정과 시간에 촉박한 경우에는 이 시각화의 최소 영역에 대해서 고민하고 결정해야 한다. 완전한 시각화를 이룰 경우에는 소프트웨어 개발 관리조직과 품질조직, 테스트 조직 등의 PM관리체계가 완비되어 있는 경우에만 이러한 과정을 수행하는 것이 최선이다.
그리고, 중요한 케이스나 문서 등에 대해서 품질관리 조직과 PM조직이 해당 문서를 작성하는 것이 되어야지, 각 개발자에게 이러한 업무를 전가하는 방식으로 진행되어서는 문제가 해결되지 않는다. 언제나, 품질조직은 옥상옥이 되어서는 안된다.