소프트웨어 버그와 품질에 관한 소고
품질에 대한 개발자의 책임에 대하여
배경
최근 회사에서 한 API의 응답 필드를 non-null
타입에서 nullable
로 변경하는 작업을 진행하였다. 예상되는 호출처에 문의하여 문제가 생기지 않도록 사전 조사를 하고 진행하였지만, 배포 후 해당 API를 호출할 것이라 예상하지 못했던 팀에서 오류가 발생한다는 소식을 접했고 롤백을 진행하였다.
앞으로 이런 실수를 어떻게 예방하면 좋을지 고민하다 자연스레 소프트웨어 버그와 품질에 대한 생각으로 이어졌다. 이 글은 현재의 내가 바라보는 소프트웨어 버그와 품질 그리고 개발자의 책임에 대해 정리한 작은 기록이다.
품질에 관하여
대학에서 애자일을 처음 접하고, 실무에서 테스트 주도 개발(TDD)을 익히고 실천하다 보니 자연스레 익스트림 프로그래밍(XP)이 나의 소프트웨어 개발 철학의 중심을 차지하게 되었다. 그러다 보니, 내가 개발하는 소프트웨어에 대한 책임감을 느끼고 부끄럽지 않게 개발해 나가는 애자일에서의 장인정신 역시 나의 핵심 가치로 자리 잡게 되었다.
장인은 자신의 창작물을 결코 가볍게 여기지 않는다. 마찬가지로, 장인정신을 지닌 소프트웨어 개발자라면 자신이 만든 결과물에 대해 극한의 품질을 추구해야 한다. 소프트웨어에서의 버그는 곧 품질에 대한 직격탄이기에, 장인정신을 갖춘 개발자라면 자신의 결과물에서 버그가 발생하는 일을 결코 가볍게 넘기지 않을 것이다. 즉, 소프트웨어의 품질은 그것을 개발한 개발자의 온전한 책임이다.
QA(품질 보증)에 관하여
품질이 개발자의 온전한 책임이라고 말하면 QA에 대한 이야기가 나오리라 생각한다. QA는 말 그대로 품질을 보증하는 활동이기 때문이다. 하지만, 나는 품질을 QA에 위임하지 않는다. 품질은 소프트웨어를 만드는 개발자의 손에서 탄생하며 유지되기 때문이다.
TDD(테스트 주도 개발) 관점에서
요구사항을 테스트로 먼저 기술하고 그 테스트를 통과하도록 코드를 작성하는 TDD의 관점에서 QA를 바라본다면, QA 역시 미리 기술된 요구사항(테스트)과 다름이 없다. QA는 요구사항을 코드 외적으로 기술한 것일 뿐이며, TDD에서 작성한 테스트가 통과하는 것이 당연하듯 우리의 결과물은 QA를 당연히 통과해야 한다. 즉, QA는 결과물이 요구사항을 충족했는지 확인하는 절차이지, 숨어 있는 버그를 찾아내는 활동이 아니다.
물론 TDD가 중요하듯 QA 활동 역시 중요하다. 하지만, 소프트웨어의 품질을 QA에 위임하여선 안 되며 소프트웨어의 버그와 품질은, 그 세부 구현을 가장 잘 이해하는 개발자가 책임지고 예방해야 할 영역이다.
귀납의 한계 관점에서
과학에는 '반증주의'라는 패러다임이 있다. '반증주의'란 실험으로는 대상 가설이나 이론이 맞다는 것을 보여줄 수 없고, 오직 반증만 가능하다고 보는 패러다임이다. '반증주의'에 따르면, 어떤 이론이 10번의 실험을 통과하든 만 번의 실험을 통과하든 이론의 신뢰성에 영향을 주지 못한다고 본다. 이론을 반증하는 단 하나의 실험이 이제껏 이론이 맞다고 보여주는 수천수만 번의 실험을 의미 없는 것으로 만들 수 있기 때문이다.
'반증주의'는 귀납의 한계를 잘 보여주는 패러다임이다. 이제껏 관찰하니 아침에 태양이 떠오르고 저녁에 태양이 저물었다고 해서 내일도 똑같을 것이라고 말할 수 없다. 내일도 오늘과 같이 아침에 태양이 떠오르고 저녁에 태양이 질 것이라고 말하려면, 단순한 과거의 관찰(귀납)에 기대기보다는 그 현상을 연역적으로 설명할 수 있어야 한다.
QA 역시 귀납의 한계를 넘어설 수 없다. 현재의 시스템이 아무리 많은 QA를 통과했다고 하더라도 그것이 소프트웨어의 견고성을 보장하지 않는다. 소프트웨어가 마땅히 수행해야 할 명세를 충족했다는 사실 이상을 보장하지 못하는 것이다.
결국, 소프트웨어의 품질은 코드를 작성하는 개발자가 연역적으로 풀어나가는 것에 달려있다.
정책과 자율에 관하여
정책
소프트웨어의 품질을 개발자가 아닌 그 밖의 프로세스를 통해 달성하고자 하는 시도들도 자주 봐왔다. 하지만, 개발자에게 제약을 가하는 정책은 신중히 도입해야 할 문제다. 소프트웨어의 견고함과 품질은 앞서 설명했듯 개발자의 손에서 탄생하고 완성된다. 그러나, 정책은 개발자의 손을 떠난 뒤에 개입하는 것이다. 정책은 본질적으로 근본 원인을 다루는 것이 아닌 차선책일 수밖에 없다. 그리고 그 차선책에는 아래의 단점들이 따라오기에 정책의 도입은 신중에 신중을 기해야 한다.
정책은 본질적으로 개발자의 자율적인 활동을 제한하며, 이는 필연적으로 개발자의 생산성을 저하시킨다. 생산성 저하는 단순히 일의 속도를 늦출 뿐만 아니라, 소프트웨어의 개발 주기를 지연시켜 소프트웨어의 생명에도 큰 위협이 된다. 이는 마치 소프트웨어의 심박수가 느려지는 것과 같다.
또한 정책은 '무엇인가를 하면 안 된다.' 혹은 '무엇인가를 해야 한다'와 같이 기술된다. '하면 안 되는 것'과 '해야 하는 것'이 잘 지켜지는지 확인하는 역할이 생길 수밖에 없고, 그것을 지키지 못하였을 때 내려지는 처벌 역시 생길 수밖에 없다. 이는 불필요한 권위를 생산하며 조직을 경직되게 만든다. 불필요한 권위는 시간이 지나면서 타락의 길을 걷게 될 수 있으며, 그 권위를 가진 자는 자신의 권위를 유지하기 위해 불필요한 권위를 더 많이 생산해 낼 가능성이 크다.
자율
앞서 이야기한 것처럼 소프트웨어의 품질은 결국 개발자에게 달려있다. 개발자 개인의 실력 향상이 품질과 직접적으로 연관되는 것이다. 나머지 요소들은 근본적으로 품질을 보장해 주지 못하며 차선책일 뿐이다.
소프트웨어의 품질을 높이는 가장 좋은 방법은 개발자 개개인이 장인정신을 갖고 자신이 만드는 생산물의 품질을 올리는 활동을 꾸준히 해나가는 것이다. 끊임없이 학습하고, 실패를 통해 배우며, 더 나은 품질을 향한 노력을 이어가야 한다. 이를 위해선 개발자 각자의 자율이 보장되어야 한다고 생각한다.
물론 자율과 정책 사이에는 균형이 필요하겠지만, 개발자 개개인의 실력이 뛰어날수록 정책은 불필요한 경우가 많다는 사실로 미루어보았을 때 결국, 그 균형은 자율을 우선시할 때 자연스럽게 지켜진다고 생각한다.
책임
결국 소프트웨어 품질은 개발자의 책임이며, 이를 높이기 위해서는 개발자의 활동에 초점을 맞추어야 한다. 이번 고찰의 출발점이 된 버그에 대해서도 QA나 정책 같은 외부 요인에 기대는 것이 아닌 개발자의 활동에 초점을 맞춰 재발 방지 대책을 도출했다. 코드를 작성하는 개발자에게 초점을 맞추고 품질을 올리고자 노력하는 활동을 이어간다면 개발자가 성장하는 만큼 소프트웨어 역시 견고해지리라 생각한다.
참고문헌
- 로버트 C. 마틴. 소프트웨어 장인 정신 이야기. 인사이트, 2023.