논리에서 태어난 언어와 필요에서 태어난 언어


컴퓨터 공학부

2008-11708 

전보영


읽을거리 part1에 있는 글과 비디오를 보면서, 논리에 근거하여 체계적으로 설계된 프로그래밍 언어와 당장 실용적으로 필요하기 때문에 만들어진 프로그래밍 언어의 차이에 대하여 생각하게 되었다. 이 둘은 크게 언어의 구성에 대한 측면과 언어의 보급에 대한 측면에서 서로 다른 특성을 나타내는데, 이런 차이를 통해 이 두 성격의 언어가 프로그래밍 언어의 발전 과정에서 어떤 역할을 맡고 있는지 짐작해 보았다.

먼저 필요에 의해 만들어진 언어의 대표적인 예로 C 언어를 꼽을 수 있다. 이 사실은 Dennis M. Ritchie가 쓴 ‘The Development of the C Language’에 잘 드러난다. 이 논문에 의하면 새로 구현한 운영체제(Unix)에서 쓸 시스템 프로그래밍 언어가 필요하여 기존의 언어 BCPL을 개량한 B를 만들었고, B의 단점을 보완하기 위해 데이터 타입을 도입하여 C를 탄생시켰다. 그 뒤로 개선점이 발견될 때마다 C는 조금씩 개량되었다. 1973년경, 하드웨어에 표준이 정해지면서 C도 발 빠르게 호환성을 제공하였고 세계적으로 널리 사용되는 언어로 도약했다. 이 때문에 많은 변형판이 나오게 되었고 1989년 국제 표준화 기구에서 C의 표준을 정하였다. 이렇게 수정에 수정을 거쳐 지금의 C 언어가 만들어졌으나, C는 여전히 많은 문제점을 안고 있다. Dennis M. Ritchie가 지적하는 문제점은 포인터 사용이 초보자에게 어렵다는 점, 타입을 강경하게 점검하지 않아 프로그래머의 실수가 많다는 점, 스트링을 다루기가 어렵고 메모리 동적 할당과 모듈화가 불편하다는 점 등이다.

다음으로, 논리에 기반을 두고 만든 대표적인 언어로 ML이 있다. Robin Milner와의 대담을 보면 전반부에 ML을 개발한 동기 및 과정에 대한 내용이 있고, 후반부에 Concurrency, Object-Oriented Programming, 나아가서 Computer Science 전반에 관한 Milner의 견해가 나와 있다. 후반부 Milner의 견해에서, 그는 어떤 문제를 해결할 때 구체적인 실례보다 그 문제를 포괄하는 논리 체계를 우선시한다는 것을 알 수 있다. 이런 견해는 ML의 개발에도 영향을 미친다. Milner는 실용적인 기술보다 프로그램의 근본을 이해하는 것에 관심이 있었으며 추론을 도와주는 프로그램을 만들려 했다. 그러던 중 Dana Scott의 Logic for Computable Functions(LCF)를 접하였고 이 논리를 프로그램 언어로 구현하여 발전시킨 것이 ML이다. ML을 개발하는 도중에도 구현에 앞서 언어의 정밀한 정의를 만들면서 언어를 설계하였다. 또 ML의 특징은 논리적 증명이나 추론에 용이한 함수형 언어라는 점과 안전성 증진을 가져오는 강력한 타입 시스템인데, 이 두 가지 아이디어 역시 논리학에 기반을 두고 있다. Philip Wadler가 쓴 ‘Proofs are Programs: 19th Century Logic and 21st Century Computing’을 보면, 두 논리학 이론이 프로그래밍 언어 설계에 어떤 영향을 미치는지 설명한다. 먼저 증명을 위한 논리 체계 natural deducton과 간결한 방법으로 함수를 표현한 lambda calculus, 그것에 타입을 도입한 typed lambda calculus를 각각 소개한다. 그런 다음 natural deducton의 증명 규칙과 typed lambda calculus의 타입 도출 규칙이 유사하다는 점에 착안하여 증명을 간단하게 만드는 것과 프로그램을 실행시키는 것(계산하는 것)은 서로 대응된다는 이론을 설명한다. 즉 증명과 프로그램은 같은 것이다. 이 이론에서 수많은 논리와 타입 시스템, 프로그래밍 언어 등이 파생되었고 ML도 그 중 하나로 언급되어 있다.

이 두 프로그래밍 언어는 구조면에서 큰 차이를 보인다. 당시의 필요에 따라 만들어진 언어, 즉 C 언어는 이미 존재하는 언어를 필요에 따라 개량하여 만들었다. 처음부터 큰 구상을 가지고 만든 언어가 아니기 때문에 사용할수록 모르던 문제점이 발생했다. 그런데 C 언어 개발자들이 취한 대응 방법은 문제점이 발견되면 그때마다 당장 드러난 문제를 보완하는 방향으로 언어를 수정하는 것이었다. 언어의 구조를 분석하여 문제의 근본적인 원인이 무엇인지 밝히지 않고 눈앞에 닥친 문제만 해결하는 이런 방식은 임시방편에 불과했다. 당시에 그들이 맞닥뜨린 몇 가지 불편은 해결되었을지 모르지만 여러 번 수정을 거듭하여 표준 C가 정의된 지금도 C 언어의 구조는 완성되었다기보다 엉성한 모습에 가깝다. 반면 오랜 시간동안 논리에 근거하여 설계된 ML은 C 언어와 뚜렷한 차이를 보인다. 언어를 설계하기 시작한 목적은 C 언어처럼 실용적인 부분보다 연구적인 성격이 강하다. 프로그래밍 언어 자체가 필요했던 것이 아니라, LCF라는 논리 체계를 이용해서 컴퓨터가 논리적 증명을 할 수 있음을 보이고 싶다는 것이 동기였기 때문이다. 따라서 ML 개발진은 구현에 급급하지 않고 충분한 시간을 들여 언어의 구조를 철저하게 설계했고 언어의 정의도 수학적 표현으로 명확하게 내리려했다. 이렇게 작은 부분에 집중하기보다 큰 시각에서 설계했기 때문에 언어가 치밀하고 체계화되어 있다.

또 언어가 보급되는 속도에 관해서도 두 언어는 서로 상반되는 특성을 보인다. 시대의 흐름에서 지금 필요한 것을 반영하여 빠르게 구현한 언어는 당연히 급속도로 널리 보급될 것이다. C 언어에서 그 예를 찾아볼 수 있는데, 개발자들은 IBM360 등 표준화된 하드웨어가 나오던 시대적 흐름에서 프로그래밍 언어에 호환성이 필요함을 읽고 C 언어에 그것을 빠르게 반영했다. 그러자 불과 몇 년 사이에 C 언어는 널리 확산되었고 10년이 채 지나지 않아 거의 모든 컴퓨터와 운영체제에서 사용되었다. 이에 반해 ML은 예상하지 못한 경로로 사람들에게 알려졌다. 그 계기는 어느 이름 없는 대학원생이 박사 학위 논문으로 ML을 확장하여 구현한 것이었다. 이 일로 몇몇 사람들이 학생들에게 프로그래밍을 가르칠 때 ML이 유용하다는 사실을 알게 되었고 교육용 언어로서 조금씩 퍼져나갔다. 이렇게 ML은 개발의 본래 의도와 상관없는 우연한 사건으로 보급되었다. 이런 우연성이 없었다면 당시에 그렇게 많은 사람이 ML을 알지 못했을 지도 모른다. ML은 프로그래밍에 관한 연구의 산물로 현실적 요구와 상관없이 만들어졌으므로 학술적 성격이 강하고 실용적 성격이 약하다. 따라서 빠르게 보급되지 않는 편이 자연스러울 것이다. 그런데 프로그래밍 언어 분야에서 ML과 같은 함수형 언어가 주목을 받기 시작했다. 이에 따라 학술적 성격이 강한 활용, 즉 이론을 증명하는 프로그램 등에 쓰이는 것 외에 보다 실질적인 분야에 사용될 수 있도록 ML을 개량한 언어가 다수 등장했다. 실제로 회사에서 사용되는 사례도 발생하고 있다. 한 예로 읽을거리 part1 중 비디오에 나왔던 Jane Street사는 ML의 변형인 OCaml을 사용한다. 이 Jane Street사는 평범한 무역 회사이며 어떤 학술적 성격도 없는데 프로그래밍 언어로 OCaml을 사용한다. Jane Street사에서 원하는 Correctness, Agility, Performance, 이 세 가지 기술적 특성을 OCaml이 만족시키기 때문이다. 하지만 OCaml의 단점도 몇 가지 언급하는데, 라이브러리가 외부에 있고 사용자 인터페이스가 좋지 않으며 병렬 프로그래밍이나 큰 프로그램을 짜는 데 적합하지 않다고 한다. 이렇게 부족한 점이 있지만, 안전성과 효용성이 뛰어나기 때문에 함수형 언어를 실용적으로 사용하려는 노력은 멈추지 않을 것이다. 이상의 사실에서, ML과 같이 획기적인 논리에 기반을 둔 프로그래밍 언어는 시대의 흐름에 몸을 잘 실어서 보급되는 것이 아니라, 급속도로 확산되지 않아도 시대의 흐름을 서서히 끌어올 수 있는 잠재력이 있는 것으로 보인다.

이처럼 특성이 확연하게 갈리는 이 두 언어 중 어느 한 쪽이 더 우월하다고 확정짓고 다른 한쪽을 배제하는 것은 옳지 않을 뿐 아니라 불가능에 가깝다. 시대 상황의 즉각적인 요구를 따라가는 방법으로만 프로그래밍 언어를 만든다면 프로그래밍 언어의 깊이와 미학은 사라지고 얄팍한 언어들만 남을 것으로 예상된다. 또 프로그래밍 분야가 한 단계 도약하여 학문적인 발전을 이루어내는 일도 없을 것이다. 현재 프로그래밍을 하나의 학문 분야로 만든 semantic equivalence, sequentiality, interaction, mobility와 같은 논제들은 대부분 수학, 논리학적으로 연구되기 때문이다. 반대로 프로그래밍 언어를 설계할 때 무조건 환상적인 논리적 기반을 찾으려 해도 문제가 있다. 패러다임을 이끌만한 이론을 얻으려면 오랜 시간에 걸쳐 많은 연구가 있어야 하고 가치 있는 이론이 차곡차곡 쌓여야 한다. 지금 당장 필요한 것이 있는데 그런 연구 결과가 나오기를 손 놓고 기다리는 것은 우스운 일이며 현실적으로 가능하지 않다. 또 ML의 예에서 보듯이 철저하게 수학과 논리학에 기반을 두고 설계한 언어는 실용적인 기능이 떨어지게 마련이다. 이런 단점을 보완할 때 기존의 실용적 언어에서 아이디어를 차용할 수 있기 때문에 실용성을 목표로 만든 언어가 무조건 가치 없다고 말할 수 없다. Milner가 학생들에게 조언했듯이, 언어의 실용성과 논리성 중 어느 한 쪽만 취하는 것은 바람직하지 않다. 이 두 가지가 함께 있을 때 비로소 언어는 빛을 품기 시작한다.