2025년 07월 02일
12

코드는 설계다 — Jack W. Reeves의 1992년 통찰

개발
KKingmo

Changmo Oh

@KKingmo

전체 글 보기

소프트웨어 개발 과정에 대해 고민하는 개발자라면 누구나 한 번쯤 다음 질문에 봉착한다.

  • 설계를 완벽하게 끝내고 코딩을 시작해야 하는가?
  • 왜 코딩 단계에서 자꾸 설계를 수정하게 되는가?

이러한 고민에 대한 명쾌한 통찰을 제공하는 글이 있다. 바로 잭 W. 리브스(Jack W. Reeves)가 1992년에 발표한 에세이 "What Is Software Design?"이다. 이 글은 30년이 지난 오늘날까지도 소프트웨어 공학의 본질을 논할 때 핵심적인 레퍼런스로 인용된다.

이 에세이의 핵심 주장은 다음과 같다.

"최종 소스 코드가 곧 실제 소프트웨어 설계(Design)이다."

이 파격적인 관점이 소프트웨어 개발 과정에 어떤 의미를 부여하는지 상세히 알아본다.


1. 소프트웨어 개발의 '설계'와 '구축'에 대한 오해

일반적으로 소프트웨어 개발은 하드웨어 제조나 건축 과정에 비유된다.

  • 설계(Design): 아키텍처 문서, UML 다이어그램, 고수준 명세 작성
  • 구축(Construction/Build): 설계 문서를 바탕으로 소스 코드를 작성하는 행위

이 관점에 따르면 프로그래머는 '설계도(문서)'를 받아 '구축 작업'을 수행하는 건설 노동자로 간주된다. 따라서 설계자가 만든 문서를 코딩 중에 변경하는 행위는 '규칙 위반'이나 '실수'로 여겨진다.

하지만 리브스는 이 비유가 근본적으로 잘못되었다고 지적한다.

실제 소프트웨어의 '구축(Build, Manufacturing)' 과정은 사람이 아닌 컴파일러와 링커가 수행한다. 우리가 build 명령을 실행할 때 발생하는 일, 즉 소스 코드를 실행 가능한 0과 1의 파일로 변환하는 과정이 하드웨어의 '제조'에 해당한다는 것이다.

그렇다면 프로그래머가 에디터 앞에서 코드를 작성하는 행위는 무엇인가?

프로그래밍은 소프트웨어를 '설계(Designing)'하는 활동이다.

즉, 우리는 기계가 제품을 만들 수 있도록 최종 설계도(소스 코드)를 그리고 있는 것이다.

2. 설계는 비싸고, 구축은 거의 무료이다

소스 코드를 설계로 간주할 때, 소프트웨어의 경제적 특성이 명확하게 드러난다.

1) 소프트웨어 구축(Build) 비용: 저렴하다

하드웨어는 설계도 복잡하지만, 실제로 제품을 제조하는 데 드는 비용(자재비, 공장 설비, 인건비)이 매우 비싸다. 반면, 소프트웨어는 컴파일하고 링크하는 '빌드' 과정에 드는 비용이 컴퓨터 자원 소모 외에 거의 없다. 빌드는 실패하더라도 언제든지 다시 할 수 있으며, 그 비용은 '거의 무료'에 가깝다.

2) 소프트웨어 설계(Design) 비용: 매우 비싸다

소프트웨어는 본질적으로 매우 복잡하다. 수많은 기술적 요구사항과 비즈니스 로직을 인간의 지식으로 포착하고 구조화하는 과정 자체가 막대한 비용을 발생시킨다. 우리가 코드를 작성하는 행위, 즉 '설계' 과정이야말로 소프트웨어 개발에서 가장 많은 비용을 차지하는 부분이다.

3. 테스트와 디버깅은 '공학적 정제' 과정이다

많은 개발 조직에서 테스트와 디버깅은 코딩 과정의 오류를 제거하는 '수습 작업'처럼 취급된다.

그러나 소스 코드가 설계라는 관점을 적용하면, 테스트와 디버깅은 다른 공학 분야의 설계 검증 및 정제 과정으로 재정의된다.

  • 하드웨어 엔지니어가 다리 설계를 확정하기 위해 시뮬레이션이나 축소 모형 실험을 하듯이, 소프트웨어 엔지니어는 실제 디자인 결과물(코드)을 빌드하고 실행하며 테스트한다.
  • 테스트 과정에서 발견된 오류를 수정하는 디버깅은 설계의 결함을 찾아내고 이를 개선하는 정제 과정이다.

따라서 코드를 작성하고 테스트하는 과정에서 설계가 바뀌는 것은 프로그래머가 실수를 했기 때문이 아니라, 설계가 복잡하여 필연적으로 수반되는 '공학적 정제'의 현실이기 때문이라고 리브스는 주장한다.

4. 모든 것이 설계 과정이다

소프트웨어의 복잡성 때문에, 고수준의 아키텍처 설계와 저수준의 모듈 알고리즘 설계는 분리될 수 없고 서로 영향을 미친다. 코딩 과정에서 모듈의 알고리즘을 상세화하다 보면, 반드시 상위 레벨 설계의 허점이나 비효율성이 드러나게 마련이다.

이러한 현실을 바탕으로 리브스는 다음과 같이 결론을 내린다.

소프트웨어 개발의 압도적인 문제는 '모든 것'이 설계 과정의 일부라는 점이다.

고수준 설계 단계에서 코딩을 미루는 것은, 설계를 검증하고 정제할 수 있는 빌드/테스트 주기를 지연시키는 행위와 같다. 이는 설계의 오류를 후반부에 발견하게 만들어 더 큰 비용을 초래한다. 따라서 좋은 소프트웨어 설계 프로세스는 코딩을 설계 활동으로 인식하고, 설계 과정 초기에 코드를 작성하여 빌드/테스트를 통해 설계를 검증하고 정제하는 과정을 포함해야 한다.

5. 프로그래밍 언어의 중요성

리브스는 소프트웨어 개발의 진정한 발전은 프로그래밍 기술의 진보에 달려있으며, 이는 곧 프로그래밍 언어의 진보를 의미한다고 강조한다.

  • 구조도, UML 등 수많은 표기법들은 설계 과정에 도움을 주는 보조 도구일 뿐, 소프트웨어 설계 그 자체는 아니다.
  • 궁극적으로 설계는 프로그래밍 언어로 표현되어야 한다.

당시 C++가 폭발적으로 인기를 얻은 이유도 C++가 고수준의 설계 개념(객체 지향)을 코드에 직접적으로, 그리고 더 표현력 있게 담아낼 수 있는 언어였기 때문이라고 설명한다. 즉, 더 나은 프로그래밍 언어는 더 나은 설계 도구인 것이다.

6. 보조 문서의 역할

소스 코드가 유일한 설계 문서라면, 기존의 설계 문서는 어떤 역할을 해야 하는가?

보조 문서는 여전히 중요하다. 하지만 그 역할은 코드가 설명할 수 없는 '의도'와 '맥락'을 기록하는 것으로 바뀐다.

  • 코드: '무엇(What)'을, '어떻게(How)' 구현했는지에 대한 유일한 진실.
  • 보조 문서: '왜(Why)' 이 설계를 선택했는지, 어떤 대안이 있었는지, 문제 영역의 어떤 중요한 정보가 설계에 반영되었는지 등을 기록한다.

소스 코드가 실제 설계를 결정한다는 원칙을 잊어서는 안 되며, 보조 문서는 코드가 변경될 때마다 반드시 업데이트되어야 그 가치를 유지할 수 있다.


요약

잭 W. 리브스의 에세이는 소프트웨어 개발에 대한 관점을 재정립한다.

  1. 코드가 곧 설계이다. (프로그램 리스팅은 소프트웨어 설계를 나타내는 문서이다.)
  2. 프로그래밍은 설계 활동이다. (소프트웨어 구축 비용은 저렴하지만, 설계 비용은 매우 비싸다.)
  3. 테스트와 디버깅은 설계의 정제 과정이다. (단순한 오류 제거 작업이 아닌, 설계 검증을 위한 공학적 과정이다.)
  4. 모든 단계가 설계 활동이다. (최상위 설계부터 코딩, 테스트까지 모두 상호작용하며 설계를 완성한다.)
  5. 더 나은 프로그래밍 언어는 더 나은 설계 도구이다.

이러한 관점은 폭포수 모델과 같은 경직된 개발 프로세스를 지양하고, 코딩과 테스트를 일찍 시작하여 설계를 빠르게 검증하고 정제하는 애자일(Agile) 방식의 근간이 되는 통찰이라고 할 수 있다.