백년 언어

2003년 4월

(이 에세이는 PyCon 2003 기조연설에서 발췌했습니다.)

백년 후의 삶이 어떠할지 예측하기는 어렵습니다. 확실하게 말할 수 있는 것은 몇 가지뿐입니다. 모두가 나는 자동차를 운전하고, 수백 층짜리 건물을 허용하도록 구역 설정 법규가 완화될 것이며, 대부분의 시간이 어두울 것이고, 여성들은 모두 무술을 훈련받을 것이라는 점입니다. 여기서 저는 이 그림의 한 가지 세부 사항에 초점을 맞추고 싶습니다. 그들은 나는 자동차를 제어하는 소프트웨어를 작성하기 위해 어떤 종류의 프로그래밍 언어를 사용할까요?

이것은 우리가 실제로 이 언어들을 사용하게 될 것이기 때문이라기보다는, 운이 좋다면 이 지점에서 그 지점으로 가는 길에 있는 언어들을 사용하게 될 것이기 때문에 생각해 볼 가치가 있습니다.

저는 종처럼 언어도 진화 트리를 형성하고, 사방으로 막다른 길들이 갈라져 나갈 것이라고 생각합니다. 우리는 이미 이런 현상이 일어나고 있음을 볼 수 있습니다. Cobol은 한때 인기가 있었음에도 불구하고, 지적인 후손이 없는 것 같습니다. 그것은 진화의 막다른 길, 즉 네안데르탈 언어입니다.

저는 Java에도 비슷한 운명이 닥칠 것이라고 예측합니다. 사람들이 가끔 저에게 "Java가 성공적인 언어가 아닐 것이라고 어떻게 말할 수 있습니까? 이미 성공적인 언어인데요."라고 메일을 보냅니다. 그리고 저는 그것에 대한 책들이 차지하는 서가 공간(특히 개별 책들)이나 취업을 위해 배워야 한다고 믿는 학부생의 수로 성공을 측정한다면, 그렇다고 인정합니다. 제가 Java가 성공적인 언어가 아닐 것이라고 말할 때, 저는 좀 더 구체적인 의미를 말하는 것입니다. 즉, Java는 Cobol처럼 진화의 막다른 길이 될 것이라는 뜻입니다.

이것은 단지 추측일 뿐입니다. 제가 틀릴 수도 있습니다. 여기서 제 요점은 Java를 폄하하려는 것이 아니라, 진화 트리의 문제를 제기하고 사람들이 '언어 X는 이 트리에서 어디에 있는가?'라고 묻게 하려는 것입니다. 이 질문을 하는 이유는 백년 후에 우리의 유령이 '내가 말했잖아!'라고 말하기 위함만이 아닙니다. 지금 프로그래밍하기 좋은 언어를 찾는 데 있어 주요 가지에 가까이 머무는 것이 유용한 발견적 방법이기 때문입니다.

어느 시점에서든, 당신은 아마도 진화 트리의 주요 가지에 있을 때 가장 행복할 것입니다. 네안데르탈인이 여전히 많았을 때조차도, 네안데르탈인으로 사는 것은 힘들었을 것입니다. 크로마뇽인들은 끊임없이 와서 당신을 때리고 음식을 훔쳐갔을 테니까요.

제가 백년 후에 언어들이 어떠할지 알고 싶은 이유는 지금 어떤 트리의 가지에 걸어야 할지 알기 위함입니다.

언어의 진화는 종의 진화와 다릅니다. 가지들이 수렴할 수 있기 때문입니다. 예를 들어, Fortran 가지는 Algol의 후손들과 합쳐지는 것처럼 보입니다. 이론적으로는 종에게도 가능하지만, 세포보다 큰 생물에게는 일어났을 가능성이 낮습니다.

언어에서 수렴이 더 가능성이 높은 이유는 부분적으로는 가능성의 공간이 더 작고, 부분적으로는 변이가 무작위적이지 않기 때문입니다. 언어 설계자들은 다른 언어의 아이디어를 의도적으로 통합합니다.

언어 설계자들이 프로그래밍 언어의 진화가 어디로 이어질지 생각하는 것은 특히 유용합니다. 그들이 그에 따라 방향을 잡을 수 있기 때문입니다. 이 경우, '주요 가지에 머무르라'는 좋은 언어를 선택하는 방법 이상이 됩니다. 그것은 언어 설계에 대한 올바른 결정을 내리기 위한 발견적 방법이 됩니다.

모든 프로그래밍 언어는 두 부분으로 나눌 수 있습니다. 공리의 역할을 하는 일련의 기본 연산자들과, 원칙적으로 이 기본 연산자들을 사용하여 작성될 수 있는 나머지 언어입니다.

저는 기본 연산자들이 언어의 장기적인 생존에 가장 중요한 요소라고 생각합니다. 나머지는 바꿀 수 있습니다. 집을 살 때 위치를 최우선으로 고려해야 한다는 규칙과 같습니다. 다른 모든 것은 나중에 고칠 수 있지만, 위치는 고칠 수 없습니다.

저는 공리들이 잘 선택되는 것뿐만 아니라, 그 수가 적어야 한다고 생각합니다. 수학자들은 항상 공리에 대해 이런 식으로 생각했습니다. 적을수록 좋다고 말이죠. 그리고 저는 그들이 뭔가 중요한 것을 발견했다고 생각합니다.

적어도, 언어의 핵심을 면밀히 살펴 제거할 수 있는 공리가 있는지 확인하는 것은 유용한 연습이 될 것입니다. 저는 게으름뱅이로서의 오랜 경력에서 잡동사니가 잡동사니를 낳는다는 것을 발견했으며, 침대 밑이나 방 구석뿐만 아니라 소프트웨어에서도 이런 현상을 보았습니다.

저는 진화 트리의 주요 가지가 가장 작고 깔끔한 핵심을 가진 언어들을 통과한다고 예감합니다. 언어 자체로 더 많은 부분을 작성할 수 있을수록 더 좋습니다.

물론, 제가 백년 후에 프로그래밍 언어가 어떠할지 묻는 것 자체가 큰 가정을 하는 것입니다. 백년 후에도 우리가 프로그램을 작성하고 있을까요? 컴퓨터에게 우리가 원하는 것을 말하기만 하면 되지 않을까요?

지금까지 그 분야에서는 많은 진전이 없었습니다. 제 생각에는 백년 후에도 사람들은 우리가 인식할 수 있는 프로그램들을 사용하여 컴퓨터에게 무엇을 할지 지시할 것입니다. 지금은 프로그램을 작성하여 해결하는 작업 중 백년 후에는 프로그램을 작성할 필요가 없는 작업도 있겠지만, 저는 오늘날 우리가 하는 유형의 프로그래밍이 여전히 상당 부분 존재할 것이라고 생각합니다.

어떤 기술이 백년 후에 어떻게 보일지 예측할 수 있다고 생각하는 것은 주제넘게 보일 수 있습니다. 하지만 우리는 이미 거의 50년의 역사를 가지고 있다는 것을 기억하십시오. 지난 50년 동안 언어가 얼마나 느리게 진화했는지 고려할 때, 백년 앞을 내다보는 것은 이해할 수 있는 생각입니다.

언어는 기술이 아니기 때문에 느리게 진화합니다. 언어는 표기법입니다. 프로그램은 컴퓨터가 당신을 위해 해결하기를 원하는 문제에 대한 형식적인 설명입니다. 따라서 프로그래밍 언어의 진화 속도는 운송이나 통신보다 수학적 표기법의 진화 속도와 더 비슷합니다. 수학적 표기법은 진화하지만, 기술에서 볼 수 있는 거대한 도약과는 다릅니다.

백년 후에 컴퓨터가 무엇으로 만들어지든, 지금보다 훨씬 빠를 것이라고 예측하는 것은 안전해 보입니다. 무어의 법칙이 계속된다면, 컴퓨터는 7400경(73,786,976,294,838,206,464) 배 더 빨라질 것입니다. 상상하기 어려운 수치입니다. 그리고 실제로 속도 부문에서 가장 가능성 있는 예측은 무어의 법칙이 작동을 멈출 것이라는 점일 수 있습니다. 18개월마다 두 배가 되어야 하는 모든 것은 결국 어떤 종류의 근본적인 한계에 부딪힐 가능성이 있습니다. 하지만 저는 컴퓨터가 훨씬 더 빨라질 것이라고 믿는 데 아무런 문제가 없습니다. 설령 고작 백만 배만 빨라진다고 해도, 그것은 프로그래밍 언어의 기본 규칙을 상당히 바꿀 것입니다. 무엇보다도, 지금은 느린 언어로 간주될 수 있는, 즉 효율적인 코드를 생성하지 못하는 언어들을 위한 공간이 더 많아질 것입니다.

그럼에도 불구하고 일부 애플리케이션은 여전히 속도를 요구할 것입니다. 우리가 컴퓨터로 해결하려는 문제 중 일부는 컴퓨터에 의해 생성됩니다. 예를 들어, 비디오 이미지를 처리해야 하는 속도는 다른 컴퓨터가 이미지를 생성할 수 있는 속도에 따라 달라집니다. 그리고 본질적으로 무한한 사이클을 소비할 수 있는 또 다른 종류의 문제들이 있습니다. 이미지 렌더링, 암호화, 시뮬레이션 등이 그것입니다.

일부 애플리케이션은 점점 더 비효율적일 수 있는 반면, 다른 애플리케이션은 하드웨어가 제공할 수 있는 모든 속도를 계속 요구한다면, 더 빠른 컴퓨터는 언어가 훨씬 더 넓은 범위의 효율성을 포괄해야 함을 의미할 것입니다. 우리는 이미 이런 현상이 일어나고 있음을 보았습니다. 일부 인기 있는 새로운 언어의 현재 구현은 지난 수십 년의 기준으로는 충격적일 정도로 낭비적입니다.

이것은 프로그래밍 언어에서만 일어나는 일이 아닙니다. 일반적인 역사적 추세입니다. 기술이 발전함에 따라, 각 세대는 이전 세대가 낭비적이라고 생각했을 일들을 할 수 있습니다. 30년 전 사람들은 우리가 장거리 전화를 얼마나 아무렇지 않게 거는지에 놀랄 것입니다. 100년 전 사람들은 언젠가 보스턴에서 뉴욕으로 가는 소포가 멤피스를 경유한다는 사실에 더욱 놀랄 것입니다.

저는 더 빠른 하드웨어가 앞으로 백년 동안 우리에게 줄 모든 추가 사이클에 무슨 일이 일어날지 이미 말씀드릴 수 있습니다. 그것들은 거의 모두 낭비될 것입니다.

저는 컴퓨터 성능이 부족했던 시절에 프로그래밍을 배웠습니다. 4K TRS-80의 메모리에 맞추기 위해 Basic 프로그램에서 모든 공백을 제거했던 것을 기억합니다. 이 모든 엄청나게 비효율적인 소프트웨어가 같은 일을 반복하며 사이클을 소모하는 것을 생각하면 저에게는 다소 역겹게 느껴집니다. 하지만 저는 여기서 제 직관이 틀렸다고 생각합니다. 저는 가난하게 자라서 의사에게 가는 것과 같은 중요한 일에도 돈을 쓰는 것을 참지 못하는 사람과 같습니다.

어떤 종류의 낭비는 정말 역겹습니다. 예를 들어, SUV는 연료가 고갈되지 않고 오염을 발생시키지 않는 연료로 작동하더라도 역겹다고 주장할 수 있습니다. SUV는 역겨운 문제(미니밴을 더 남성적으로 보이게 하는 방법)에 대한 해결책이기 때문에 역겹습니다. 하지만 모든 낭비가 나쁜 것은 아닙니다. 이제 그것을 지원할 인프라가 생겼으니, 장거리 통화 시간을 세는 것은 사소하게 느껴지기 시작합니다. 자원이 있다면, 상대방이 어디에 있든 모든 전화 통화를 한 가지 종류의 것으로 생각하는 것이 더 우아합니다.

좋은 낭비와 나쁜 낭비가 있습니다. 저는 좋은 낭비에 관심이 있습니다. 즉, 더 많이 소비함으로써 더 간단한 설계를 얻을 수 있는 종류의 낭비입니다. 우리는 새롭고 더 빠른 하드웨어로부터 얻을 사이클 낭비 기회를 어떻게 활용할까요?

속도에 대한 욕구는 우리의 보잘것없는 컴퓨터와 함께 우리 안에 너무 깊이 뿌리박혀 있어서, 그것을 극복하려면 의식적인 노력이 필요할 것입니다. 언어 설계에서 우리는 효율성을 아주 작은 편리함의 증가와 맞바꿀 수 있는 상황을 의식적으로 찾아야 합니다.

대부분의 데이터 구조는 속도 때문에 존재합니다. 예를 들어, 오늘날 많은 언어에는 문자열과 리스트가 모두 있습니다. 의미론적으로 문자열은 요소가 문자인 리스트의 부분집합과 거의 같습니다. 그렇다면 왜 별도의 데이터 유형이 필요할까요? 사실 필요 없습니다. 문자열은 효율성을 위해 존재할 뿐입니다. 하지만 프로그램을 더 빨리 실행하기 위한 꼼수로 언어의 의미론을 복잡하게 만드는 것은 한심한 일입니다. 언어에 문자열을 포함하는 것은 시기상조의 최적화 사례로 보입니다.

언어의 핵심을 공리 집합으로 생각한다면, 단순히 효율성을 위해 표현력을 추가하지 않는 추가 공리를 갖는 것은 분명히 역겨운 일입니다. 효율성은 중요하지만, 그것을 얻을 올바른 방법이라고 생각하지 않습니다.

그 문제를 해결하는 올바른 방법은 프로그램의 의미를 구현 세부 사항과 분리하는 것이라고 생각합니다. 리스트와 문자열을 모두 갖는 대신, 필요할 경우 컴파일러가 문자열을 연속적인 바이트로 배치할 수 있도록 최적화 조언을 제공하는 방식으로 리스트만 갖는 것입니다.

대부분의 프로그램에서 속도는 중요하지 않으므로, 일반적으로 이런 종류의 미세 관리에 신경 쓸 필요가 없을 것입니다. 컴퓨터가 빨라질수록 이것은 더욱 사실이 될 것입니다.

구현에 대해 덜 말하는 것은 프로그램들을 더 유연하게 만들 것입니다. 프로그램이 작성되는 동안 사양은 변경되며, 이것은 불가피할 뿐만 아니라 바람직한 일입니다.

단어 'essay'는 프랑스어 동사 'essayer'에서 유래했으며, '시도하다'라는 뜻입니다. 원래 의미의 에세이는 무언가를 알아내기 위해 쓰는 것입니다. 이것은 소프트웨어에서도 마찬가지입니다. 저는 최고의 프로그램 중 일부는 저자들이 시작할 때 정확히 무엇을 작성하려는지 몰랐다는 점에서 에세이였다고 생각합니다.

Lisp 해커들은 이미 데이터 구조에 유연성을 갖는 것의 가치를 알고 있습니다. 우리는 프로그램의 첫 버전을 모든 것을 리스트로 처리하도록 작성하는 경향이 있습니다. 이러한 초기 버전은 너무나 충격적으로 비효율적이어서, 적어도 저에게는 스테이크를 먹을 때 그것이 어디서 왔는지 생각하지 않으려는 의식적인 노력이 필요한 것처럼, 그것들이 무엇을 하는지 생각하지 않으려는 의식적인 노력이 필요합니다.

백년 후의 프로그래머들이 가장 중요하게 찾을 것은, 믿을 수 없을 정도로 비효율적인 프로그램의 버전 1을 최소한의 노력으로 대충 만들 수 있는 언어일 것입니다. 적어도 그것이 오늘날의 용어로 우리가 설명하는 방식입니다. 그들은 프로그래밍하기 쉬운 언어를 원한다고 말할 것입니다.

비효율적인 소프트웨어는 역겹지 않습니다. 역겨운 것은 프로그래머에게 불필요한 작업을 시키는 언어입니다. 프로그래머 시간을 낭비하는 것이 진정한 비효율이며, 기계 시간을 낭비하는 것이 아닙니다. 컴퓨터가 빨라질수록 이것은 더욱 분명해질 것입니다.

저는 문자열을 없애는 것이 이미 우리가 생각해 볼 만한 일이라고 생각합니다. 우리는 Arc에서 그렇게 했고, 그것은 이득인 것 같습니다. 정규 표현식으로 설명하기 어색한 일부 연산들을 재귀 함수로 쉽게 설명할 수 있습니다.

이러한 데이터 구조의 평탄화는 어디까지 갈까요? 저는 의식적으로 마음을 넓혔음에도 불구하고 저조차도 충격받을 가능성들을 생각할 수 있습니다. 예를 들어, 배열을 없앨까요? 결국 배열은 키가 정수 벡터인 해시 테이블의 부분집합일 뿐입니다. 해시 테이블 자체를 리스트로 대체할까요?

그보다 더 충격적인 전망도 있습니다. 예를 들어, McCarthy가 1960년에 설명한 Lisp에는 숫자가 없었습니다. 논리적으로 숫자에 대한 별도의 개념을 가질 필요가 없습니다. 숫자를 리스트로 표현할 수 있기 때문입니다. 정수 n은 n개의 요소를 가진 리스트로 표현될 수 있습니다. 이런 식으로 수학을 할 수 있습니다. 단지 참을 수 없을 정도로 비효율적일 뿐입니다.

실제로 숫자를 리스트로 구현하자고 제안한 사람은 아무도 없었습니다. 사실, McCarthy의 1960년 논문은 당시 전혀 구현될 의도가 아니었습니다. 그것은 이론적인 연습이었고, 튜링 머신에 대한 더 우아한 대안을 만들려는 시도였습니다. 누군가가 예상치 못하게 이 논문을 가져다가 작동하는 Lisp 인터프리터로 번역했을 때, 숫자는 분명히 리스트로 표현되지 않았습니다. 다른 모든 언어에서처럼 이진수로 표현되었습니다.

프로그래밍 언어가 기본 데이터 유형으로서 숫자를 없애는 데까지 나아갈 수 있을까요? 저는 이것을 진지한 질문이라기보다는 미래와 '치킨 게임'을 하는 방식으로 묻는 것입니다. 그것은 저항할 수 없는 힘이 움직이지 않는 물체를 만나는 가상의 경우와 같습니다. 여기서는 상상할 수 없을 정도로 비효율적인 구현이 상상할 수 없을 정도로 거대한 자원을 만나는 것입니다. 저는 안 될 이유가 없다고 봅니다. 미래는 꽤 깁니다. 핵심 언어의 공리 수를 줄이기 위해 우리가 할 수 있는 일이 있다면, t가 무한대에 가까워질수록 그쪽에 걸어야 할 것 같습니다. 백년 후에도 그 아이디어가 여전히 참을 수 없어 보인다면, 천년 후에는 그렇지 않을 수도 있습니다.

이것을 명확히 하자면, 저는 모든 수치 계산이 실제로 리스트를 사용하여 수행될 것이라고 제안하는 것이 아닙니다. 저는 구현에 대한 추가적인 표기법이 있기 전에 핵심 언어가 이런 식으로 정의되어야 한다고 제안하는 것입니다. 실제로는 어떤 양의 수학을 하고자 하는 프로그램은 아마도 숫자를 이진수로 표현할 것이지만, 이것은 최적화이며 핵심 언어 의미론의 일부가 아닐 것입니다.

사이클을 소모하는 또 다른 방법은 애플리케이션과 하드웨어 사이에 여러 소프트웨어 계층을 두는 것입니다. 이것 또한 우리가 이미 보고 있는 추세입니다. 많은 최신 언어들이 바이트 코드로 컴파일됩니다. Bill Woods는 제게 경험상 각 해석 계층이 속도에서 10배의 비용을 발생시킨다고 말한 적이 있습니다. 이 추가 비용은 유연성을 제공합니다.

Arc의 첫 번째 버전은 이런 종류의 다단계 느림의 극단적인 사례였으며, 그에 상응하는 이점도 있었습니다. 그것은 Common Lisp 위에 작성된 고전적인 "메타순환" 인터프리터였고, McCarthy의 원래 Lisp 논문에 정의된 eval 함수와 확실한 가족 유사성을 가졌습니다. 전체 코드는 겨우 수백 줄에 불과하여 이해하고 변경하기 매우 쉬웠습니다. 우리가 사용한 Common Lisp인 CLisp 자체도 바이트 코드 인터프리터 위에서 실행됩니다. 그래서 여기에는 두 단계의 해석이 있었고, 그 중 하나(가장 상위)는 충격적으로 비효율적이었지만, 언어는 사용할 수 있었습니다. 간신히 사용할 수 있었지만, 사용할 수 있었습니다.

소프트웨어를 여러 계층으로 작성하는 것은 애플리케이션 내에서도 강력한 기술입니다. 상향식 프로그래밍(Bottom-up programming)은 프로그램을 일련의 계층으로 작성하는 것을 의미하며, 각 계층은 그 위에 있는 계층을 위한 언어 역할을 합니다. 이 접근 방식은 더 작고 유연한 프로그램을 만드는 경향이 있습니다. 또한 재사용성이라는 성배에 이르는 최고의 경로이기도 합니다. 언어는 정의상 재사용 가능합니다. 애플리케이션의 더 많은 부분을 해당 유형의 애플리케이션을 작성하기 위한 언어로 밀어 넣을수록, 소프트웨어의 재사용성이 높아질 것입니다.

어쩐지 재사용성이라는 아이디어가 1980년대에 객체 지향 프로그래밍에 붙었고, 아무리 반대되는 증거가 있어도 그것을 떨쳐내지 못하는 것 같습니다. 하지만 일부 객체 지향 소프트웨어가 재사용 가능하더라도, 그것을 재사용 가능하게 만드는 것은 객체 지향성 때문이 아니라 상향식(bottom-up) 특성 때문입니다. 라이브러리를 생각해 보세요. 그것들은 객체 지향 스타일로 작성되었든 아니든, 언어이기 때문에 재사용 가능합니다.

참고로 저는 객체 지향 프로그래밍의 종말을 예측하지 않습니다. 특정 전문 분야를 제외하고는 좋은 프로그래머에게 제공할 것이 많지 않다고 생각하지만, 대규모 조직에게는 저항할 수 없습니다. 객체 지향 프로그래밍은 스파게티 코드를 작성하는 지속 가능한 방법을 제공합니다. 그것은 일련의 패치로 프로그램을 축적하게 합니다. 대규모 조직은 항상 이런 식으로 소프트웨어를 개발하는 경향이 있으며, 저는 이것이 오늘날과 마찬가지로 백년 후에도 사실일 것이라고 예상합니다.

미래에 대해 이야기하는 한, 병렬 컴퓨팅에 대해 이야기하는 것이 좋습니다. 이 아이디어가 그곳에 살고 있는 것 같기 때문입니다. 즉, 언제 이야기하든 병렬 컴퓨팅은 미래에 일어날 일처럼 보입니다.

미래가 과연 그것을 따라잡을까요? 사람들은 적어도 20년 동안 병렬 컴퓨팅을 임박한 것으로 이야기해 왔지만, 지금까지 프로그래밍 관행에 큰 영향을 미치지 못했습니다. 아니면 그렇지 않나요? 이미 칩 설계자들은 그것에 대해 생각해야 하고, 다중 CPU 컴퓨터에서 시스템 소프트웨어를 작성하려는 사람들도 마찬가지입니다.

진정한 질문은 병렬성이 추상화의 사다리를 얼마나 높이 올라갈 것인가 하는 것입니다. 백년 후에는 애플리케이션 프로그래머에게까지 영향을 미칠까요? 아니면 컴파일러 작성자들이 생각하는 것이지만, 애플리케이션의 소스 코드에서는 보통 보이지 않는 것이 될까요?

한 가지 가능성이 높아 보이는 것은 병렬 처리 기회의 대부분이 낭비될 것이라는 점입니다. 이것은 우리가 부여받는 추가 컴퓨터 성능의 대부분이 낭비될 것이라는 저의 더 일반적인 예측의 특별한 경우입니다. 저는 기본 하드웨어의 엄청난 속도와 마찬가지로, 병렬 처리도 명시적으로 요청하면 사용할 수 있지만, 일반적으로는 사용되지 않을 것이라고 예상합니다. 이는 백년 후에 우리가 갖게 될 병렬 처리 방식이 특별한 애플리케이션을 제외하고는 대규모 병렬 처리가 아닐 것임을 의미합니다. 일반 프로그래머에게는 모든 프로세스가 병렬로 실행되도록 포크할 수 있는 것과 더 비슷할 것이라고 예상합니다.

그리고 이것은 데이터 구조의 특정 구현을 요청하는 것과 마찬가지로, 프로그램을 최적화하려고 할 때 프로그램 수명 후반에 하는 일이 될 것입니다. 버전 1은 데이터의 특정 표현에서 얻을 수 있는 이점을 무시하는 것처럼, 병렬 컴퓨팅에서 얻을 수 있는 이점도 일반적으로 무시할 것입니다.

특별한 종류의 애플리케이션을 제외하고는, 병렬 처리가 백년 후에 작성될 프로그램에 만연하지는 않을 것입니다. 만약 그렇다면 그것은 시기상조의 최적화가 될 것입니다.

백년 후에는 몇 개의 프로그래밍 언어가 있을까요? 최근에는 엄청나게 많은 새로운 프로그래밍 언어가 등장하는 것 같습니다. 그 이유 중 하나는 더 빠른 하드웨어가 프로그래머들이 애플리케이션에 따라 속도와 편의성 사이에서 다른 절충점을 만들 수 있도록 허용했기 때문입니다. 이것이 실제 추세라면, 백년 후에 우리가 갖게 될 하드웨어는 이를 더욱 증가시킬 것입니다.

그럼에도 불구하고 백년 후에는 널리 사용되는 언어가 몇 개에 불과할 수도 있습니다. 제가 이렇게 말하는 이유 중 하나는 낙관주의 때문입니다. 정말 잘한다면, 느린 버전 1을 작성하는 데 이상적이지만, 컴파일러에 올바른 최적화 조언을 제공하면 필요할 때 매우 빠른 코드도 생성할 수 있는 언어를 만들 수 있을 것 같습니다. 따라서 저는 낙관적이므로, 허용 가능한 효율성과 최대 효율성 사이에 큰 격차가 있더라도, 백년 후의 프로그래머들은 그 대부분을 아우를 수 있는 언어를 갖게 될 것이라고 예측합니다.

이 격차가 벌어질수록 프로파일러는 점점 더 중요해질 것입니다. 지금은 프로파일링에 거의 관심이 없습니다. 많은 사람들은 여전히 빠른 애플리케이션을 얻는 방법은 빠른 코드를 생성하는 컴파일러를 작성하는 것이라고 믿는 것 같습니다. 허용 가능한 성능과 최대 성능 사이의 격차가 벌어질수록, 빠른 애플리케이션을 얻는 방법은 한쪽에서 다른 쪽으로 가는 좋은 안내자를 갖는 것임이 점점 더 분명해질 것입니다.

언어가 몇 개에 불과할 수 있다고 말할 때, 저는 도메인 특화 "작은 언어"를 포함하지 않습니다. 저는 그런 임베디드 언어가 훌륭한 아이디어라고 생각하며, 그것들이 확산될 것이라고 예상합니다. 하지만 사용자들은 그 아래에 있는 범용 언어를 볼 수 있을 만큼 얇은 스킨으로 작성될 것이라고 예상합니다.

미래의 언어는 누가 설계할까요? 지난 10년간 가장 흥미로운 추세 중 하나는 Perl, Python, Ruby와 같은 오픈 소스 언어의 부상이었습니다. 언어 설계는 해커들에 의해 주도되고 있습니다. 지금까지의 결과는 지저분하지만, 고무적입니다. 예를 들어 Perl에는 놀랍도록 새로운 아이디어들이 있습니다. 많은 것들이 놀랍도록 나쁘지만, 야심 찬 노력에는 항상 그렇습니다. 현재의 변이 속도로 볼 때, 백년 후에 Perl이 무엇으로 진화할지는 아무도 모릅니다.

할 수 없는 자가 가르친다는 말은 사실이 아닙니다(제가 아는 최고의 해커 중 일부는 교수입니다). 하지만 가르치는 자가 할 수 없는 많은 것들이 있다는 것은 사실입니다. 연구는 제약적인 계급 제한을 부과합니다. 어떤 학문 분야에서든 연구해도 괜찮은 주제와 그렇지 않은 주제가 있습니다. 불행히도 허용되는 주제와 금지되는 주제의 구분은 대개 연구 논문에 기술될 때 얼마나 지적으로 들리는지에 기반하며, 좋은 결과를 얻는 데 얼마나 중요한지에 기반하지 않습니다. 극단적인 경우는 아마도 문학일 것입니다. 문학을 연구하는 사람들은 그것을 생산하는 사람들에게 조금이라도 유용할 만한 말을 거의 하지 않습니다.

과학 분야에서는 상황이 더 낫지만, 허용되는 작업과 좋은 언어를 만들어내는 작업 사이의 중첩은 실망스러울 정도로 작습니다. (Olin Shivers는 이에 대해 유창하게 불평했습니다.) 예를 들어, 타입은 연구 논문의 마르지 않는 샘처럼 보이지만, 정적 타이핑은 진정한 매크로를 배제하는 것처럼 보입니다. 제 생각에는 매크로 없이는 어떤 언어도 사용할 가치가 없습니다.

추세는 단순히 언어가 '연구'보다는 오픈 소스 프로젝트로 개발되는 것뿐만 아니라, 컴파일러 작성자보다는 언어를 사용해야 하는 애플리케이션 프로그래머에 의해 설계되는 방향으로 나아가고 있습니다. 이것은 좋은 추세이며 계속될 것이라고 예상합니다.

백년 후의 물리학이 거의 필연적으로 예측 불가능한 것과 달리, 저는 백년 후 사용자들에게 매력적일 언어를 지금 원칙적으로 설계하는 것이 가능할 수도 있다고 생각합니다.

언어를 설계하는 한 가지 방법은 컴파일러가 번역할 수 있는지 또는 하드웨어가 실행할 수 있는지와 상관없이 작성하고 싶은 프로그램을 그냥 적어보는 것입니다. 이렇게 하면 무한한 자원을 가정할 수 있습니다. 백년 후와 마찬가지로 오늘날에도 무한한 자원을 상상할 수 있어야 할 것 같습니다.

어떤 프로그램을 작성하고 싶을까요? 가장 적은 노력이 드는 것입니다. 하지만 정확히는 아닙니다. 프로그래밍에 대한 당신의 생각이 현재 익숙한 언어에 의해 이미 영향을 받지 않았다면, 가장 적은 노력이 들 입니다. 그러한 영향은 너무나 만연하여 그것을 극복하는 데 큰 노력이 필요합니다. 우리처럼 게으른 존재에게는 최소한의 노력으로 프로그램을 표현하는 방법이 명확할 것이라고 생각할 것입니다. 사실, 우리가 생각하는 가능성에 대한 우리의 아이디어는 우리가 생각하는 언어에 의해 너무나 제한되어 있어서, 더 쉬운 프로그램 공식화가 매우 놀랍게 느껴집니다. 그것들은 당신이 발견해야 하는 것이지, 자연스럽게 빠져드는 것이 아닙니다.

여기서 유용한 한 가지 요령은 프로그램의 길이를 작성하는 데 드는 노력의 근사치로 사용하는 것입니다. 물론 문자 수가 아니라, 구문 요소의 개수, 즉 구문 트리의 크기입니다. 가장 짧은 프로그램이 작성하는 데 가장 적은 노력이 든다고 정확히 말할 수는 없지만, 최소한의 노력이라는 모호하고 가까운 목표보다는 간결함이라는 확실한 목표를 지향하는 것이 더 낫습니다. 그러면 언어 설계 알고리즘은 다음과 같습니다. 프로그램을 보고 '이것을 더 짧게 작성할 방법이 없을까?'라고 묻는 것입니다.

실제로, 상상의 백년 언어로 프로그램을 작성하는 것은 핵심에 얼마나 가까운지에 따라 다양한 정도로 작동할 것입니다. 정렬 루틴은 지금도 작성할 수 있습니다. 하지만 백년 후에 어떤 종류의 라이브러리가 필요할지 지금 예측하기는 어려울 것입니다. 아마도 많은 라이브러리는 아직 존재하지 않는 도메인을 위한 것일 것입니다. 예를 들어, SETI@home이 작동한다면, 우리는 외계인과 통신하기 위한 라이브러리가 필요할 것입니다. 물론 그들이 이미 XML로 통신할 만큼 충분히 발전하지 않았다면 말이죠.

다른 극단에서는, 핵심 언어를 오늘날 설계할 수 있을 것이라고 생각합니다. 사실, 일부는 1958년에 이미 대부분 설계되었다고 주장할 수도 있습니다.

백년 언어가 오늘날 사용 가능하다면, 우리는 그것으로 프로그래밍하고 싶을까요? 이 질문에 답하는 한 가지 방법은 과거를 돌아보는 것입니다. 만약 1960년에 오늘날의 프로그래밍 언어가 사용 가능했다면, 누군가 그것들을 사용하고 싶어 했을까요?

어떤 면에서는 답은 '아니오'입니다. 오늘날의 언어는 1960년에는 존재하지 않았던 인프라를 가정합니다. 예를 들어, Python처럼 들여쓰기가 중요한 언어는 프린터 터미널에서는 잘 작동하지 않을 것입니다. 하지만 그런 문제들을 제쳐두고, 예를 들어 프로그램이 모두 종이에 작성되었다고 가정한다면, 1960년대의 프로그래머들은 우리가 지금 사용하는 언어로 프로그램을 작성하는 것을 좋아했을까요?

저는 그렇다고 생각합니다. 초기 언어의 유물이 프로그램이 무엇인지에 대한 그들의 생각에 내재되어 있던 상상력이 부족한 일부는 어려움을 겪었을 수도 있습니다. (포인터 연산 없이 어떻게 데이터를 조작할 수 있는가? goto 없이 어떻게 플로우차트를 구현할 수 있는가?) 하지만 가장 똑똑한 프로그래머들은 오늘날의 언어를 가졌다면 그것들을 최대한 활용하는 데 아무런 문제가 없었을 것이라고 생각합니다.

만약 우리가 지금 백년 언어를 가지고 있다면, 적어도 훌륭한 의사 코드가 될 것입니다. 그것을 사용하여 소프트웨어를 작성하는 것은 어떨까요? 백년 언어는 일부 애플리케이션을 위해 빠른 코드를 생성해야 할 것이므로, 아마도 우리 하드웨어에서 허용 가능한 수준으로 잘 실행될 만큼 효율적인 코드를 생성할 수 있을 것입니다. 백년 후의 사용자들보다 더 많은 최적화 조언을 제공해야 할 수도 있지만, 여전히 순이익이 될 수 있습니다.

이제 두 가지 아이디어를 결합하면 흥미로운 가능성을 제시합니다. (1) 백년 언어는 원칙적으로 오늘날 설계될 수 있으며, (2) 그러한 언어가 존재한다면 오늘날 프로그래밍하기에 좋을 수 있다는 것입니다. 이 아이디어들이 그렇게 펼쳐진 것을 보면, '지금 백년 언어를 작성해 보지 않을 이유가 무엇인가?'라고 생각하지 않기 어렵습니다.

언어 설계를 할 때, 저는 그런 목표를 가지고 그것을 의식적으로 염두에 두는 것이 좋다고 생각합니다. 운전을 배울 때 가르치는 원칙 중 하나는, 차를 도로에 그려진 줄에 보닛을 맞추는 것이 아니라, 멀리 있는 어떤 지점을 목표로 삼아 정렬하는 것입니다. 당신이 신경 쓰는 것이 다음 10피트에서 일어나는 일뿐이라 할지라도, 이것이 올바른 답입니다. 저는 우리가 프로그래밍 언어에서도 똑같이 할 수 있고 해야 한다고 생각합니다.

참고

저는 Lisp Machine Lisp이 선언(동적 변수 선언 제외)이 단지 최적화 조언일 뿐이며, 올바른 프로그램의 의미를 변경하지 않는다는 원칙을 구현한 첫 번째 언어라고 생각합니다. Common Lisp은 이를 명시적으로 언급한 첫 번째 언어인 것 같습니다.

감사

이 초고를 읽어준 Trevor Blackwell, Robert Morris, Dan Giffin에게 감사드립니다. 그리고 PyCon에서 연설하도록 초대해준 Guido van Rossum, Jeremy Hylton 및 나머지 Python 팀에게도 감사드립니다.