공학으로서의 소프트웨어 개발
IEEE Software Engineering Body of Knowledge (SWEBOK)는 '공학’과 '소프트웨어 공학’을 다음과 같이 정의한다.
공학이란 구조물, 기계, 제품, 시스템 또는 프로세스에 대한 체계적이고, 규율있으며, 정량화 가능한 접근법의 적용이다.
소프트웨어 공학이란 소프트웨어의 개발, 운영, 유지보수에 대한 체계적이고, 규율있으며, 정량화 가능한 접근법의 적용, 즉 소프트웨어에 대한 공학의 적용이다.
이 정의에 따르면 소프트웨어 개발에 공학적 측면이 있음은 자명하다. 그럼에도 일각에서 소프트웨어 개발을 공학이라고 인정하지 않는 이유는, 공학의 정의에 부합하지 않는 방식으로도 소프트웨어를 개발할 수 있기 때문이다. 프로그래머는 체계적이지 않게 설계할 수 있고, 규율없이 코딩할 수 있으며, 이를 통해 결과적으로 정량화 불가능한 소프트웨어를 완성할 수 있다.
이 글에서 언급하는 '소프트웨어 개발’이라는 용어는 코드 작성, 설계, 테스트, 유지보수 등 소프트웨어를 만들고 운영하는 데 수반되는 총체적인 과정을 일컫는다. 때로 소프트웨어 엔지니어(engineer)는 설계를 하고, 소프트웨어 개발자(developer)는 코딩을 한다고 말하기도 하는데, 오늘날 업계의 애자일 조직에서 이런 식으로 프로그래머의 직책과 직무를 명확히 구분하는 사례는 드물다.
다만 캐나다의 경우, “소프트웨어 엔지니어”, “컴퓨터 엔지니어” 및 "엔지니어"라는 접두사가 붙은 정보 처리 분야의 직함은 해당 주의 엔지니어링 규제 기관으로부터 엔지니어 자격(P.Eng)을 취득한 경우에만 사용할 수 있다.
개발 과정이 어떻든, 동작하는 소프트웨어를 만들 수 있기 때문에 소프트웨어 개발에서 공학적 접근법은 간과되곤 한다. 다른 공학 분야와 달리 소프트웨어 개발 분야는 지난 30년간 급격하게 변화했고, 이 때문에 개발 과정에서 올바른 원칙을 따르기 보다는 속도와 편의에 집중해왔다. 그러나 이렇게 만들어진 소프트웨어는 주로 국소적인 요구 사항만 충족하는 방식으로 만들어져 유연하게 확장할 수 없고, 운영 중 문제가 발생했을 때 이를 재현하거나 인지하는 것조차 불가능할 수 있다. 소프트웨어의 수요와 그 중요성에 비해 소프트웨어의 완성도는 후순위로 취급되는 것이 사실이다. 잘못 만들어진 소프트웨어는 작게는 사용자에게 불편을 일으키며, 크게는 사용자의 생명이나 조직 및 사회의 위험을 초래한다. 때문에 공학적 접근을 통해 소프트웨어의 완성도를 높이는 것이 어느때보다 중요하다.
물론 공학적이지 않은 방식으로 소프트웨어를 완성도 높게 개발할 수 있다는 관점도 있다. 소프트웨어 가드닝(gardening)의 접근은 소프트웨어를 살아있는 생물로 보고, 소프트웨어의 예측불가능성을 받아들인다. 이 관점에 따르면 개발자는 주인 의식과 직관에 따라 변화하는 소프트웨어를 섬세하게 가꾸는 전문가다. 소프트웨어 공학과 소프트웨어 가드닝의 차이는 소프트웨어 공학에서는 개발 과정에 공학적 접근을 적용하며, 공학 원칙과 일관된 프로세스가 더 나은 결과물을 만들 수 있음을 기대한다는 점이다.
소프트웨어 개발을 공학이라고 말하는 데 필요한 조건은 문제의 난이도나 엔지니어의 자격과는 무관하다. 상술한 SWEBOK의 정의에 따르면 소프트웨어 개발에 공학적 접근법을 적용했는지가 소프트웨어 개발을 공학으로 만드는 핵심이다. 다른 분야의 전문가와 달리 엔지니어는 추정하고, 실험하고, 측정하고, 재현하고, 개선하고, 반복한다. 모든 분야를 공학적으로 접근해야 하는 것은 아니다. 보통 공학적으로 해결이 필요한 문제에는 대부분 단 하나의 정답이 아닌 다양한 해법이 있다. 엔지니어는 제시된 필요를 가장 잘 충족하는 실현 가능한 해법을 선택하게 된다. 해법을 결정하고, 실현하는 과정에 공학적 접근을 적용하면 최선의 해법을 선택할 확률을 높일 수 있기 때문에 공학적 접근이 필요하다.
공학적 접근법
공학적 접근의 첫 단계는 실제 문제를 이해하는 것이다. 공학은 필요가 인식되고, 필요를 충족하는 기존 해법이 없을 때 시작된다. 그러나 해결이 필요한 문제가 항상 엔지니어에게 전달된 요구 사항과 같은 것은 아니다. 근본적인 문제를 이해하기 위해서는 5WHY와 같은 질문 기법이나 디자인 씽킹(design thinking) 등 사고 기법을 활용할 수 있다.
두 번째 단계는 합리적이고 기술적으로 실현 가능한 모든 해법을 식별하는 것이다. 공학적 의사결정의 목표는 최선의 해법을 찾는 것이다. 잠재적 해법에 대해서는 프로토타이핑이나 개념 증명을 통해 기술적 실현 가능성을 검증할 수 있다. 이는 더 많은 후보의 식별을 촉진할 수 있다. 한편 후보를 추가하면 최선의 후보가 집합에 포함될 확률이 높아진다. 하지만 후보 하나하나가 의사결정 비용을 추가하므로 엔지니어는 충분한 후보가 확보되었는지 판단해야 한다.
세 번째 단계는 선택 기준을 정의하는 것이다. 공학적 의사결정은 대체로 재무적 관점을 고려하지만, 다른 기준도 관련될 수 있다. 가령 환경을 중시하는 조직은 더 친환경적이라면 덜 경제적인 해법을 선택할 수도 있다. 각 기준은 객관적으로 표현해야 하며, 기준이 너무 적으면 후보 해법을 충분히 차별화하지 못해 차선의 선택으로 이어질 수 있다.
네 번째 단계에서는 두 번째 단계에서 식별한 해법들을 세 번째 단계에서 정의한 기준으로 평가하고 선택한다.
다섯 번째 단계는 선택한 해법을 실행하고 모니터링하는 것이다. 공학적 의사결정은 추정에 기반하며, 그 추정은 틀릴 수 있다. 따라서 선택한 해법의 실제 결과를 평가하고, 필요하다면 다른 대안 중 더 나을 것을 판단하는 것이 필수적이다. 추정은 공학적 의사결정의 근본 요소이므로 의사결정의 질은 추정의 질에 달려있다. 나쁜 추정은 나쁜 결정으로 이어진다. 소프트웨어 엔지니어는 추정치를 실제 결과와 비교함으로써 추정의 피드백 루프를 완성해야 한다. 추정과 실제 결과 사이의 괴리를 유발하는 요인을 이해하면, 추정 기법을 다듬어 미래에 더 정확한 추정을 만들 수 있다.
위 과정은 순차적일 필요는 없지만, 반드시 반복적어야 한다. 공학적 접근법은 본질적으로 반복적이다. 어느 시점에서든 획득한 지식이 이전 단계와 연관될 수 있으며, 이는 자연스럽게 반복을 유발한다. 이 반복을 통해 매 시도마다 개선을 달성할 수 있어야 한다.
예측 가능성
공학의 산출물은 예측할 수 있어야 하고, 일관된 프로세스에 따라 재현할 수 있어야 하며, 또한 동작 과정을 관측할 수 있어야 한다. 이것이 불가능하면 추정과 평가, 개선을 반복하는 공학적 접근 자체가 불가능하다. 소프트웨어 개발에서 역시 마찬가지다.
예측 가능성은 웹 프론트엔드 개발을 비롯한 UI 개발에 공학적 접근을 좌절시키는 요인이기도 하다. 소프트웨어의 입력인 사용자 인터랙션은 본질적으로 동작의 예측이 어렵고, 인터랙션의 경로에 따라 재현도 까다롭다. 이로 인해 결과적으로 공학적인 프로세스를 적용함으로써 높은 품질을 기대할 수 없게 된다. UI 개발 분야에서 함수형 프로그래밍이나 XState와 같은 유한 상태 기계 모델이 주목받는 것은 이러한 공학적 한계를 해결하기 위한 시도로 볼 수 있다.
참고자료
- Hironori Washizaki eds., “Guide to the Software Engineering Body of Knowledge (SWEBOK Guide), Version 4.0”, IEEE Computer Society, 2025.
- Jeff Atwood, “Tending Your Software Graden”, 2008.