동화는 실제 그 이상이야. 용이 존재한다고 얘기해서가 아니라, 용을 물리칠 수 있다고 말하거든.
닐 게이먼(Neil Gaiman), 『코랄린(Coraline)』1
여러분과 함께 여행을 하게 되어 정말 신난다. 이 책에서는 프로그래밍 언어의 인터프리터(interpreter)를 직접 구현한다. 또 구현할 가치가 있는 언어를 디자인하는 방법을 차근차근 설명한다. 내가 프로그래밍 언어에 처음 입문했을 때 이런 책이 있었으면 좋겠다고 생각했고, 실은 거의 10년 동안 머릿속으로 이 책을 써왔다.
친구들과 가족들이여, 그동안 내가 정신이 딴 데 팔려 있어서 미안!
지금부터 완전한 기능을 갖춘(full-featured) 언어를 2개의 완전한 인터프리터로 구현하는 과정을 하나씩 살펴보겠다. 여러분이 언어의 내면을 들여다보는 것은 처음이라 보고, 실행 가능하면서도 성능이 빠른, 완전한 언어 구현체(language implementation)를 만들기 위해 필요한 개념과 코드 줄을 단계별로 설명할 것이다.
책 한 권에 두 가지 구현체를 욱여넣고 처음부터 끝까지 죽 다루기 때문에 타 도서에 비해 이론적인 내용은 적은 편이다. 시스템을 한 조각씩 만들어가며 이면에 숨겨진 역사와 개념을 간간이 소개하겠다. 나중에 여러분이 PL(Programming Language) 연구원들과 함께 칵테일 파티에 참석할 때를 생각하여 그들 수준에 걸맞은 전문 용어(lingo)도 익숙하게끔 노력하겠다.
신기하게 나 역시 그런 상황에 노출된 적이 더러 있었다. 술을 어찌나 작정하고 들이키던지!
그러나 대부분은 언어를 돌아가게 만드는 데 모든 뇌즙을 짜낼 생각이다. 이론 따윈 중요하지 않다는 소리가 아니다. 구문(syntax, 신택스)과 시맨틱(semantics, 의미)을 정확하게, 형식에 맞게 추론하는 능력은 언어를 만지작거릴 때 꼭 필요한 기술이지만, 개인적으로는 직접 실행해보면서 배우는 게 최고라고 생각한다. 추상적 개념으로 가득한 단락의 파도를 넘고 넘어 내 것으로 만들기는 어렵지만, 직접 코드를 짜서 실행하고 디버깅을 해보면 비로소 내 산 지식이 된다.
특히, 정적 타입(static type) 시스템에서는 엄격한 형식 추론(rigorous formal reasoning)이 필요하다. 타입 시스템을 파보는 것은 수학 정리를 증명하는 느낌과 비슷하다.
우연히 그런 것이 아니다. 20세기 초, 하스켈 커리(Haskell Curry)와 윌리엄 앨빈 하워드(William Alvin Howard)는 이 둘2이 동전의 양면이라는 사실을 증명했다. '커리-하워드 동형(Curry-Howard isomorphism)'3
이것이 내 목표다. 나는 여러분이 이 책을 다 읽고 나서 실제 언어가 어떻게 살아 숨 쉬는지 확실히 깨닫고, 나중에 다른 더 이론적인 책을 읽더라도 이 책에서 실습을 통해 이해한 기반을 바탕으로 개념을 마음 속에 단단히 새겼으면 좋겠다.