본문 바로가기
생각 정리

SW 테스트에 대한 고찰

by yyjun 2026. 5. 12.

요즘 AI를 열심히 쓰면서 SW의 품질에 대한 고민이 늘어났다. AI를 쓰면서 개발 속도는 확실히 빨라졌다. 근데 결과물의 품질을 보장할 수 없다는 생각이 들었다. 품질이 높은 소프트웨어란 무엇일까? 나는 결함이 적을수록, 유지보수성이 높을수록 소프트웨어의 품질이 높다고 생각한다. 이런 관점에서 봤을 땐 AI가 작성해 주는 코드를 맹신해서는 고품질의 소프트웨어를 만들 수 없다고 생각한다.

 

AI를 사용했을 때 개발 속도가 너무나 빨라지기 때문에 개발 과정에서 AI를 사용하지 않을 수는 없다. 사실 사람이 직접 개발할 때도 고품질을 보장하기 어렵다. 그렇다면 AI를 사용하더라도 일정 수준 이상의 품질을 보장할 수 있는 장치가 필요하다. 마치 가드레일처럼 AI가 만든 작업물의 품질이 일정 범위를 벗어나지 않도록 만들어주는 장치가 필요하다. 많은 고민을 해봤지만, 결국 이 역할은 테스트가 담당할 수 있고, 테스트만 이 역할을 담당할 수 있다는 결론을 내렸다.

 

특히 백엔드 개발자인 내 입장에서는 자동화된 테스트가 중요하다고 생각한다. 프론트엔드의 테스팅 요소들 중에는 온전히 자동화가 힘든 영역이 존재한다. 그렇기 때문에 프론트엔드 개발자에게는 자동화 테스트 못지않게 수동 테스트 역시 중요할 수 있다. 그렇지만 백엔드 영역에서는 거의 대부분의 테스팅을 자동으로 수행할 수 있다. 그래서 백엔드 개발자인 내 입장에서는 테스트 수행 비용이 저렴한 자동화 테스트가 중요하다.

 

다시 본론으로 돌아와서, 왜 테스트가 SW의 품질을 보장하는 유일한 장치일까? SW의 결함 발견과 유지보수 관점에서 설명할 수 있다. 우선 SW의 결함 발견 측면에서 테스트를 살펴보자. SW의 결함이 발생하는 원인은 크게 둘로 나눌 수 있다고 본다. 요구사항이 명확하지 않거나 코드가 요구사항대로 개발되지 않았을 경우 결함이 발생한다. 테스트 코드를 작성하고, 테스트를 수행하는 과정에서 이 두 가지를 모두 방지할 수 있다.

 

먼저 테스트 케이스를 도출하는 과정에서 요구사항을 더욱 명료하게 만들 수 있다. 테스트 케이스를 제대로 도출한다면, 도출하는 과정에서 다양한 엣지 케이스들을 고려하게 된다. 이러한 엣지 케이스들을 고려하면서 요구사항의 빈틈을 찾을 수 있다. 그리고 이해관계자와 대화를 하며 이러한 요구사항의 빈틈을 채울 수 있다. 이런 식으로 테스트 케이스를 도출하고, 지속적으로 보완하다 보면 요구사항이 명료해지게 될 것이다.

 

또한 요구사항은 계속 변한다. 그리고 뭐가 변할지 예측하는 것은 힘들다. 이런 상황에서 테스트 코드는 살아있는 요구사항 명세서 역할을 한다. 요구사항을 문서로만 관리하면 어느 순간 문서와 코드 사이에 괴리가 생기기 쉽다. 요구사항 문서와 코드를 동시에 업데이트해야 하는데, 문서만 업데이트할 수 있기 때문이다. 코드에서도 단일 진실 공급원(SSOT, Single Source of Truth)이 중요한 것처럼, 요구사항 관리 역시 단일 진실 공급원이 중요하다. 요구사항 명세서를 문서로 관리하지 않고 테스트 코드로 관리하면 테스트 코드가 요구사항의 단일 진실 공급원이 된다. 개발자는 뭐가 맞는 요구사항인지 의심하고 고민할 필요 없이 테스트 코드를 믿으면 된다. 그리고 테스트 코드로 요구사항을 만족하는지 검증할 수 있다. 즉, 테스트 코드가 모두 통과한다면 주어진 요구사항을 모두 만족한다고 볼 수 있다. 물론 테스트 케이스를 제대로 도출하고 테스트 코드를 효과적으로 작성했다는 전제 하에 성립하는 말들이다. 테스트가 부실하면 이러한 말들은 성립하지 않는다.

 

이제 SW의 결함이 발생하는 다른 원인, 요구사항대로 개발되지 않은 경우를 살펴보자. 이 경우는 특히 비즈니스 로직이 복잡한 경우에 흔히 볼 수 있다. 개발자 또는 AI가 요구사항을 만족하기 위해 나름 노력을 했지만, 요구사항이 복잡해서 제대로 개발되지 않은 경우다. 이 역시 테스트로 해결할 수 있다. 복잡한 요구사항을 모두 테스트로 옮기면 된다. 만약 요구사항대로 개발하지 않았다면 여러 테스트 중 몇 개의 테스트가 실패할 것이다. 테스트가 모두 성공할 때까지 코드를 수정하면 된다. 테스트가 모두 성공한다면 요구사항을 모두 만족하게 될 것이다. 복잡한 요구사항을 테스트로 옮기는 것 자체가 사실 어려운 일이기는 하다. 테스트를 잘 작성하는 방법은 나중에 정리해서 다른 글로 적도록 하겠다.

 

한편, 유지보수 측면에서는 회귀 방지와 안전한 리팩토링 측면에서 테스트가 중요하다. 유지보수를 거치다 보면 기존에 작성된 코드를 일부 수정하는 일이 있다. 새로운 기능을 추가하거나, 기존 코드를 리팩토링 하는 경우가 그러하다. 그리고 새로운 기능을 추가할 때 기존 코드를 전혀 건드리지 않더라도 사이드 이펙트로 인해 기존 기능이 예상치 못하게 영향을 받는 경우도 있다. 테스트 코드를 작성하면 이러한 문제를 방지할 수 있다. 테스트는 앞에서 말했던 것처럼 살아 있는 요구사항 명세서 역할을 한다. 그렇기 때문에 유지보수 과정에서 요구사항을 만족하지 못하게 변한다면 테스트가 바로 실패한다. 실제 사용자에게 배포하기 전에 코드에 문제가 생겼음을 알 수 있고 고칠 수 있다.

 

위와 같은 이유로 테스트를 제대로 활용하면 결함이 적고 유지보수성이 높은 소프트웨어를 만들 수 있다고 생각한다.

 

테스트 케이스를 도출하고 테스트 코드를 작성하는 과정 역시 AI를 활용하면 훨씬 효율적일 것 같다. AI가 작성한 코드의 품질을 보장하기 위해 테스트를 수행하는 건데, 테스트를 효율적으로 수행하기 위해서는 AI가 필요하다. 테스트를 수행하는 과정에서는 AI 작업물의 품질을 어떻게 보장해야 할지 아직 고민이 된다. 좋은 방법을 찾으면 다른 글을 작성하도록 하겠다.