겸손한 프로그래머 (EWD 340)

ko생성일: 2025. 10. 8.갱신일: 2025. 10. 9.

에츠허르 W. 다익스트라가 프로그래밍 직업의 형성과 소프트웨어 위기의 배경, 프로그래밍 언어의 발전과 한계, 추상화와 정확성 증명에 기반한 설계, 도구가 사고방식에 미치는 영향 등을 반추하며, 인간 지성의 한계를 존중하는 겸손하고 절제된 프로그래밍을 촉구한다.

겸손한 프로그래머

저자

Edsger W. Dijkstra

기막힌 우연의 연쇄 끝에 나는 1952년 봄 첫 아침, 공식적으로 프로그래밍 직업에 발을 들였고, 내가 아는 한 네덜란드에서 그렇게 한 첫 번째 사람이었다. 돌이켜보면 가장 놀라웠던 것은, 적어도 내가 살던 세상에서는, 프로그래밍이라는 직업이 등장하는 데 믿기 어려울 정도로 더디었다는 사실이다. 하지만 그 더딤을 의심의 여지 없이 증명해 주는, 그 시기의 생생한 기억 두 가지가 있어 나는 오히려 고맙게 생각한다.

프로그래밍을 시작한 지 3년쯤 되었을 때, 나는 당시 암스테르담 수학 센터에서 나의 상사였던 A. van Wijngaarden과 대화를 나눴다. 나는 그에게 평생 감사할 것이다. 동시에 나는 라이덴 대학교에서 이론물리학을 공부해야 했고, 두 활동을 병행하는 일이 점점 더 어려워졌기에 결정을 내려야 했다. 프로그래밍을 그만두고 진짜로 존경받는 이론물리학자가 되든지, 아니면 물리학 공부를 최소한의 노력으로 형식적으로만 마무리하고…, 그렇다면 무엇이 되는가? 프로그래머? 하지만 그것이 존경받을 만한 직업이었는가? 도대체 프로그래밍이란 무엇이었나? 그것을 지적(知的)으로 존중받을 만한 학문으로 떠받쳐 줄 탄탄한 지식 체계가 어디에 있었나? 나는 하드웨어 동료들이 부러웠다. 그들은 자신의 전문성을 묻는 질문에 진공관, 증폭기 등등을 속속들이 안다고 자신 있게 말할 수 있었지만, 나는 그런 질문을 받으면 아무것도 손에 쥔 것이 없는 듯한 공허함을 느꼈기 때문이다. 망설임으로 가득 차서 나는 반 비안하르덴의 사무실 문을 두드리며 “잠깐 말씀 좀 드려도 될까요?”라고 물었다. 몇 시간 뒤 그의 사무실을 나설 때 나는 완전히 다른 사람이 되어 있었다. 그는 나의 고민을 참고 들어준 다음, 그때까지는 프로그래밍이라는 학문이 별로 존재하지 않았다는 데 동의했다. 그러나 그는 차분히 말했다. 자동식 컴퓨터는 사라지지 않을 것이며, 우리는 이제 막 시작일 뿐이니, 앞으로의 세월 동안 프로그래밍을 존중받는 학문으로 만드는 부름을 내가 받을 수 있지 않겠느냐고. 그것은 내 인생의 전환점이었다. 나는 가능한 한 빨리 형식적으로 물리학 공부를 마쳤다. 이 이야기의 교훈은 분명하다. 젊은이에게 조언할 때 매우 조심해야 한다. 그들은 때때로 그 조언을 정말로 따르기 때문이다!

또 두 해가 지나 1957년에 나는 결혼했다. 네덜란드의 혼인 신고에는 직업을 명시해야 했고, 나는 프로그래머라고 적었다. 그러나 암스테르담 시청은 그런 직업은 없다며 받아주지 않았다. 믿기 어렵겠지만, 내 혼인 신고서의 직업란에는 우스꽝스럽게도 “이론물리학자”라고 적혀 있다!

이것이 내가 살던 나라에서 프로그래밍이라는 직업이 얼마나 더디게 등장했는지를 보여준다. 그 후 나는 더 넓은 세상을 보았고, 날짜의 차이는 있을지언정 다른 나라에서도 성장 패턴은 대체로 크게 다르지 않았다는 인상을 받았다.

이제 옛날의 상황을 좀 더 자세히 그려 보며, 오늘날의 상황을 더 잘 이해할 수 있기를 바란다. 분석을 진행하는 동안, 프로그래밍 업무의 진정한 본질을 둘러싼 숱한 오해가 얼마나 그 먼 과거로 거슬러 올라가는지 보게 될 것이다.

최초의 자동 전자식 컴퓨터들은 모두 하나뿐인 유일한 기계였고, 실험실 특유의 흥분이 넘치는 환경에 있었다. 자동식 컴퓨터라는 비전이 생겨나자, 그것을 구현하는 일은 당시 전자 공학이 감당해야 할 엄청난 도전이었다. 분명한 한 가지는, 그런 엄청난 장치를 만들겠다고 나선 집단들의 용기를 우리는 부정할 수 없다는 점이다. 그 기계들은 정말로 환상적인 장비였다. 지금 돌아보면, 그 초기 기계들이 어쨌든 작동했다는 사실 자체가 놀랍다. 무엇보다도 압도적인 문제는 기계를 작동 상태로 만들고 유지하는 일이었다. 자동 계산의 물리적 측면에 대한 집착은 이 분야의 오래된 학회 이름들—Association for Computing Machinery, British Computer Society 등—에 여전히 반영되어 있다. 그 이름들은 물리적 장비를 명시적으로 가리킨다.

그렇다면 불쌍한 프로그래머는 어땠는가? 솔직히 말하면, 거의 주목받지 못했다. 우선 초기의 기계들은 너무 거대해서 옮기는 것조차 어려웠고, 광범위한 유지보수를 요했기에, 기계를 사용하려는 사람들이 기계를 개발한 바로 그 연구실에서 일하는 것이 자연스러웠다. 둘째, 프로그래머의 다소 보이지 않는 작업에는 아무런 화려함도 없었다. 방문객에게 기계를 보여주는 것이 코딩지 몇 장을 보여주는 것보다 수백 배 더 극적이었다. 하지만 무엇보다 중요한 것은, 프로그래머 자신이 자신의 일을 매우 소박하게 여겼다는 점이다. 그의 일은 오롯이 그 경이로운 기계의 존재에서 의미를 얻었다. 그 기계가 유일무이했기 때문에, 그의 프로그램은 지역적 의미밖에 갖지 못했으며, 게다가 그 기계의 수명이 한정적이라는 것이 명백했기에, 자신의 작업이 오래도록 가치가 남을 가능성은 거의 없다고 그는 알고 있었다. 마지막으로, 프로그래머의 태도에 지대한 영향을 준 또 하나의 환경이 있었다. 한편으로 그의 기계는 신뢰성이 떨어질 뿐 아니라 보통 너무 느리고 메모리는 너무 작았다. 즉 발에 맞지 않는 꽉 끼는 신발을 신고 있는 셈이었다. 다른 한편으로, 흔히 기묘한 명령 코드는 가장 예상치 못한 구성까지도 가능하게 했다. 그 시절 많은 영리한 프로그래머들은, 장비의 제약 속에 불가능을 쑤셔 넣는 교묘한 요령에서 엄청난 지적 만족을 얻었다.

그 시절부터 생겨난 프로그래밍에 관한 견해 두 가지가 있다. 지금 언급해 두고 나중에 다시 돌아오겠다. 하나는, 진정 유능한 프로그래머는 퍼즐을 좋아하고 교묘한 트릭을 아주 즐겨야 한다는 견해였다. 또 하나는, 프로그래밍이란 계산 과정을 이 방향저 방향으로 최적화하는 것 이상도 이하도 아니라는 견해였다.

후자의 견해는, 당시 보유한 장비가 정말로 발을 죄는 신발 같았다는 빈번한 경험에서 비롯되었다. 그래서 더 강력한 기계만 나온다면 프로그래밍은 더 이상 문제가 되지 않을 것이라고 순진하게 기대하곤 했다. 기계를 끝까지 쥐어짜는 싸움이 더 이상 필요 없어질 테고, 그게 곧 프로그래밍의 전부 아니냐는 것이다. 그러나 그 뒤 수십 년 동안 벌어진 일은 전혀 달랐다. 더 강력한 기계가 등장했다. 한 자릿수 배가 아니라, 수십, 수백 배 더 강력해졌다. 그런데도 모든 프로그래밍 문제가 해결된 영원한 행복 상태에 들어간 것이 아니라, 우리는 소프트웨어 위기 속에서 허우적거리게 되었다! 어쩐 일인가?

작은 원인 하나는 이렇다. 한두 가지 측면에서 현대의 기계는 옛 기계에 비해 본질적으로 다루기 어려워졌다. 첫째, 예측할 수 없고 재현도 되지 않는 순간에 발생하는 I/O 인터럽트가 생겼다. 완전히 결정론적 자동기계인 척하던 옛 순차 기계와 비교하면, 이것은 극적인 변화다. 시스템 프로그래머의 희끗한 머리카락은 그 특징이 야기한 논리적 문제를 가볍게 말해서는 안 된다는 것을 증언한다. 둘째, 다단계 저장장치를 갖춘 기계가 등장했고, 이에 따른 관리 전략 문제는 방대한 문헌에도 불구하고 여전히 꽤 붙잡기 어렵다. 실제 기계의 구조적 변화가 초래한 복잡성은 이 정도로 하겠다.

그러나 나는 이것을 작은 원인이라 했다. 큰 원인은… 기계가 수자릿수 배로 더 강력해졌기 때문이다! 노골적으로 말해 보자. 기계가 없던 시절에는 프로그래밍은 전혀 문제가 아니었다. 아주 약한 컴퓨터가 몇 대 생기자 프로그래밍은 약간의 문제가 되었다. 그리고 지금 우리는 거대한 컴퓨터를 갖게 되었고, 프로그래밍도 똑같이 거대한 문제가 되었다. 이런 의미에서 전자 산업은 단 하나의 문제도 해결하지 못했다. 오히려 그것은 문제를 만들었다. 그것의 제품을 사용하는 문제가 만들어진 것이다. 달리 말하면, 기계의 성능이 천 배 이상 커지는 동안, 사회가 그 기계를 적용하려는 야심도 비례해서 커졌다. 그리고 목표와 수단 사이의 폭발한 긴장장 안에서 고생한 것은 불쌍한 프로그래머였다. 하드웨어의 성능 향상과—아마 더 극적인—신뢰성 향상은, 몇 년 전만 해도 프로그래머가 감히 꿈꾸지 못했던 해결책들을 가능하게 만들었다. 그리고 이제, 몇 년이 지난 뒤에는, 그는 그것들을 반드시 꿈꿔야 했다. 더 나아가, 그런 꿈을 현실로 바꾸어야만 했다! 우리가 소프트웨어 위기에 빠진 것이 놀랄 일인가? 전혀 아니다. 짐작했겠지만, 이것은 아주 일찍이 예견되기도 했다. 다만 작은 예언자(minor prophet)의 난점은 대개 5년쯤 지나서야 그가 옳았다는 것을 진정으로 알게 된다는 데 있다.

그러던 중 60년대 중반, 끔찍한 일이 벌어졌다. 이른바 3세대 컴퓨터가 등장한 것이다. 공식 문헌에 따르면, 가격/성능 비율이 주요 설계 목표 가운데 하나였다. 그런데 만약 “성능”을 기계 각 구성 요소의 가동률로 정의한다면, 의심스러운 필요성의 내부 집안일만으로도 성능 목표의 주요 부분을 달성하게 만드는 설계로 귀결될 수 있다. 또 가격을 하드웨어 가격으로만 정의한다면, 프로그래밍하기 끔찍하게 어려운 설계로 끝나게 막을 장치가 별로 없다. 예컨대 명령 코드가, 프로그래머나 시스템에게 해결 불가능한 충돌을 야기하는 초기 바인딩 결정을 강제할 수 있다. 이러한 불쾌한 가능성의 상당 부분이 현실이 된 것으로 보인다.

이 기계들이 발표되고 기능 명세가 알려졌을 때, 우리 중 적잖은 사람들이 꽤 비참해졌을 것이다. 적어도 나는 그랬다. 그런 기계가 컴퓨팅 공동체를 휩쓸 것이 당연히 예상되었기에, 그 설계가 가능한 한 건전해야 한다는 점은 더욱 중요했다. 하지만 설계에는 너무도 심각한 결함이 들어 있었고, 그 한 방에 컴퓨팅 과학의 진보가 최소 10년은 후퇴했다고 느꼈다. 내 직업 인생 통틀어 가장 어두웠던 한 주였다. 아마 가장 슬픈 일은, 그 뒤 수년의 좌절스러운 경험에도 불구하고 여전히 많은 사람들이 마치 자연법칙이라도 되는 듯, 기계는 원래 그래야 한다고 진심으로 믿는다는 점이다. 그들은 이렇게 많은 기계가 팔렸다는 사실을 보며 의심을 잠재우고, 그 관찰에서 설계가 그리 나쁘진 않았으리라는 거짓된 안도감을 얻는다. 그러나 자세히 들여다보면, 그 방어 논리는 “담배를 피우는 사람이 그토록 많으니 흡연은 건강에 좋다”는 주장만큼이나 설득력이 없다.

이와 관련해, 컴퓨팅 분야의 과학 저널들이 새로 발표된 컴퓨터를 과학 출판물처럼 서평하는 관행이 없는 것이 유감스럽다. 기계를 리뷰하는 일은 적어도 그만큼 중요할 것이다. 여기서 고백할 것이 있다. 60년대 초, 나는 CACM에 제출할 생각으로 그런 서평을 썼다. 그 글을 받아 본 몇몇 동료들이 모두 제출하라고 권했음에도, 나는 감히 내지 못했다. 나 자신이나 편집위원회가 겪게 될 곤란이 너무 클 것 같았기 때문이다. 이 억눔은 내 비겁함이었고, 시간이 갈수록 더 크게 자책한다. 내가 예상한 곤란은 일반적으로 받아들여진 기준이 없기 때문이었다. 내가 적용하려 한 기준의 타당성에는 스스로 확신했지만, 내 서평이 “개인 취향”으로 거부되거나 폐기될까 두려웠다. 나는 여전히 그런 서평이 대단히 유익하리라 생각하며, 그것들이 모습을 드러나기를 학수고대한다. 그런 서평이 널리 수용되어 실리는 것은 컴퓨팅 공동체의 성숙을 보여주는 확실한 신호일 것이다.

하드웨어 상황을 위처럼 길게 이야기한 이유는, 어떤 컴퓨팅 도구든 그것을 쓰려는 이들의 사고 습관에 미치는 영향이 가장 중요한 면모 가운데 하나라는 느낌 때문이며, 그 영향이 보통 생각하는 것보다 훨씬 강하다고 믿을 이유가 있기 때문이다. 이제 소프트웨어 쪽으로 시선을 돌리자.

여기서는 다양성이 너무 커서 몇몇 디딤돌만 고를 수밖에 없다. 선택이 임의적이라는 점을 잘 알고 있으며, 언급되지 않을 많은 노력들에 대한 나의 평가와는 무관하다는 점을 양해해 주기 바란다.

처음에 영국 케임브리지의 EDSAC이 있었다. 그 시작부터 서브루틴 라이브러리라는 개념이 그 기계의 설계와 사용 방식에서 중심적 역할을 했다는 사실은 꽤 인상적이다. 이제 거의 25년이 지났고 컴퓨팅의 풍경은 극적으로 변했지만, 기본 소프트웨어라는 개념은 여전히 우리 곁에 있으며, 닫힌(폐쇄된) 서브루틴이라는 개념은 프로그래밍의 핵심 개념 가운데 하나로 남아 있다. 닫힌 서브루틴은 위대한 소프트웨어 발명 가운데 하나로 인정해야 한다. 그것은 세 세대의 컴퓨터를 견뎌냈고 앞으로도 몇 세대를 더 견딜 것이다. 그것은 우리의 기본적인 추상화 패턴 가운데 하나를 구현하는 데 기여하기 때문이다. 유감스럽게도, 산술 장치의 명명된 레지스터가 지나치게 많았던 3세대 컴퓨터 설계에서는 이의 중요성이 과소평가되었다. 그 결과 서브루틴 메커니즘에는 큰 오버헤드가 붙었다. 하지만 그조차 서브루틴 개념을 죽이지는 못했다. 우리는 다만 그 돌연변이가 유전되지 않기를 기도할 뿐이다.

다음으로 언급하고 싶은 소프트웨어상의 큰 전개는 FORTRAN의 탄생이다. 당시 이것은 큰 대담함이 필요한 프로젝트였고, 그 책임자들은 큰 찬사를 받아 마땅하다. 10여 년의 폭넓은 사용 끝에야 드러난 단점을 그들에게 탓하는 것은 부당하다. 10년 앞을 성공적으로 내다본 집단은 매우 드물기 때문이다! 돌아보면, FORTRAN은 성공적인 코딩 기법으로 평가할 수 있지만, 구상(발상)을 돕는 효과적인 도구는 거의 제공하지 못했다. 지금 우리에게 절실한 것은 바로 그런 도구이며, 그런 점에서 FORTRAN은 이제 시대에 뒤떨어졌다. FORTRAN을 잊을 수 있다면 빠를수록 좋다. 사유의 도구로서 더는 충분하지 않다. 우리의 두뇌력을 낭비시키고, 위험 부담이 크며, 그래서 사용하기에 너무 비싸다. FORTRAN의 비극적 운명은 그것이 널리 받아들여졌다는 점이다. 그 결과 수많은 프로그래머들이 과거의 실수에 정신적으로 사슬로 묶이고 말았다. 나는 매일같이 기도한다. 더 많은 동료 프로그래머들이 호환성이라는 저주에서 자신을 해방할 방법을 찾게 되기를.

세 번째로 언급하지 않고 지나갈 수 없는 프로젝트는 LISP이다. 성격이 완전히 다른, 매혹적인 시도였다. 아주 기본적인 몇 가지 원리 위에 서서, 놀라운 안정성을 보여주었다. 또한 LISP는 어떤 의미에서는 가장 정교한 컴퓨터 응용의 상당 부분을 실어 나른 매개체였다. LISP는 농담 삼아 “컴퓨터를 남용하는 가장 지적인 방식”이라고 묘사되곤 했다. 나는 그 묘사를 큰 찬사라고 생각한다. 그 말은 해방의 맛을 온전히 전하기 때문이다. LISP는 우리 가운데 가장 재능 있는 이들 몇 명이 이전에는 불가능했던 생각을 하도록 도와주었다.

네 번째로 언급할 프로젝트는 ALGOL 60이다. 오늘날까지도 FORTRAN 프로그래머들은 자신이 쓰는 언어를 손에 든 특정 구현의 관점으로 이해하는 경향이 있다—그 결과 팔진수, 16진수 덤프가 성행한다. LISP의 정의는 여전히 언어의 의미와 메커니즘의 작동 방식이 기묘하게 뒤섞여 있다. 이에 비해, 유명한 ‘알고리즘 언어 ALGOL 60에 관한 보고서’는 추상화를 한 걸음 더 전진시켜, 구현 독립적인 방식으로 프로그래밍 언어를 정의하고자 한 진지한 노력의 결실이다. 이 점에서 저자들이 너무 성공한 나머지, 그것이 과연 구현 가능한가에 대해 심각한 의구심까지 낳았다고 주장할 수도 있겠다! 그 보고서는 공식적 방법 BNF—이제는 Backus–Naur Form으로 널리 알려진—의 힘과, 신중히 다듬어진 영어의 힘, 최소한 피터 나우어처럼 탁월한 사람이 사용할 때의 힘을 영광스럽게 보여주었다. 그렇게 짧은 문서 가운데 컴퓨팅 공동체에 이만큼 깊은 영향을 끼친 문서는 매우 드물다고 말해도 공평할 것이다. 이후 수년 동안 ALGOL과 ALGOL-유사라는 이름이, 보호되지 않은 상표처럼, 때로는 거의 관련이 없는 젊은 프로젝트에까지 그 영광을 덧씌우는 데 쓰였다는 사실은, 그 위상을 보여주는 다소 충격적인 찬사이기도 하다. 정의 장치로서의 BNF의 강력함은 내가 언어의 약점이라고 보는 부분에도 책임이 있다. 지나치게 공들였고 그리 체계적이지 않은 문법이, 아주 적은 페이지 수 안에 욱여넣어질 수 있게 되었다. BNF 같은 강력한 장치가 있었다면, ALGOL 60 보고서는 훨씬 짧았어야 했다. 그 밖에도, 나는 ALGOL 60의 매개변수 메커니즘에 점점 회의적이 되었다. 그것은 프로그래머에게 너무 많은 조합적 자유를 허용하며, 그것을 자신 있게 쓰려면 강한 규율이 필요하다. 구현 비용도 비싸고, 사용하기에도 위험해 보인다.

마지막으로, 유쾌한 주제는 아니지만 PL/1을 언급해야겠다. 그 정의 문서는 크기와 복잡성이 두려울 정도인 프로그래밍 언어다. PL/1을 쓰는 것은 마치 조종석에 7000개의 버튼과 스위치, 손잡이가 달린 비행기를 모는 것과 같을 것이다. 우리 프로그램이 점점 커져도 그것을 우리의 지적 통제 안에 단단히 붙들어 두려면, 우리의 기본 도구—프로그래밍 언어!—가 지적 통제를 벗어나지 않아야 한다. 그런데 PL/1의 바로크적 난삽함은 이미 우리의 통제를 벗어나고 있다. PL/1이 사용자에게 미칠 영향을 비유하라면, 내게 떠오르는 가장 가까운 비유는 ‘약물’이다. 고급 프로그래밍 언어에 관한 심포지엄에서, PL/1을 옹호하는 한 연사가—자신을 PL/1의 헌신적 사용자라고 소개했는데—강연을 한 바 있다. 그러나 1시간의 찬양 강연 동안 그는 50개가량의 새로운 “기능”을 추가해 달라고 요청했다. 그의 문제의 주된 원천이, PL/1에 이미 너무 많은 “기능”이 들어 있다는 데 있을 수 있다는 점은 거의 눈치채지 못한 채 말이다. 그 연사는 중독의 모든 우울한 징후를 보였다. 더, 더, 더…라고 요청하는 것밖에 할 수 없는 정신적 정체 상태로 내려앉아 있었다. FORTRAN이 유아적 질환이라고 불렸다면, 위험한 종양처럼 성장하는 PL/1의 전모는 치명적 질병으로 판명날 수 있다.

과거는 이쯤 하자. 실수를 하는 데 의미가 있으려면, 그 다음에 우리가 그로부터 배울 수 있어야 한다. 사실 나는 우리가 충분히 많이 배워서, 몇 년 안에 프로그래밍이라는 활동이 지금까지와는 전혀 다른 모습이 될 수 있다고 생각한다. 너무 달라서 충격에 대비하는 편이 나을 것이다. 가능한 미래상 하나를 그려 보겠다. 언뜻 보기에는 이 가까운 미래의 프로그래밍 비전이 터무니없이 공상처럼 들릴지 모른다. 그러니 그런 비전에 이르게 만드는 고려사항도 덧붙이겠다. 그것이 아주 현실적인 가능성임을 시사하는 고려사항을.

그 비전은 이렇다. 1970년대가 끝나기 훨씬 전에, 지금 우리의 프로그래밍 능력을 한껏 긴장시키는 종류의 시스템을, 현재 투입되는 인년(人年)의 몇 퍼센트만으로 설계하고 구현할 수 있게 된다. 게다가 그 시스템은 사실상 버그가 거의 없다. 이 두 향상은 함께 간다. 후자의 점에서 소프트웨어는 다른 많은 제품과 다르다. 대개 더 높은 품질은 더 높은 가격을 의미하지만, 소프트웨어는 그렇지 않다. 정말 신뢰할 수 있는 소프트웨어를 원하는 이들은, 애초에 대다수의 버그를 피하는 방법을 찾아야 한다는 것을 발견할 것이다. 그 결과 프로그래밍 과정은 더 싸진다. 더 효과적인 프로그래머를 원한다면, 그들이 디버깅으로 시간을 낭비해서는 안 된다. 애초에 버그를 집어넣지 말아야 한다. 달리 말하면, 두 목표는 같은 변화를 가리킨다.

그렇듯 짧은 시간에 그런 극적인 변화가 일어나는 것은 혁명일 것이다. 최근 과거의 완만한 외삽에 근거해 미래를 기대하는—사회·문화적 관성의 불문율을 호소하는—사람들에게는, 그런 변화가 일어날 가능성이 미미해 보일 것이다. 하지만 혁명이 때로는 일어난다는 것을 우리는 모두 안다! 이번 혁명의 가능성은 얼마나 될까?

세 가지 대조건이 충족되어야 한다. 세상은 변화의 필요를 인정해야 하며, 둘째로 그에 대한 경제적 필요가 충분히 강해야 하고, 셋째로 변화가 기술적으로 가능한 것이어야 한다. 이 세 조건을 순서대로 논하겠다.

소프트웨어의 더 큰 신뢰성에 대한 필요의 인정에 관해서는 더 이상 이견이 없으리라 본다. 불과 몇 년 전만 해도 달랐다. 소프트웨어 위기를 말하는 것 자체가 불경이었다. 전환점은 1968년 10월 가르미슈의 소프트웨어 공학 회의였다. 그 회의에서 소프트웨어 위기가 처음으로 공개적으로 인정되었고, 큰 반향을 낳았다. 이제는 규모가 크고 정교한 시스템의 설계가 매우 어려운 일이 될 것이라는 점이 일반적으로 인정되고 있다. 그런 일을 맡은 사람들을 만나보면, 그들이 신뢰성 문제를 크게 우려함을 알 수 있다. 당연한 일이다. 요컨대 우리의 첫 번째 조건은 충족된 듯하다.

이제 경제적 필요를 보자. 요즘, 60년대에 프로그래밍은 과대평가된 직업이었고, 앞으로 프로그래머의 급여가 내려갈 것이라는 의견을 자주 만난다. 대개 불황과 관련 지어 이렇게 말하지만, 사실 이것은 다른, 꽤 건강한 징후일 수도 있다. 어쩌면 지난 10년의 프로그래머들이 해야 할 만큼 잘하지 못했을지도 모른다는 뜻이다. 사회는 프로그래머의 성과와 그들의 제품에 만족하지 못하고 있다. 하지만 훨씬 더 큰 요인이 있다. 현재 특정 시스템을 위해 소프트웨어 개발에 지불하는 가격은, 필요한 하드웨어 가격과 같은 자릿수인 것이 흔하며, 사회는 이를 대강 받아들이고 있다. 그러나 하드웨어 제조업체는 다음 10년 동안 하드웨어 가격이 10분의 1로 떨어질 수 있다고 말한다. 소프트웨어 개발이 지금처럼 서투르고 비싼 과정으로 남아 있다면, 균형은 완전히 무너질 것이다. 사회가 이를 받아들일 것이라 기대할 수 없다. 그러므로 우리는 프로그래밍을 한 자릿수 배 더 효과적으로 하는 법을 반드시 배워야 한다. 달리 말하면, 예산에서 기계가 가장 큰 항목이던 때에는 프로그래밍 직종이 서투른 기법으로 버틸 수 있었지만, 그 우산은 급격히 접힐 것이다. 요컨대 두 번째 조건도 충족된 듯하다.

이제 세 번째 조건, 기술적으로 가능한가? 가능하다고 본다. 그 견해를 지지하는 여섯 가지 논거를 제시하겠다.

프로그램 구조 연구는, 동일한 과제와 같은 수학적 내용을 담은 대체 프로그램이라 해도, 지적으로 감당하기 쉬운 정도가 엄청나게 다를 수 있음을 보여주었다. 프로그램의 지적 관리 가능성을 심각하게 훼손하거나 완전히 파괴하는 규칙들이 몇 가지 발견되었다. 이 규칙에는 두 종류가 있다. 첫째 종류는 적절히 선택된 프로그래밍 언어로 기계적으로 강제할 수 있다. 예를 들면 goto 문 배제, 출력 매개변수가 둘 이상인 프로시저 배제 등을 들 수 있다. 둘째 종류는—아마 내 역량 부족 탓일 수도 있으나—기계적으로 강제하는 방법을 모르겠다. 일종의 자동 정리 증명기가 필요한 듯한데, 그런 것이 존재한다는 증거를 나는 갖고 있지 않다. 그래서 당분간, 어쩌면 영원히, 둘째 종류의 규칙은 프로그래머에게 요구되는 규율의 요소로 남는다. 내가 염두에 둔 규칙들 가운데 일부는 아주 분명하여, 가르칠 수 있을 만큼 명확하고, 특정 프로그램이 그것을 위반했는지에 대해 논란이 일어날 필요가 없다. 예를 들면, 어떤 루프도 종료성에 대한 증명 없이, 그리고 반복 실행되는 문장이 파괴하지 않을 불변 관계를 명시하지 않고는 작성되어서는 안 된다는 요구가 있다.

나는 우리가 지적으로 감당 가능한 프로그램의 설계와 구현에 한정하자고 제안한다. 누군가 이 제한이 너무 엄격해서 우리가 감당할 수 없을 것이라 걱정한다면, 그를 안심시킬 수 있다. 지적으로 감당 가능한 프로그램의 범주는 여전히, 알고리즘적으로 풀 수 있는 어떤 문제에 대해서도 매우 현실적인 프로그램을 담을 만큼 충분히 풍부하다. 우리는 우리의 일이 프로그램을 만드는 것이 아니라, 원하는 행태를 보일 계산의 류(類)를 설계하는 일임을 잊지 말아야 한다. 지적으로 감당 가능한 프로그램에 한정하자는 제안은, 내가 예고한 여섯 논거 가운데 첫 두 가지의 토대다.

논거 하나. 프로그래머가 고려해야 할 것이 지적으로 감당 가능한 프로그램뿐이라면, 그가 선택해야 할 대안은 훨씬 다루기 쉬워진다.

논거 둘. 지적으로 감당 가능한 프로그램의 부분집합으로 스스로를 제한하기로 결정하는 순간, 우리가 고려해야 할 해 공간(solution space)이 일거에 대폭 줄어든다. 이것은 논거 하나와 구별되는 논거다.

논거 셋은 프로그램 정당성(correctness)의 구성적 접근에 근거한다. 오늘날 통상적 기법은 프로그램을 먼저 만들고, 그다음 테스트하는 것이다. 그러나 테스트는 버그의 ‘존재’를 보이는 데에는 매우 효과적일 수 있지만, 버그의 ‘부재’를 보이는 데에는 절망적으로 부적절하다. 프로그램에 대한 신뢰도를 유의미하게 끌어올리는 유일한 효과적 방법은, 그것의 정당성에 대한 설득력 있는 증명을 제시하는 것이다. 하지만 프로그램을 먼저 만들고 나중에 정당성을 증명해서는 안 된다. 그렇게 하면 증명을 마련해야 한다는 요구가 불쌍한 프로그래머의 짐을 더할 뿐이다. 반대로 해야 한다. 프로그래머는 정당성 증명과 프로그램을 함께 자라게 해야 한다. 논거 셋은 본질적으로 다음 관찰에 기초한다. 먼저 어떤 정당성 증명이 설득력 있으려면 어떤 구조가 되어야 하는지를 스스로에게 묻고, 그것을 찾은 다음에 그 증명의 요구 사항을 만족하는 프로그램을 구성하면, 이러한 정당성 고려가 매우 효과적인 발견법적 안내 역할을 한다는 것이다. 정의상 이 접근은 우리가 지적으로 감당 가능한 프로그램으로 제한할 때에만 적용 가능하다. 그러나 그 안에서 만족스러운 것을 찾는 데 효과적인 수단을 제공한다.

논거 넷은, 프로그램 길이에 따라 프로그램 설계에 필요한 지적 노력이 어떻게 달라지는가와 관련이 있다. 프로그램 길이의 제곱에 비례해 지적 노력이 든다는 일종의 자연법칙이 있다는 제안이 있었다. 다행히도 아무도 이 법칙을 증명하지 못했다. 그럴 필요가 없기 때문이다. 유한한 추론이 무수한 경우를 포괄할 수 있게 해 주는 유일한 정신적 도구를 우리는 “추상화”라고 부른다. 그 결과, 자신의 추상화 능력을 효과적으로 활용하는 일은 유능한 프로그래머의 가장 중요한 활동 가운데 하나로 여겨져야 한다. 이와 관련해 덧붙일 가치가 있는 점이 있다. 추상화의 목적은 막연해지기 위함이 아니라, 절대적으로 정밀할 수 있는 새로운 의미 수준을 만들어 내기 위함이다. 우리의 추상화 메커니즘이 충분히 효과적이지 못하도록 막는 근본 원인이 있는지 찾아보려 했다. 아무리 애써도 그런 원인을 찾지 못했다. 그 결과—지금까지의 경험에 의해 반증되지 않은—가정을 하게 되었다. 적절한 추상화의 적용을 통해, 프로그램을 고안하거나 이해하는 데 필요한 지적 노력은 프로그램 길이에 비례 이상으로 증가할 필요가 없다는 가정이다. 그러나 이 탐구의 부산물이 실무적으로 훨씬 더 중요할 수 있으며, 사실상 내 네 번째 논거의 기반이 된다. 그 부산물은, 프로그램을 구성하는 전 과정에서 핵심적 역할을 하는 몇 가지 추상화 패턴을 확인한 것이다. 이제 우리는 이 추상화 패턴들에 관해 꽤 많은 것을 안다. 각각에 대해 한 강연씩 할 수 있을 정도다. 이 추상화 패턴들에 대한 친숙함과 의식적 지식이 함의하는 바를 나는 이렇게 깨달았다. 15년 전에 그것들이 공지의 사실이었다면, 예컨대 BNF에서 구문 지향 컴파일러로의 도약은 몇 년이 아니라 몇 분이면 되었을 것이다. 그러므로 나는 이러한 핵심 추상화 패턴에 대한 최근의 지식을 네 번째 논거로 제시한다.

이제 다섯 번째 논거. 우리가 쓰려는 도구가 우리의 사고 습관에 미치는 영향에 관한 것이다. 나는 어떤 문화적 전통을 관찰한다. 아마 르네상스에 뿌리를 둔 전통일 텐데, 이 영향은 무시하고 인간의 정신을 자신의 산물에 대해 최고이자 자율적인 주인으로 여기려는 전통이다. 그러나 내 자신과 동료 인간들의 사고 습관을 분석하기 시작하면—좋든 싫든—전혀 다른 결론에 이르게 된다. 우리가 쓰려는 도구와, 우리의 생각을 표현하고 기록하는 언어·표기법이, 우리가 무엇을 생각하고 표현할 수 있는지를 결정하는 주요 요인이라는 결론이다! 프로그래밍 언어가 사용자들의 사고 습관에 미치는 영향에 대한 분석, 그리고 이제 두뇌력이 단연코 가장 희소한 자원이라는 인식은, 여러 프로그래밍 언어의 상대적 장점을 비교하기 위한 새로운 자를 우리에게 준다. 유능한 프로그래머는 자신의 두개골 용량이 엄격히 제한되어 있음을 잘 안다. 그러므로 그는 충만한 겸손으로 프로그래밍 과제에 접근하며, 그 밖의 것들 가운데에서도, 교묘한 요령을 전염병처럼 피한다. 잘 알려진 대화형 프로그래밍 언어 하나의 경우, 그 언어의 터미널을 갖게 되면 프로그래밍 공동체에서 특정 현상이—‘원라이너(one-liner)’라는—정착된 이름까지 붙어—발생한다는 말을 여기저기서 들었다. 이 현상은 두 가지 형태 가운데 하나로 나타난다. 한 프로그래머가 다른 프로그래머의 책상에 한 줄짜리 프로그램을 올려놓고는, 자랑스럽게 그것이 무엇을 하는지를 말하고 “이걸 더 적은 기호로 코딩할 수 있겠어?”라고 묻는다—마치 그것이 개념적으로라도 의미가 있는 양!—. 아니면 그냥 “이게 뭘 하는지 맞혀봐!”라고 묻는다. 이 관찰에서 우리는, 그 언어라는 도구가 교묘한 요령을 마구 부리도록 하는 열린 초대장임을 결론지어야 한다. 바로 이것이 그 언어의 매력의 일부—자신이 얼마나 영리한지를 과시하길 좋아하는 이들에게—의 설명일 수 있겠지만, 유감스럽게도 나는 이것이 프로그래밍 언어에 대해 말할 수 있는 가장 가혹한 비난 가운데 하나라고 보아야 한다. 최근의 과거로부터 우리가 배워야 할 또 다른 교훈은, “더 풍부한” “더 강력한” 프로그래밍 언어의 개발이 실수였다는 점이다. 그런 바로크적 괴물, 기벽의 집합체는 기계적으로도, 정신적으로도 정말로 감당할 수 없다. 나는 매우 체계적이고 매우 소박한 프로그래밍 언어에 큰 미래가 있다고 본다. “소박한”의 의미는, 예컨대 ALGOL 60의 for 절뿐 아니라, FORTRAN의 DO 루프조차 너무 바로크적이라 내던져질 수 있다는 뜻이다. 나는 숙련된 지원자들과 작은 프로그래밍 실험을 해 본 적이 있다. 그런데 전혀 의도치도, 예상치도 못한 일이 벌어졌다. 어느 지원자도 가장 분명하고 가장 우아한 해법을 찾지 못했다. 자세히 분석해 보니, 그 공통 원인은, 반복이라는 개념을 ‘증가시켜 가는 제어 변수’와 너무 단단히 결합해서 생각하는 바람에, 분명한 것을 보지 못하도록 정신적으로 막혔다는 점이었다. 그들의 해법은 덜 효율적이었고, 쓸데없이 이해하기 어려웠으며, 그것을 찾는 데 터무니없이 오랜 시간이 걸렸다. 내게는 계몽적이면서도 충격적인 경험이었다. 마지막으로, 한 가지 면에서 내일의 프로그래밍 언어는 지금 우리가 익숙한 것과 크게 달라지길 바란다. 지금까지보다 훨씬 큰 폭으로, 우리가 설계하려는 것의 복잡성을 개념적으로 다루는 데 필요한 모든 추상화를, 우리가 적어 넣는 코드의 구조 속에 반영하도록 우리를 초대해야 한다. 미래 도구의 더 큰 적합성은 다섯 번째 논거의 기반이었다.

곁다리로, 프로그래밍 과제의 어려움을 현재 도구의 결함과 싸우는 일과 동일시하는 이들에게 경고를 하나 덧붙이고 싶다. 그들은 도구가 훨씬 더 적합해지면 프로그래밍은 더 이상 문제가 아니게 될 것이라는 결론에 이를지 모른다. 프로그래밍은 여전히 매우 어려울 것이다. 주변의 번거로움에서 우리 자신을 해방시키는 순간, 우리는 지금의 프로그래밍 역량으로는 한참 넘는 문제들을 다룰 자유를 얻게 될 것이기 때문이다.

여섯 번째 논거는 논쟁의 여지가 있을 수 있다. 그것을 지지할 실험적 증거를 모으기가 쉽지 않기 때문이다. 그럼에도 나는 그 유효성을 믿는다. 지금까지 “계층(hierarchy)”이라는 단어를 입에 올리지 않았지만, 이것이 단정히 분해된 해법을 구현하는 모든 시스템의 핵심 개념이라는 점은 공평하게 말할 수 있을 것이다. 더 나아가, 믿음의 조항으로까지 나아갈 수 있다. 우리가 정말로 만족스럽게 풀 수 있는 문제는, 결국 단정히 분해된 해법을 허용하는 문제뿐이라는 것이다. 처음 들으면 인간의 한계를 다소 우울하게 보는 관점처럼 느껴질지 모르지만, 나는 전혀 그렇게 느끼지 않는다. 오히려 그 반대다! 우리의 한계를 배우는 최선의 방법은 그것을 아는 것이다. 다른 시도들은 우리의 지적 손아귀를 벗어나기에, 우리는 오직 분해형 해법만 시도할 만큼 충분히 겸손해지는 때, 시스템을 유익하게 분해할 능력을 해치는 모든 인터페이스를 피하려 최선을 다할 것이다. 그리고 나는, 처음에는 다루기 어려웠던 문제가 결국 분해 가능하다는 발견이 반복해서 일어나리라 기대한다. “코드 생성”이라고 불리는 컴파일 단계의 대다수 문제가, 명령 코드의 희한한 성질로 거슬러 올라갈 수 있음을 본 사람은, 내가 염두에 둔 것의 간단한 예를 알고 있을 것이다. 단정히 분해된 해법의 더 넓은 적용 가능성이, 현 시기에 일어날지 모르는 혁명의 기술적 실현 가능성에 대한 나의 여섯 번째이자 마지막 논거다.

원칙적으로, 내 고려사항에 얼마나 무게를 둘지는 여러분에게 맡기겠다. 남에게 내 신념을 강요할 수 없음을 잘 안다. 모든 진지한 혁명이 그러하듯, 이는 격렬한 반대를 부를 것이다. 그런 전개를 방해하려는 보수적 힘이 어디에 있을지 자문해 보자. 나는 그것이 대기업, 심지어 컴퓨터 업계에 주로 있지는 않으리라 본다. 나는 오히려 오늘의 교육을 제공하는 교육 기관들, 그리고 자신들의 오래된 프로그램이 너무 중요하다고 생각해 그것을 다시 쓰고 개선할 가치가 없다고 여기는 보수적 사용자 집단에게서 그것을 예상한다. 이와 관련해, 많은 대학 캠퍼스에서 중앙 컴퓨팅 설비의 선택이 너무나 자주, 몇몇 기성의—하지만 비용이 많이 드는—응용의 요구에 의해 좌우되었고, 자신의 프로그램을 기꺼이 쓰려는 수천의 ‘소사용자’들이 그 선택 때문에 얼마나 고통 받을지를 묻는 질문은 경시되었다는 사실은 슬프다. 이를테면 고에너지 물리학이 남은 실험 장비의 가격으로 과학 공동체를 협박해 온 경우가 너무 잦았다. 물론 가장 쉬운 대응은 기술적 실현 가능성을 일도 아니게 부정하는 것이다. 그러나 그러려면 꽤 강력한 논거가 필요하리라 본다. 오늘날 평균적 프로그래머의 지적 상한선이 혁명이 일어나는 것을 가로막아 줄 것이라는 말에서 위안을 얻을 수는 없다. 다른 이들이 훨씬 더 효과적으로 프로그래밍하게 되면, 그는 어차피 그림자밖으로 밀려날 수 있기 때문이다.

정치적 장애물도 있을 수 있다. 우리가 내일의 프로 프로그래머를 어떻게 교육해야 하는지 안다 해도, 우리가 사는 사회가 그것을 허락할지는 확실치 않다. 지식 전파가 아니라 방법론을 가르치는 첫 번째 효과는, 이미 유능한 이들의 능력을 더 키워 지능의 격차를 확대하는 것이다. 교육 시스템이 균질화된 문화를 확립하기 위한 도구로 쓰이는 사회, 즉 크림이 위에 뜨는 것을 막는 사회에서는, 유능한 프로그래머의 교육이 정치적으로 받아들이기 어려울 수 있다.

마무리하겠다. 자동식 컴퓨터가 우리 곁에 온 지 이제 4분의 1세기다. 도구로서 그것들은 사회에 큰 영향을 끼쳤다. 그러나 그 영향은 인류 문화사에서 전례 없는 지적 도전이라는 능력에서, 훨씬 더 심오한 영향을 끼치게 될 것이고, 도구로서의 영향은 그에 비하면 문화 표면에 이는 잔물결에 불과할 것이다. 계층적 시스템은, 어떤 수준에서 분해 불가능한 단일체로 여겨지는 것이 다음, 더 낮은 세부 수준에서는 합성물로 여겨지는 성질을 갖는 듯하다. 그 결과, 한 수준에서 다음 더 낮은 수준으로 관심을 옮길 때마다 적용 가능한 자연스러운 공간/시간의 눈금은 한 자릿수 배로 감소한다. 우리는 벽을 벽돌로, 벽돌을 결정으로, 결정을 분자로 이해한다. 그 결과, 계층적 시스템에서 의미 있게 구분할 수 있는 수준의 수는, 가장 큰 눈금과 가장 작은 눈금의 비율의 로그에 대체로 비례한다. 따라서 이 비율이 매우 크지 않다면, 많은 수준을 기대할 수 없다. 컴퓨터 프로그래밍에서 우리의 기본 빌딩 블록은 1마이크로초보다 짧은 시간 눈금을 갖지만, 우리의 프로그램은 계산에 몇 시간이 걸릴 수 있다. 10의 10제곱(또는 그 이상)의 비율을 아우르는 다른 기술을 나는 알지 못한다. 컴퓨터는 그 엄청난 속도 덕분에, 고도로 계층적인 인공물을 만들 수 있고 또 필요로 하는 환경을 처음으로 제공해 준 듯하다. 이 도전—프로그래밍 과제와의 대면—은 너무나 독특해서, 이 새로운 경험은 우리 자신에 대해 많은 것을 가르쳐 줄 수 있다. 그것은 설계와 창조의 과정에 대한 우리의 이해를 심화시키고, 우리의 사고를 조직하는 과제에 대한 더 나은 통제를 제공해야 한다. 그렇지 못한다면, 내 취향으로는 우리는 컴퓨터를 가질 자격이 없다!

이미 몇 가지 교훈을 얻었다. 이 강연에서 내가 강조하기로 선택한 교훈은 다음과 같다. 우리는 훨씬 더 나은 프로그래밍을 하게 될 것이다. 다만 그 과제의 엄청난 어려움을 충분히 인정하는 태도로 접근하고, 소박하면서도 우아한 프로그래밍 언어를 고수하며, 인간 정신의 본래적 한계를 존중하고, ‘매우 겸손한 프로그래머’로서 그 과제에 임할 때에 한해서다.