해커 문화의 뿌리를 찾아서 Part 4: 액터와 람다 |
 |


안윤호 mindengine@freechal.com
필자는 아마추어 리눅스 커널 해커였으며 최근에 팹(Fab)이라는 책을 번역 출간했다. 컴퓨터의 여러 분야에 관심이 많고 컴퓨터와 문화의 인터페이스에도 관심이 많다.
2007년 7월 18일
|
|
 |
|
연재순서
1회(2007년 4월): 리스프가 탄생하기까지
2회(2007년 5월): 원시 리스프의 재구성
3회(2007년 6월): 해커리즘의 문화
4회(2007년 7월): 액터와 람다
지난번에는 람다에 대해 간단히 적었다. 람다 계산법이 이상하게 보인다 해도 너무 심각하게 생각하지 않아도 된다. 당장은 이해할 필요도 없다. 이해에는 많은 시간이 걸릴지도 모르며 이해하지 않아도 별 문제는 없을지도 모른다. 컴퓨터를 잘 몰라도 IT 개발 업무에 종사하는 사람이 상당수 있는 것처럼 람다를 잘 모른다고 큰 문제가 생기는 것도 아니다. 실제 코드를 짜는 일에 람다 계산법을 적용하는 일도 별로 없다. 리스프는 이미 람다를 충실하게 구현하고 있다.
필자의 임무는 리스프 여행 가이드이므로 너무 어렵지 않게 이야기를 적어 나가야 한다는 것을 안다. 읽다가 호기심이 생기는 부분이 있으면 찾아볼 자료들은 얼마든지 있을 것이다. 이번 이야기는 람다가 중요한 화두로 등장하는 역사적 사실의 배경이다. 그 시작은 서스만과 스틸의 스킴(Scheme)이 람다 페이퍼들과 함께 나왔고 람다 페이퍼가 나온 이유는 이들이 액터 모델(actor model)을 이해하고 싶어 했기 때문이다.
액터 모델은 칼 휴이트(Carl Hewitt)라는 총명한 학자가 제시한 모델이다. 사실 이번 이야기는 액터 모델보다도 휴이트가 주인공이다.
휴이트와 액터
어느날 칼 휴이트가 람다와는 관련이 없어 보이는 액터 모델이라는 이론을 들고 나왔다(Carl Hewitt, Peter Bishop, Richard Steiger(1973). 「A Universal Modular Actor Formalism for Artificial Intelligence」). 람다가 하나의 계산 형태인 것처럼 액터 역시 형식이 중요하다. 이 모델에서 세상의 모든 것은 액터라는 개념을 채택했다. 마치 객체지향 프로그래밍에서 모든 것이 객체이며 리스프에서는 모든 것이 리스트인 것과 같다.
액터는 객체보다 더 동시적인 모델이다. 액터는 물리적인 세상을 추상화하려는 시도에서 나왔다(반면 람다는 논리적인 모형으로부터 나왔다). 물리적인 시스템에서 중력이나 전기장은 다른 요소들과 직접적, 동시적으로 영향을 받는다. 액터는 이러한 동시적 작용을 위한 메시지를 보내는 모델을 만들고자 했다(액터와 비슷한 것들은 여러 번 등장했다. 우선 정보이론 자체가 맥스웰의 도깨비에 대한 새넌과 위너의 고민으로부터 나온 것을 생각해 보면 된다. 더 거슬러 올라가면 라이프니츠의 모나드(monad) 이론부터 시작한다). 액터는 컴퓨터상의 존재로 메시지를 받으면 다음과 같은 일을 동시적으로 만들어낼 수 있다.
* 다른 액터에 한정된 개수의 메시지를 보낼 수 있다.
* 유한한 개수의 액터를 만들어낼 수 있다.
* 다른 액터가 받을 메시지에 수반될 행동(behavior)을 지정할 수 있다.
* 이런 일들이 동시적으로 진행되는 데 있어 미리 정해진 순서는 없다.
통신은 비동기적이며 메시지를 보내는 액터는 메시지가 다 수신되기를 기다리지 않는다. 메시지 수신자는 주소로 확인되며 우편주소라고 부른다. 그래서 액터는 주소를 갖고 있는 액터들에 한해 통신할 수 있다. 주소는 수신하면서 알아낼 수도 있고 자신이 만든 액터의 주소일 수도 있다. 요약하면 액터 모델은 액터들 사이의 동시적 계산, 액터의 동적인 생성, 메시지에 액터의 주소를 포함시킬 수 있는 것, 그리고 도착순서의 제한을 받지 않은 비동기적 메시지 전달을 통한 상호작용이 특징이다.
내용을 읽다 보면 액터 모델과 비슷한 것이 우리가 사용하는 전자우편이라는 생각이 들지 않는가? 실제로 그렇다. 액터 모델의 내용을 읽고 있으면 리턴 값을 전달하는 이야기가 없으며 실제로 계산 값은 메시지를 전달하면서 전해질 수 있다. 그래서 액터 방식으로 계산하는 방법은 함수나 서브루틴을 호출하여 2와 3을 더하여 5를 리턴 받는 것이 아니다. 이를테면 다른 액터에 3이라는 값을 보내면서 여기에 2를 더할 것을 요구하는 메시지와 함께 전송하는 것이다. 이상하게 보이는가?
이상하게 생각할 것은 없다. 이메일로 지시를 보내 일을 처리하는 방식을 확장하면 된다. 메시지를 여러 번 보내고 받으면 복잡한 일도 처리할 수 있다(어떤 사람들은 웹 서비스의 SOAP 모델도 액터 모델로 잘 표현할 수 있다고 생각한다).
휴이트의 액터는 람다 계산, 스몰토크(Smalltalk), 시뮬라의 영향을 받았다. 이들은 동시에 휴이트의 영향을 받았다.
우선 람다 계산부터 살펴보자. 위키백과 영어판의 액터 모델(http://en.wikipedia.org/wiki/Actor_model)에서 람다 계산법을 이용한 메시지 전달은 다음과 같다.
λ(leftSubTree,rightSubTree)
λ(message)
if (message == "getLeft") then leftSubTree
else if (message == "getRight") then rightSubTree
|
얼핏 보면 단순한 치환(substitution)이다. 그러나 서스만과 스틸은 스킴을 만들면서 환경(environment)이라는 개념을 도입하면서 리스프를 다시 해석하게 되었다(액터를 이해하기 위해 서스만과 스틸이 만든 장난감 리스프 언어가 스킴이 되었다. 휴이트와 이야기를 나누던 서스만은 사소한 점 두 가지를 제외하고는 람다와 액터 모델이 거의 일치한다는 것을 알았다). 스틸은 이 내용을 「The History of Scheme」이라는 글에서 요약했다. 람다가 개별적으로 상태 변수를 갖고 서로 값을 주고받으면서 액터의 역할과 같은 일을 할 수 있다는 것을 알았다. 동시성 문제가 완전히 해결된 것은 아니지만 리스프 구조에 큰 변화가 왔고 그 와중에 지난번에 소개한 ‘the original lambda papers’라는 것들이 나왔다. 람다라는 것은 개념으로부터 하나의 완벽한 계산상의 실체가 되었다.
별다른 내용이 아닌 것 같지만 프로시저나 함수들, 액터, 객체 그리고 람다 객체들이 메시지를 주고받는 패턴으로 컴퓨터의 제어 구조를 결정한다는 간단하면서도 심오한 결론에 도달한다. 운영체제의 IPC가 얼마나 복잡해질 수 있는가를 이해할 수 있는 독자라면 같은 패턴이 언어에도 적용된다는 것을 알 수 있다. 객체가 사용하는 메시지 전달 같은 것은 그 다양한 종류의 하나일 뿐이다.
사실 조금만 파고들어도 복잡한 측면들이 나타난다. 일부 객체지향 언어에서 메시지는 객체를 통제하는 거의 유일한 수단이다. 만약 객체가 메시지에 반응한다면 그 객체는 메시지에 대한 메서드(method)를 갖고 있는 것이다. 객체지향 언어보다 먼저 나타난 구조적 프로그래밍에서 메시지를 보내는 방법은 함수 호출이다. 그 이전에는 포트란이나 베이직처럼 직접 goto(jump)하는 방법이 있었다. 프로그램이 제어를 전달하는 방법에서 jump는 나쁜 방법이 아니다. 많은 문헌에서 컨티뉴에이션(continuation)이라고 부르는 방법도 제어와 메시지를 전하는 방법이다. 스택을 쓰지 않아도 컨티뉴에이션으로 해결할 수 있고 파이썬이나 그 외 몇 가지 언어에서는 이미 시험대에 오른 문제이기도 하다. 차이가 있다면 일의 종류나 알고리즘에 따라 얼마만큼 우아하고 추상적으로 표현할 수 있느냐가 관건이다.
리스프에서 스킴을 만든 팀만 휴이트를 만난 것이 아니다. OOP 발전에 결정적 영향을 미친 알런 케이(Alan Kay)도 휴이트를 만났다. 먼저 알란 케이가 스몰토크를 만들면서 메시지 패싱의 사고방식에 영향을 받았다. 메시지 패싱은 최초의 객체지향 언어라고 하는 시뮬라에 처음 모습을 나타냈다. 휴이트의 경우 메시지 패싱은 패턴 지향적으로 플래너(Planner)를 불러내는 데 사용되었다. 플래너는 휴이트가 만든 인공지능 언어이며 여기서 메시지 패싱의 개념을 설명하고 있다. 이것이 스몰토그-71 개발에 영향을 주었다. 얼마 후 휴이트 역시 스몰토크-71에 의해 크게 자극 받았으나 구현 방법이 너무 복잡한 것이 문제였다.
1972년 케이는 스몰토크-72에 대한 아이디어와 세이모어 패퍼트(Seymour Papert)의 로고(Logo)에 나오는 ‘little person’의 개념을 토론하기 위해 MIT를 방문했다. 그러나 스몰토크-72의 메시지 패싱은 정말 복잡했다. 그래서 나중에는 메시지 패싱에 근거하는 동시 계산의 수학적 모델은 적어도 스몰토크-72보다는 간단해야 한다고도 했다. 스몰토크의 나중 버전들은 시뮬라의 모델을 따랐다. 휴이트의 메시지 패싱에 대한 방법론이 케이에게 영향을 준 것은 분명하지만 액터 모델도 케이의 영향을 받았다.
스몰토크가 GUI와 데스크톱 그래픽 환경에 결정적 영향을 준 것에 비해(PARC의 워크스테이션과 매킨토시 그리고 스퀵) 액터는 컴퓨터 이론과 공학에서 다루어졌다. 역사의 개괄은 간단하지만 둘은 서로 많은 영향을 주고받았다(우리가 알고 있는 객체의 개념이 세포의 영향을 받은 것이라든지, 북유럽에서 날아온 알골의 변형인 시뮬라의 영향 같은 것은 모두 튜링상을 받은 사람들의 가장 중요한 개념이었음에도 불구하고 별로 알려져 있지 않다. 신기하게도 세부적인 언어 구현의 요소들에 대해 고민하면서도 문제 자체를 문제로 고민할 기회는 상대적으로 적었다).
언어는 어느 정도까지 추상화나 세계의 모습을 제공해야 하는가? 그것은 잘 모른다. 하지만 언어에서 생물학적 모델, 물리학적 모델 같은 것을 다룰 때 메시지 패싱은 중요한 부분이다(물론 독자들은 메시지 패싱이 본질적이며 골치 아픈 내용이라는 것을 잘 알고 있을 것이다). 이 문제는 아무튼 30년이 넘게 중요한 화두로 작용했다.
휴이트가 던진 화두에 리스프 해커들은 람다를 골똘히 연구하는 것으로 문제를 해결했다. 람다 함수의 인스턴스는 제한이 없으며 서로 전부 다른 상태(state)를 만들 수 있기 때문에 수많은 객체가 있는 것과 마찬가지다. 여기서 람다들이 어떤 측면(aspect)을 바라보도록 설계하는지가 중요한 문제다.
SICP 3장은 이런 모델링의 중요한 모습을 드러낸다. 리스트를 기계의 부속을 연결하는 것처럼 사용하는 코드들이 나온다. 5장에 가면 재귀(recursion)와 컨티뉴에이션이 실제 언어 구현에서 어떻게 제어를 넘기는지 극명한 예들을 제시한다. 이런 것들을 학부 학생들에게 가르치겠다는 과감한 시도가 SICP에 사람들이 열광하는 이유다. 물론 싫어하는 이유이기도 하다.
책을 보며 필자가 느낀 기묘한 느낌은 오랫동안 머릿속에 남아있었다. 그런데 필자만 그런 것을 느낀 것은 아니었다. 필자는 예전에 김창준 님이 워드 커닝엄(Ward Cunningham)과 인터뷰한 글을 떠올렸다(워드 커닝엄과 켄트 벡은 패턴을 컴퓨터 프로그램에 적용하는 실험적 작업을 20년 전에 시도했다). 그 내용이 박스 기사에 소개되어 있다.
액터 모델은 오랫동안 많은 사람들에게 영감을 준 화두다. “핵심적 내용인 메시지 패싱에 대해 생각해 보면 좋을 것이다” 정도가 필자의 간단한 결론이 되겠다. 어떤 형식으로 요소들 간에 메시지를 주고받게 할 것이며 어떤 기구를 제공할 수 있는가 하는 문제는 답이 나지 않는 문제다. 그래서 계속 생각해 볼 화두로서 가치는 충분하다.
조금만 생각해 보는 것으로도 우리가 아는 언어에 대한 상식들에 대한 새로운 관점들을 얻을 것이다. 그리고 이 주제들은 SICP 5장에서 반복적으로 나온다.

그림은 휴이트의 「Viewing Control Structures as Patterns of Passing Messages」에 나오는 그림이다. 재귀를 이용하여 팩토리얼을 계산하는 문제를 메시지 패싱으로 본 그림이다. 생각하기에 따라 메일로 메시지를 보내는 것처럼 문제를 해결할 수도 있다. 수신자 숫자를 늘리거나 더 복잡한 동작을 시킬 수도 있다. 이 그림은 「History of Scheme」에서 다른 방법으로 설명한다.
휴이트의 다른 작업 플래너
공교롭게도 칼 휴이트, 제럴드 제이 서스만, Terry Winograd는 모두 세이모어 패퍼트의 제자였다. 플래너는 휴이트가 만든 언어의 이름이다. 지식(knowledge)을 정의하면서 지식을 논리 수학의 형식으로 정리해야 한다는 매카시 같은 사람들의 생각과, 고수준의 프로시저 플랜의 형태로 지식을 표현할 수 있다는 사람들의 의견이 있었다. 플래너는 두 방법을 혼합한 형태였다. 인공지능 언어는 리스프 뿐만 아니라 여러 가지가 있었고 플래너는 그 중 하나였다. 플래너는 너무 방대하기 때문에 피코플래너나 마이크로플래너 같은 부분적 구현들도 있었다.
* 리스프(매카시 외, 1958)
* 플래너(휴이트, 1969)
* 마이크로플래너(서스만 외, 1971)
* Conniver(서스만 외, 1972)
* 플라즈마(휴이트 외, 1973)
* Schemer(서스만과 스틸, 1975)
이들은 1970년대 초반 마이크로플래너를 홍보하기 위해 에딘버그를 방문한다. 서스만과 Terry Winograd는 에딘버그 대학을 방문하여 새로운 버전인 마이크로플래너의 소식을 전하고 증명 방법의 절차 논리를 논의했다. 에딘버그에는 피코플래너라는 마이크로플래너의 축소판과 완전한 플래너가 구현되어 있었다. 에딘버그의 논리학자 코왈스키와 헤이스는 마이크로플래너의 많은 부분이 전통적인 수학적 논리에 의해 수행될 수 있다는 것을 알았다. 그래서 코왈스키는 마이크로플래너의 일부를 사용하여 프롤로그(Prolog: programming in logic)의 아이디어를 떠올리고 마르세이유 대학에서 프롤로그가 구현되었다. 그래서 프롤로그가 나오는데 이것은 미국의 연구팀에게는 충격이었다.
유럽 연구자들은 리스프를 잘 몰랐으나 플래너의 개념은 알고 있었고 미국 학자들은 우아하게 자신의 연구를 포장하지 못했다. 플래너의 개념이 명제 논리학과 만나자 프롤로그가 나왔다. Colomeur와 다른 연구자들에 의해 새로운 언어와 형식이 나온 것이다. 프롤로그는 플래너보다 많이 간단했고 큰 장점으로 작용했다. 간단히 배워 논리 프로그래밍을 배울 수 있었다. 프롤로그는 유럽에서 많이 사용되었다.
결국 기본적 도구를 만들어 준 셈인데 프롤로그는 또 다른 하나의 강력한 주류로 나타난다. 플래너에서 지식에 대해 ‘절차적 지식의 구현’의 개념이 조금 명확해졌다면 다른 형식을 빌려 선언형 지식(declarative knowledge)의 모습을 떠올릴 수 있었다.
그 이후 리스프의 고급 교과서에는 프롤로그를 만드는 예제가 나온다, SICP와 지난번에 소개한 PAIP(Paradigms of Artificial Intelligence Programming)에도 프롤로그 인터프리터를 만드는 예제가 많은 지면을 할애하여 나온다. SICP의 논리 프로그래밍 장에는 몇 가지 간단한 법칙과 프레임으로 프롤로그 인터프리터를 만드는 방법을 설명한다. 그러면서 “훌륭하기는 했으나 이해하기는 어려웠던 휴이트의 박사 논문을 가지고 씨름하던 MIT의 연구자들에 의해 논리 프로그래밍을 연구 중이었으나” 하는 문장으로 시작하는 주석문이 있다. 지식을 표현하는 더 우아한 표현법이 있다는 것을 인정해야 했다.
지면상 더 쓸 수는 없지만 어떤 지식들은 ‘선언(declare)’될 수 있었던 것이다. 논리적으로 선언된 지식들은 법칙에 의해 프로그램을 자동으로 ‘생성’할 수 있다. 이상해 보이기는 하지만 사실이다. PAIP는 프롤로그에 너무 많은 지면을 할애한다고 비난까지 받았지만 정말 중요한 부분이었다.
스킴 칩과 리스프 머신
SICP 5장은 컴파일러, 그리고 조금 비약하면 스킴 칩까지 구현하는 내용이다. 이 칩의 가장 충격적인 특징은 소프트웨어가 자신이 실행될 하드웨어를 디자인하는 것이었다. 설계의 원형은 「Design of LISP-based Processors, or SCHEME: A Dielectric LISP, or Finite Memories Considered Harmful, or LAMBDA: The Ultimate Opcode」(Guy Lewis Steele, Gerald Jay Sussman, AI Lab memo, AIM-514)에 나온다. 이 글을 쓸 때는 1979년이었다. 당시로서는 획기적인 개념이었다. 설계의 많은 부분은 반도체 팀이 아닌 소프트웨어 디자이너들이 쓴 것이고 이 글은 유명한 카버 미드(Carver Mead)의 책이 나오기 전의 초고를 빌려 읽으면서 썼다. 책의 내용은 거의 30년이 되어가는 지금 보아도 흥미진진하다. 람다의 원형이 점차 간단해져 칩으로 변한다. 한편 출판된 미드의 책은 이 글을 중요한 사례로 인용했다.
SICP 5장은 개념적인 레지스터 머신(register machine)을 만들면서 설명하고 컴파일러를 만든다. 컴파일러는 점차 기계로 스킴을 옮긴다. 리스프 컴파일러의 서브셋과 기계의 요소는 크게 다르지 않다. 이런 일이 아주 쉬운 내용은 아니지만 아주 어려운 내용도 아니다. 그러나 정말 생각할 것이 많은 내용이다.
리스프는 함수를 람다 표기법으로 나타낸다. 람다 표기법은 특별히 수나 기호를 구분하지 않는다. 람다 표기법은 조금 생소한 것이라 설명이 필요하다. 람다 계산법은 치환을 다루는 계산법이다. 전반적인 내용이나 배경이 위키백과에 상당히 잘 정리되어 있다. 필자는 람다 계산법을 설명하기 위해 ‘An Introduction to Lambda Calculus and Scheme’에 나오는 예제를 그대로 몇 개 인용해 보았다.
5장의 주요 내용으로 나오는 컴파일러인 래빗(Rabbit)이라는 최초의 스킴 컴파일러가 가이 스틸의 석사 학위 논문이었다. 커먼 리스프와 스킴을 만드는 데 핵심적인 역할을 한 스틸은 졸업 후 다니엘 힐리스의 Thinking Machine에 합류한다. 수많은 프로세서, 적어도 몇 만개를 묶어놓은 프로세서들의 알고리즘은 사실상 스킴 칩 설계의 영향을 받았다. 스틸과 힐리스는 모두 서스만이 지도한 학생이었다.

스킴 칩의 내부회로
사실 스킵 칩의 원형은 몇 년을 더 거슬러 올라간다. 리스프 머신이라는 기계가 그 원형으로 톰 나이트(Tom Knight)와 그린블러트라는 해커가 만들어낸 시스템이다. 처음에 나온 나이트의 cons 마이크로프로세서는 cadr 머신으로 바뀌고 얼마 후 리스프 머신으로 진화한다.
이런 프로세서가 몇 만 개가 있고 각 칩이 모두 자신의 람다를 계산한다면 어떨까. 고도로 병렬적인 작업을 만들고 이들을 모두 스킴이나 리스프로 통제할 수 있을까? 스틸과 힐리스는 가능하다고 생각했고 몇 년 동안 자신들이 설계한 커넥션 머신으로 업적을 냈다. 휴이트의 아이디어로부터 출발하기는 했지만 람다는 강력한 개념이었고 람다를 매만지면서 얻은 부산물 또한 만만치 않았다. 상업적으로 대량 생산된 프로세서들은 아니지만 본질적으로 정말 강력했다.
서로 복잡하게 얽혀있는 컴퓨터 역사에는 결정적인 글들이 있고 필자의 이번 글에는 이것들이 느슨하게 연결된 형태로 등장한다. ‘The Art of the Interpreter’는 사실상 람다 페이퍼의 종합판이며 『VLSI 시스템 입문』은 서스만이 칩을 구현할 당시 소프트웨어로 하드웨어를 표현할 수 있는 유일한 수단을 제공했다.
박스 기사
다음에 인용한 글은 워드 커닝엄과 김창준의 인터뷰의 일부로 월간 마이크로소프트웨어에 실렸던 글이다. 오늘 소개한 내용과 연관이 있다.
창준: 당신의 경력에 가장 많은 영향을 준 책이나 논문 혹은 사람이 있다면요?
워드: 카버 미드(Carver Mead)와 린 콘웨이(Lynn Conway)의 『VLSI 설계(VLSI Design)』에서 아주 많은 영향을 받았습니다. 대학에서 전기 공학을 공부할 때는 하나의 집적 회로 위에 앤드(AND) 게이트 하나를 어떻게 만들 수 있는지 배웠습니다. 미드와 콘웨이의 책에서는 컴퓨터 프로세서 전체를 어떻게 만들 수 있는지 배웠지요. 카버 미드는 제 영웅입니다.
창준: 『VLSI 시스템 입문(Introduction to VLSI systems)』을 말하는 것이죠? 프로그래밍 책 중에서 가장 영향을 많이 받은 책을 고른다면요?
워드: 네. 사실 그 책은 시스템 설계자를 위해 쓰였지 전기 기술자를 위해 쓰인 것이 아니기 때문에 그 책을 컴퓨터 프로그래밍 서적으로 생각합니다. 아델 골드버그(Adele Goldberg)와 데이비드 롭슨(David Robson)의 『Smalltalk: The language and its implementation』 책의 초고에서 객체를 배웠습니다. 제가 스몰토크를 ‘딱’하고 깨친 것은 스몰토크를 리스프(Lisp)로 구현해 놓은 장을 읽었을 때였습니다. 애석하게도 이 장은 책이 출판될 때 빠져 버렸습니다 *. 그 장을 읽기 바로 전 주에 제럴드 서스만과 가이 스틸의 ‘인터프리터의 기술(Guy Lewis Steele, Jr. and Gerald Jay Sussman. “The Art of the Interpreter or, the Modularity Complex(Parts Zero, One, and Two)”. MIT AI Lab. AI Lab Memo AIM-453. May 1978.)’이라는 메모를 읽었는데, 그 장은 이 메모에 대한 훌륭한 보완이 됐습니다.
* 인터뷰에서 책에 빠져 있다고 말하는 부분은 http://users.ipa.net/~dwighth/smalltalk/bluebook/bluebookimptoc.html에서 볼 수 있다.
[지난 Special Issue 보기]
|