[개발 생각] 버그는 막을 수 있을까

이 포스팅은 https://medium.com/qualityfaster/preventing-software-bugs-13f1cb2c7103 를 기반으로 작성되었습니다.

버그는 어떻게 나오게 될까

버그와의 전쟁은 지치고 무섭기도 하다. 하지만 버그의 본능을 안다면, 우리는 어떤 방지책이 효과적으로 고통으로부터 우리를 해방시킬 수 있는지 알 수 있을 것이다.

버그를 경험했을때는 SOPT라는 동아리 활동을 할 때였다. 서울시 앱 공모전에 제출할 어플리케이션을 제작하기 위해 처음으로 안드로이드 어플리케이션을 제작하고 있던 시기였다. 그때 특정 기능을 추가한 앱을 만들었다고 생각했는데 휴대폰에 옮기니 죽는 것이었다.

그때의 감정은 당혹감이 제일 컸었다. 분명 내가 생각했을대, 이 기능은 특정 행동을 보이며 잘 작동되리라 생각했지만, 생각하지 못한 방향으로 작동이 되었다는 것이다. 결국 버그를 고치기 위해 수많은 노력과 검색을 해야만 했었다.

당시 나의 모습은 막막한 우주를 바라보는 우주인의 모습이었을까

시간이 흘러 카카오에 있는 지금도 그 감정은 유효하다. 생각한대로 프로그램이 작동하면 좋겠지만, 세상의 원리가 그러하듯, 프로그램은 매번 내가 머리속에서 그려온대로 작동하지 않는다.

하지만 이전처럼 당혹감은 존재하지만 처음 프로그래밍을 했을때와 달리 식은땀을 막 흘리면서 작업을 하지는 않는다. 왜 그럴까. 오늘 이 글은 버그의 유형에 대해 알아보고, 버그에 대한 이해도를 높이는 기회를 얻어보려 한다.

버그를 이해한다면, 버그에 맞서 싸울 필요가 없어진다.

버그는 3가지의 타입이 존재한다. 딱 3가지. 그리고 각각 “간편한 버튼" 같은 트릭이 존재한다.


버그 타입 1: Implementation Defect

기획은 완벽했는데, 실행은 불완전했다.

흘깃 봤을때는, 이 유형의 버그가 제일 흔할 것 같지만 사실 아니다. 다음 자료에 따르면, 오직 15%의 결함이 이 단계에서 발생하고 있다. 그렇지만 이 연구가 Regressions 버그들을 고려하지는 않았기에 수치가 대등소이할 수 있다. 하지만 개인적 판단에 따르면 제일 작은 수치의 버그임에는 틀림없다.


코드가 복잡하게 꼬여있으면 만든 사람도 보기 힘들다

흔한 이유들

Regressions
버그들은 거미줄처럼 크고 복잡하게 얽혀있는 코드들 사이에 숨어있다. 업계 평균은 1000라인당 15–50개의 버그가 발생한다고 한다. 대단히 실력이 좋은 개발자라고 해도 당해낼 도리가 없다.

Smelly Code
Smelly Code” 는 버그로 이끌어가는 설계상의 약점을 고려해볼 수 있다. 이것이 발생하게 되는 요인에는 빨리 처리하기 위한 압박이나 나태함, 무시등이 있다.

충분치 못한 테스팅
타임라인은 빠듯하게 잡혀져 있고 팀은 빨리 기능을 출시해야한다고 생각해보자. 타임라인이 빠듯해지면 제일 유혹을 받는 부분은 자동 혹은 수동으로 테스트를 하는 시간을 줄이는 것이다. 이는 Production으로 넘어가기 전에 잡을 수 있는 버그들을 잡을 기회를 놓치면서 나오게 된다.


해결 방식

Test Driven Development

Test Driven Development (TDD)는 기능 명세에 맞춰 기능을 테스트할 수 있는 코드를 작성 및 테스트하는 것이다. 결과적으로 코드의 순기능에 집중해 테스트를 자동화 할 수 있다는 점을 장점으로 이야기하고 싶다.

이 작업을 함으로써 separation of concerns(관심사의 분리, 관리 요소의 분리), design patternsrefactoring같은 원칙들을 사용하도록 유도한다. 그래서 더욱 깔끔한 코드, 적어도 Smelly Code를 적게 생산할 수 있다.

이것은 또한 시간의 압박을 받을때 속도를 유지할 수 있도록 해주는 자동화continuous integration와 같은 작업을 할 수 있도록 유도한다. 결과적으로 불충분한 테스트 프로그램을 줄이도록 한다.

위의 이점들은 40–90%사이의 결점을 줄인다고 알려져 있다. 상당히 큰 수치이다. 그리고 이런 점들이 Implementation bugs를 줄이기 위한 최대효과 해결 방식으로서 TDD라는 점을 나타내준다.


Type 2: Incorrect Specification

정의가 명확하지 못해, 결과적으로 기능 구현도 부정확하다.

캠브리지 대학교에서 연구한 것에 따르면 50%의 결점은 정의를 할때 발생한다고 한다. 이 케이스의 제일 고통스러운 점은 설계를 처음부터 고쳐야 할 수도 있기 때문이다.


소통은 빈틈이 있을수록 서로 상상할 여지를 주게 된다

흔한 이유들

충분치 못한 커뮤니케이션
충분하지 못한 커뮤니케이션은 서로 이해를 다르게 할 여지를 준다. 결국 기획자가 의도한 디테일한 부분들이 구체화에 반영되지 않는다면, 구체화는 잘못된 방향으로 진행되고 버그가 발생하게 된다.

불일치
가끔 몇몇 구체화된 사항들이 이전에 구체화되었던 사항들과 충돌이 날때도 있다. 만약 발생한다면 버그는 개발 단계(운이 좋다면) 혹은 Production 단계에서 발생할 수 있다.


Bug Type 3: Missing Specifications

정의에서 놓쳐, 결과적으로 구현에서 놓쳤다.

간단히 말해, 제품을 디자인할때 상상하지도 못한 시나리오들이다. 이것들은 “알려지지 않은" 타입들을 일컫는다. 이들의 충격은 예상할 수 없으며 성가신 것부터 시작하여 파멸로 치닫는 것까지의 범위를 가진다.

구현에서 독단적인 창작은 좋지 못하다

흔한 이유들

충분하지 못한 연구
제대로 된 연구 없이 막연하게 ‘이렇게 될 것이다'라고 가정을 하기 시작하면, 결국 모든 것은 상상력으로 끝나게 된다. 가정을 하여 얻어낸 값은 큰 의미를 부여할 수 없으며 엉뚱하게도 복잡하고 난해한 문제가 따라올 가능성이 높다. 최종적으로 이것은 버그로 오게 된다.

무시
몇몇 사람들은 기대했던 행동이 정의되지 않았음에도 릴리즈를 할때 “기능이 잘못된 것 같다"는 느낌을 받을 때가 있다. 이 버그들은 정의가 부족할때 나오게 된다.


해결 방식

Behaviour Driven Development

Behaviour Driven Development (BDD)는 기획자와 개발자간의 이해를 공유하기 위해 만들어진 많이 알려진 개발 방법이다. 특히 TDD가 정착되고 나서, 개발현장은 TDD에 이은 다양한 xDD를 도입해왔다. 그 중에서도 BDD는 행동을 중심으로 한 테스트 방법이다.

BDD는 기획자와 개발자간에 어디서부터 테스트를 시작할 것이고 사용자의 행동 패턴에 맞춘 시나리오를 정의한다. 그리고 이것에 맞춰 ‘행동’에 대한 테스트를 진행한다. 최종적으로 BDD를 통해 시나리오에 대한 성공 유무를 확인할 수 있다.

이를 통해서 기획자는 시나리오의 완벽성을 확인할 수 있다. 개발자는 시나리오에 맞춘 개발 구현의 완성도를 확인할 수 있다. 또한 실패 원인에 따라 시나리오를 변경하거나 개발 구현 사항을 수정할 수 있게 된다.


정리해보기

우리는 버그를 없애기위해 필연적으로 테스트를 많이 해야한다. 처음에는 많이 당황할수도 있지만, 시간이 지날수록 요령은 생길 것이다. 제일 중요한 것은 버그를 맞서 싸우면서 기를 빼는 것보다 버그가 코드 내에 안착하기 전에 사전에 발견하여 없애는 것이 최고다.

그럼에도 버그는 필연적으로 발생할 것이며, 버그가 발견된다고 낙심하진 말자. 버그가 있다는 것은 서비스가 성장하기 위한 성장통이며, 이를 해결하는 나 자신 또한 성장하고 있다는 증거이다.