엔지니어링 철학: Roberto Ierusalimschy

핵심 요약
- 그는 여러분이 쓰는 엄청나게 많은 소프트웨어 속에 숨어 있는 스크립트 언어를 설계했습니다. Roberto Ierusalimschy는 Lua의 설계를 이끌었습니다. Lua는 1993년 PUC-Rio의 Tecgraf 연구실에서 Luiz Henrique de Figueiredo, Waldemar Celes와 함께 만들어졌습니다. World of Warcraft의 게임 로직을 돌리고, Roblox(그 방언인 Luau를 통해), Dota 2, Garry’s Mod에서 동작하며, Redis와 nginx(OpenResty를 통해)를 스크립트로 제어하고, Adobe Lightroom과 Wireshark를 구동하며, 그 아래에 운영체제조차 없는 로봇 같은 장치에까지 임베딩됩니다.127
- 규칙이 아니라 메커니즘. Lua를 규정하는 선택은 바로 거부입니다 – Lua는 클래스 시스템도, 객체 모델도, 패러다임도 제공하지 않습니다. 대신 강력하고 범용적인 몇 가지 메커니즘(테이블, 메타테이블, 코루틴)을 제공하고, 그 위에서 여러분이 직접 추상화를 쌓아 올리도록 합니다. “Lua는 프로그래머에게 어떤 객체 모델이나 클래스 모델도 강요하지 않는다”라고 설계자들은 썼습니다. 대신 그들은 “유연한 메커니즘을 제공”하여 애플리케이션에 맞는 모델을 무엇이든 직접 만들 수 있게 했습니다.3
- 작다는 것은 한계가 아니라 특징입니다. 참조 구현은 작고 깔끔합니다 – Lua 5.1 소스는 약 17,000줄의 C 코드이고, 배포본 전체가 플로피 디스크 한 장에 들어가며, 빌드된 인터프리터는 대략 143 KB입니다. 대부분의 스크립트 언어는 한 자릿수 더 큰 규모인데, Lua가 작은 상태를 유지하는 것은 바로 임베딩되도록 만들어졌기 때문입니다. 그리고 단순함이야말로 작고 빠른 구현을 가능하게 하는 요소입니다.3
- 이식성과 임베딩 가능성은 첫날부터 설계 목표였습니다. Lua는 “깔끔한 C” – C와 C++의 교집합 – 로 작성되었고, Linux와 Windows부터 휴대용 기기와 마이크로컨트롤러에 이르기까지 “대부분의 플랫폼에서 별도 작업 없이 곧바로 컴파일됩니다.” 잘 정의된 C API는 호스트 프로그램이 Lua를 완전히 제어하고 확장할 수 있게 해 주며, 바로 그 점이 게임 업계가 Lua를 사실상의 표준으로 채택한 이유입니다.34
원칙
“우리는 Lua를 객체 지향 언어로 만들고 싶지 않았다. Lua에 특정 프로그래밍 패러다임을 고정하고 싶지 않았기 때문이다… Lua는 프로그래머에게 어떤 객체 모델이나 클래스 모델도 강요하지 않는다. 대신… 우리는 프로그래머가 애플리케이션에 적합한 모델을 무엇이든 만들 수 있도록 유연한 메커니즘을 제공하기로 했다.” – Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes, The Evolution of Lua3
대부분의 언어 설계는 규칙의 축적입니다. 어떤 팀이 객체는 이렇게 동작해야 하고, 오류 처리는 저렇게 생겨야 하며, 동시성은 스레드든 비동기든 액터든 무언가를 의미한다고 결정합니다 – 그리고 그 결정을 언어에 구워 넣습니다. 그래서 그 언어로 작성된 모든 프로그램이 그 선택을 물려받습니다. 그 결정들은 대개 합리적입니다. 문제는 그것이 결정이라는 점, 한 번 내려진 결정이라는 점, 모두를 위해 내려진 결정이라는 점, 그리고 여러분의 애플리케이션을 알 수 없는 사람들이 내린 결정이라는 점입니다. Ierusalimschy의 본능은 정반대 방향으로 향했습니다. 여러분을 대신해 결정하는 대신, Lua는 범용적인 메커니즘 몇 가지를 손에 쥐여 주고 비켜섭니다. 그래서 여러분의 문제가 실제로 필요로 하는 규칙을 직접 만들 수 있습니다.3
가장 분명한 사례는 객체 지향입니다. 1990년대 초, 객체 지향 프로그래밍이 인기의 정점에 있을 때 사용자들은 Lua 팀에 클래스와 상속을 추가하라고 압박했습니다. 그들은 거부했습니다 – OOP가 틀렸기 때문이 아니라, 하나의 모델을 고정하는 것이 서로 천차만별인 애플리케이션에 임베딩되도록 만들어진 언어에 잘못된 일이었기 때문입니다. 그들은 객체와 클래스가 “필요하다면 테이블로 구현될 수 있다”고 추론했습니다. 테이블은 데이터와 메서드를 모두 담을 수 있고 함수는 일급 값이기 때문입니다.3 그래서 객체 시스템 대신 그들은 확장 가능한 의미론을 만들었습니다 – 테이블이 동작하는 방식에 개입할 수 있게 해 주는 메커니즘 – 그리고 사용자들이 상속, 기본값, 읽기 전용 뷰, 완전한 클래스 계층 구조를 스스로 조립하도록 했습니다. “확장 가능한 의미론은 Lua의 상징이 되었다”라고 그들은 썼으며, “오늘날까지도 우리의 생각은 바뀌지 않았다”라고 덧붙였습니다.3
그 거부가 감당할 수 있는 일이 되는 것은, 그것과 함께 따라오는 세 가지 다른 약속 덕분입니다. 단순함 – 언어는 메커니즘이 이해 가능하고 구현이 올바를 만큼 충분히 작은 상태를 유지합니다. 특징으로서의 작음 – 참조 구현 전체가 약 17,000줄의 깔끔한 C 코드여서, 애플리케이션에 Lua를 추가해도 “덩치가 커지지 않을” 만큼 작습니다.3 그리고 이식성 – C와 C++의 교집합으로 작성한다는 것은 동일한 소스가 슈퍼컴퓨터부터 센서까지 어디서나 컴파일된다는 뜻입니다.3 미리 정해진 버튼이 가득한 캐비닛 대신 날카롭고 범용적인 지렛대 몇 개를 사람들에게 건네고, 전체를 어디든 들고 다닐 수 있을 만큼 작게 유지하라. 그것이 원칙이며, Lua의 다른 모든 것은 그 원칙의 결과입니다.
배경
Roberto Ierusalimschy는 1960년 5월 21일 리우데자네이루에서 태어났으며, 그의 경력 전체는 한 기관 – 리우데자네이루 교황청 가톨릭 대학교(PUC-Rio) – 가까이에 머물렀습니다. 그는 1990년 이곳에서 컴퓨터 과학 박사 학위를 받았고 지금은 정보학 정교수로 재직 중입니다. 워털루 대학교에서 박사후 연구를 했고 스탠퍼드에서 방문 교수로 잠시 머물기도 했지만, PUC-Rio가 그의 본거지이며, Lua 이야기는 그곳의 한 특정 연구실과 떼어 놓을 수 없습니다.5
그 연구실이 바로 Tecgraf, 즉 컴퓨터 그래픽스 기술 그룹입니다. 1987년에 설립되어 산업 고객을 위한 소프트웨어 도구를 만들었는데, 그중 가장 큰 고객 하나는 당시에도 지금도 브라질 석유 회사 Petrobras였습니다.3 Lua의 기원은 부분적으로 브라질 무역 정책에 관한 이야기입니다. 1977년부터 1992년까지 브라질은 컴퓨터 하드웨어와 소프트웨어에 강력한 무역 장벽 – “시장 유보(market reserve)” – 정책을 유지했습니다. 자국이 스스로 만들 수 있고 또 만들어야 한다는 민족주의적 신념에서 비롯된 것이었습니다. 그런 분위기에서 Tecgraf의 고객들은 “정치적으로나 재정적으로나 해외에서 맞춤 소프트웨어를 구매할 여력이 없었습니다.” 외국 도구를 사는 것은 “자신들의 필요가 브라질 기업으로는 충족될 수 없음을 증명하는 복잡한 관료적 절차”를 의미했습니다. 이런 제약은 브라질이 다른 연구 중심지와 지리적으로 고립되어 있던 점과 맞물려 “Tecgraf가 필요로 하는 기본 도구를 처음부터 직접 구현하도록 이끌었습니다.”3 Lua는 설계자들 자신의 표현을 빌리자면 “개발도상국에서 만들어져 전 세계적 의의를 달성한 유일한 언어”입니다.3
Lua 이전에는 두 개의 작은 언어가 있었는데, 둘 다 Petrobras를 위해 만들어졌습니다. DEL – “데이터 입력 언어(data-entry language)” – 은 그래픽 프런트엔드를 생성하여, 엔지니어들이 숫자 열을 편집하는 대신 다이어그램을 클릭해 시뮬레이터 입력값을 넣을 수 있게 했습니다.3 SOL – “단순 객체 언어(Simple Object Language)” – 은 리포트 생성기를 위한 설정 언어로, BibTeX의 영향을 받은 타입 선언 문법을 갖추고 있었습니다.3 1993년 초가 되자 둘 다 원래의 범위를 넘어섰습니다. DEL 사용자들은 진짜 제어 흐름을 원했고, SOL은 절차적 능력이 필요했습니다. 1993년 중반 Ierusalimschy, de Figueiredo, Celes는 두 언어를 더 강력한 단일 언어로 대체할 수 있다고 결론지었고 – 그렇게 Lua 팀이 탄생했습니다.3 이름은 그대로 굳어진 작은 농담입니다. SOL은 포르투갈어로 “태양”을 뜻하는데, Tecgraf의 친구인 Carlos Henrique Levy가 그 후속작을 ‘Lua’ – 포르투갈어로 “달” 이라 부르자고 제안했습니다.3 1993년 7월까지 Waldemar Celes가 첫 구현을 완성했는데, 이는 Ierusalimschy의 지도하에 진행된 수업 과제로 만들어졌으며 “가능한 한 가장 단순한 것”이라는 익스트림 프로그래밍 원칙을 따랐습니다.3
작업
테이블과 메타테이블: 하나의 자료 구조, 하나의 메커니즘
테이블부터 시작합시다. 그것이 언어 전체의 축소판이기 때문입니다. Lua는 단 하나의 자료 구조화 메커니즘을 제공합니다 – 연관 배열을 가리키는 그들의 용어인 테이블 – 그리고 그 하나의 구조가 레코드, 배열, 집합, 리스트, 모듈, 객체의 역할을 모두 해냅니다.3 “대부분의 스크립트 언어가 연관 배열을 제공하지만,” 설계자들은 말합니다, “어떤 다른 언어에서도 연관 배열이 이만큼 중심적인 역할을 하지는 않는다.”3 레코드는 필드 이름을 키로 하는 테이블이고, 배열은 정수를 키로 하는 테이블이며, 객체는 데이터와 메서드를 함께 담는 테이블일 뿐입니다. 하나의 메커니즘, 여러 용도 – 이것이 바로 “규칙이 아니라 메커니즘”이라는 도박을 데이터에 적용한 것입니다.
테이블을 프로그래밍 가능하게 만드는 지렛대가 메타테이블입니다. 보통 테이블에 없는 키를 조회하면 nil이 반환됩니다. 그런데 테이블에 메타테이블 – 첫 번째 테이블이 특수한 상황에서 어떻게 동작해야 하는지를 기술하는 두 번째 테이블 – 을 부여할 수 있습니다. 가장 중요한 항목은 __index입니다. 조회가 빗나가면 Lua는 메타테이블의 __index를 참조하는데, 이는 다음으로 탐색할 또 다른 테이블을 가리킬 수 있습니다. 이것들을 연결하면, 테이블과 단 하나의 리디렉션만으로 만들어진 상속을 얻게 됩니다. 같은 메커니즘이 서로 다른 메타메서드 아래에서 연산자 오버로딩, 기본값, 읽기 전용 프록시, 지연 필드를 제공합니다. 그 어느 것도 통상적인 의미의 언어 기능이 아닙니다 – 전부 하나의 메커니즘이 서로 다른 형태로 쓰인 것입니다.3
이 메커니즘은 처음부터 완성된 형태로 도착하지 않았습니다 – 그 진화 과정 자체가 절제에 관한 교훈입니다. 그것은 Lua 2.1(1995)에서 “폴백(fallbacks)”으로 시작했습니다. 어떤 연산이 “잘못된” 종류의 값에 적용되었을 때 Lua가 호출하는 훅으로, 프로그래머가 다음에 무슨 일이 일어날지 결정할 수 있게 했습니다.3 테이블 인덱싱 폴백은 유저데이터와 다른 값들이 “테이블처럼 동작”하게 하여 “(위임을 통한) 여러 형태의 상속”을 지원했습니다.3 폴백은 전역적이었습니다 – 이벤트당 하나의 훅 – 그래서 라이브러리 간에 공유하기가 까다로웠습니다. 그래서 Lua 3.0(1997)은 이를 타입별 “태그 메서드(tag methods)”로 대체했고, Lua 5.0(2003)은 모든 것을 메타테이블과 메타메서드로 통합했는데, 이것이 오늘날 Lua가 사용하는 형태입니다. (“메타테이블”이라는 용어는 2001년 Rici Lake가 제안했습니다.)3 각 단계는 새 기능을 쌓아 올리는 대신 메커니즘을 일반화했습니다 – 언어가 클래스 시스템 제공을 계속 거부하게 만든 것과 동일한 본능입니다.
임베딩 가능성, C API, 그리고 게임이 Lua를 채택한 이유
Lua는 사실 독립형 언어가 되도록 의도되지 않았습니다. 설계자들은 그것을 “확장 가능한 확장 언어(extensible extension language)”라고 부릅니다 – 설정과 스크립팅을 통해 호스트 애플리케이션을 확장하므로 확장(extension) 언어이고, 거꾸로 C 함수로 확장될 수 있으므로 확장 가능(extensible)합니다.3 그 경첩은 잘 정의된 C API로, “Lua 코드와 외부 코드 사이의 완전한 통신을 허용”하며, Lua와 호스트 사이에서 값을 주고받는 깔끔한 스택 비유를 중심으로 만들어졌습니다. 그 API는 Lua가 C와 C++뿐 아니라 그것들을 통해 Fortran, Java, C#, 그리고 전혀 다른 언어들과도 인터페이스할 수 있게 해 줍니다.3
그 결실은 게임에서 나타났고, 그 이야기는 구체적입니다. 1997년 1월, LucasArts의 어드벤처 게임 Grim Fandango의 리드 프로그래머 Bret Mogilefsky는 자체 제작한 스크립트 언어를 Lua로 교체했으며 “게임의 엄청난 부분이 Lua로 작성되었다”고 Lua 팀에 알렸습니다.3 Mogilefsky는 게임 개발자 컨퍼런스의 라운드테이블에서 이를 이야기했고, 거기서부터 “Lua는 게임 개발자들 사이에 입소문으로 퍼져 게임 업계에서 확실히 시장성 있는 기술이 되었습니다.”3 그 적합성은 구조적입니다. 게임 엔진은 임베딩된 스크립팅 계층의 이점을 누리는 바로 그런 종류의 호스트입니다 – 무거운 작업(렌더링, 물리)은 빠른 C++에 남고, 게임 로직, 퀘스트, 행동은 디자이너가 엔진을 다시 컴파일하지 않고도 편집하고 다시 불러올 수 있는 작은 Lua 스크립트에 담깁니다. 작고, 빠르고, 이식 가능하고, 임베딩 가능한 것이 바로 게임이 필요로 하는 프로필이었고, Lua는 첫 릴리스부터 그것을 위해 만들어졌습니다.34
코루틴, 그리고 작고 빠른 구현
세 번째 위대한 메커니즘은 코루틴입니다 – 그리고 OOP와 마찬가지로, 이는 팀이 의도적으로 규칙을 거부한 결과입니다. 1990년대 후반 내내 사용자들은 멀티스레딩을 요구했고, 당연한 선택은 표준적인 선점형, 공유 메모리 스레딩 모델을 채택하는 것이었습니다. Lua 팀은 두 가지 근거로 거절했습니다. C에서 선점형 스레드를 구현하려면 “ANSI C의 일부가 아닌” 원시 기능이 필요한데 이는 Lua의 이식성을 깨뜨렸을 것이고 – 더 근본적으로는 – “우리는 표준 멀티스레딩 모델을 믿지 않았다(지금도 믿지 않는다)”, 즉 “‘a=a+1’이 결정론적이지 않은 언어에서는 누구도 올바른 프로그램을 작성할 수 없다”는 것입니다.3 그래서 스레드 대신 그들은 Lua 5.0(2003)에서 코루틴을 내놓았습니다. 함수가 스스로를 일시 중단했다가 나중에 정확히 멈췄던 자리에서 재개할 수 있는, 협력적이고 비선점적인 멀티태스킹을 위한 메커니즘입니다.3 코루틴은 동시성의 표현력 – 제너레이터, 협력적 스케줄러, 상태 기계 – 을 제공하면서도 공유 메모리 스레드를 그토록 올바르게 다루기 어렵게 만드는 비결정성은 없습니다. 다시 한번, 규칙이 아니라 메커니즘입니다.
그 모든 것 아래에는 바로 작기 때문에 빠른 구현이 자리합니다. Lua의 가상 머신은 Lua 4.0까지 스택 기반이었습니다. Lua 5.0에서 레지스터 기반이 되었는데, 이는 코드 생성기에 최적화 여지를 더 주었고 전형적인 프로그램이 실행하는 VM 명령어의 수를 줄였습니다. 설계자들은 “Lua 5.0의 가상 머신은 널리 사용된 최초의 레지스터 기반 가상 머신”이라고 언급합니다.3 메모리는 점진적 가비지 컬렉터(Lua 5.1에서 도입)가 관리하는데, 길게 멈춰 세우는 stop-the-world 일시 정지 대신 작은 단계로 나누어 작업을 수행합니다 – 게임의 실시간 루프에 중요한 점입니다.3 독립적인 벤치마크들은 Lua를 인터프리터형 스크립트 언어 중 가장 빠른 축에 둡니다. 설계자들의 설명에 따르면 “Adobe Lightroom의 40% 이상이 Lua로 작성되어” 있을 만큼, 약 10만 줄에 이를 만큼 빠릅니다.3

Lua의 도달 범위: World of Warcraft에서 운영체제 없는 로봇까지
이를 모두 합하면 Lua는 엄청나게 넓은 소프트웨어 영역의 보이지 않는 스크립팅 계층이 되었습니다. 게임에서 World of Warcraft는 인터페이스 전체를 Lua에 노출하여 플레이어가 애드온을 작성할 수 있게 했고, Roblox는 수백만 명의 어린 창작자가 코딩을 배우는 언어로 Lua 방언 Luau를 만들었으며, Dota 2, Crysis, Garry’s Mod도 Lua를 임베딩합니다.1 게임 밖에서는 Redis가 데이터베이스 내부에서 Lua 스크립트를 원자적으로 실행하고, nginx는 OpenResty 배포본을 통해 웹 서버 자체를 프로그래밍하는 데 Lua를 사용하며, Adobe Lightroom과 Wireshark가 상당 부분 Lua 위에 세워져 있고, Neovim은 Lua를 일급 설정 및 플러그인 언어로 채택했습니다.1 그리고 인터프리터가 작고 이식 가능하기에, Lua는 다른 것이 거의 들어 있지 않은 하드웨어에까지 손을 뻗습니다 – 설계자들은 RoboCup 우승 로봇 Crazy Ivan의 이야기를 전합니다. 그 “두뇌”는 “운영체제 없이 Motorola Coldfire 5206e 프로세서 위에서 직접 Lua를 돌렸습니다. 다시 말해, Lua가 곧 운영체제였습니다.”7 무역 제한 속 리우의 한 연구실에서 만들어진 작은 언어 하나가 결국 어디에나 존재하게 되었습니다 – 거의 아무것도 요구하지 않으면서 나머지를 만들 지렛대를 여러분에게 건넸기 때문입니다.
방법론
DEL, SOL, 메타테이블, 코루틴, 그리고 언어를 비대하게 만들기를 거부해 온 30년을 가로질러 읽어 보면, 동일한 움직임이 반복됩니다. Ierusalimschy의 방법론은 구호라기보다 일관된 약속들의 집합에 가깝습니다.
규칙이 아니라 메커니즘을 내놓아라. 그를 규정하는 습관은 범용적인 지렛대를 제공하고 그것이 어떻게 쓰여야 하는지를 결정하기를 거부하는 것입니다. 내장 클래스 시스템도, 고정된 동시성 모델도 없이 – 그저 테이블, 메타테이블, 코루틴이 있고, 그것들로부터 애플리케이션이 필요로 하는 무엇이든 만듭니다. 그 일반적인 교훈은 언어 설계를 훨씬 넘어 전이됩니다. 가장 오래가는 도구는 해결책의 형태를 강요하지 않으면서 능력을 부여하는 도구입니다. 이는 Guido van Rossum의 “단 하나의 명백한 방법”과 정반대이며, 그 대비가 바로 핵심입니다 – 둘 다 일관성이 있고, 여러분의 도구가 어떤 철학을 구현해야 하는지를 아는 것이 실제 결정입니다.3
올바르고, 어디든 들고 다닐 수 있을 만큼 작게 유지하라. Lua의 참조 구현은 약 17,000줄의 깔끔한 C 코드로, 다른 스크립트 언어보다 한 자릿수 더 작으며, 그 작음은 의도된 특징입니다 – 그것이 언어를 임베딩 가능하고, 이식 가능하고, 신뢰할 수 있게 만듭니다. 그 규율은 한 가지를 더 제거하면 무너질 때까지 계속 쳐내는 것이며, 이는 Lua를 Sophie Wilson이 ARM에서 보여 준 가차 없는 미니멀리즘의 소프트웨어 거울로 만듭니다 – 핵심 골조까지 벗겨내면 효율은 덤으로 따라옵니다. 이는 언어 런타임 수준에서의 최소한의 가치 있는 제품입니다.3
요청받은 기능 아래에 깔린 메커니즘을 찾을 때까지 그 기능에 저항하라. 사용자들이 객체를 요구했을 때 Lua는 확장 가능한 의미론을 주었고, 스레드를 요구했을 때 코루틴을 주었습니다. 매번 팀은 특정 규칙을 거절하고, 사용자가 규칙을 스스로 만들 수 있게 하는 더 범용적인 메커니즘을 내놓았습니다 – 그리고 결정적으로, 여러 해가 지나도 마음을 바꾸지 않았습니다.3 이는 기능 요청에 적용된 증거 관문입니다. 요청받았다고 해서 그것을 추가하지 마라. 그것이 어떤 문제를 해결하는지, 그리고 이미 가진 메커니즘이 그 문제를 해결할 수 있는지 알아내라.
축적하지 말고 일반화하라. 메타테이블은 처음부터 완성된 채 도착하지 않았습니다 – 폴백에서 태그 메서드로, 다시 메타메서드로 자라났으며, 각 단계는 새 기능을 옆에 덧붙이는 대신 이전 메커니즘을 더 범용적인 것으로 대체했습니다.3 그 교훈은 덧셈이 아니라 통합으로 진화하라는 것입니다. 그래서 언어는 같은 크기를 유지하면서 더 강력해집니다 – Thompson과 Ritchie가 작고 조합 가능한 부품으로 Unix를 만들면서 사용한 것과 동일한 수단의 경제성입니다.
제약이 도구를 설계하게 하라. Lua가 존재하는 것은 브라질의 무역 장벽이 Tecgraf로 하여금 자체 소프트웨어를 만들도록 강요했기 때문이고, 그 이식성이 존재하는 것은 연구실의 고객들이 “매우 다양한 컴퓨터 플랫폼”을 운영했기 때문입니다.3 Ierusalimschy는 그 제약들을 핸디캡으로 취급하는 대신, 자원이 풍부한 팀이 만들었을 법한 것보다 더 작고, 더 깔끔하고, 더 이식성 있는 무언가로 설계를 이끌도록 했습니다 – 진지하게 받아들인 결핍은 변명거리가 아니라 설계 도구라는 교훈입니다.3
영향의 사슬
그를 빚은 이들
Scheme과 Lisp 전통. 설계자들은 “Scheme이 Lua에 미친 영향이 점진적으로 커졌다”고 명시하며, 그것이 “특히 익명 함수와 완전한 어휘적 스코핑의 도입과 함께 영감의 원천”이 되었다고 합니다.3 Scheme과 마찬가지로 Lua는 동적 타입을 갖고, 함수를 평범한 일급 값으로 다루며, 핵심을 작게 유지합니다 – 언어가 크기가 아니라 최소함으로써 강력할 수 있다는 신념입니다. (형성적 영향)
두 개의 작은 언어, DEL과 SOL. Lua는 이론에서 솟아난 것이 아니라, Petrobras를 위해 만든 두 개의 도메인 특화 언어에서 자라났습니다. SOL은 데이터를 기술하는 테이블 생성자 문법을 제공했고, 두 언어의 경험은 팀에게 “복잡한 애플리케이션의 상당 부분이 임베딩 가능한 스크립트 언어로 작성될 수 있다”는 것을 가르쳤습니다 – 그들의 표현으로 Lua의 탄생이 기댄 깨달음입니다.3 (직접적 영향)
브라질의 시장 유보. 1977년부터 1992년까지 이어진 무역 장벽은 뜻밖이지만 진짜 영향입니다. 그것이 Tecgraf가 애초에 자체 도구를 만든 이유이고, 고객 플랫폼의 다양성이 이식성을 일차적 설계 목표로 만든 이유입니다. 정책이 언어를 만들었습니다. (형성적 영향)
그가 빚은 이들
게임 업계의 스크립팅 계층. Grim Fandango 이후로 Lua는 게임 로직을 임베딩하는 사실상의 기본값이 되었고, 그것이 대중화한 패턴 – C++의 빠른 엔진, 임베딩된 스크립트의 편집 가능한 행동 – 은 이제 표준 관행입니다. Roblox의 Luau는 한 세대의 아이들에게 Lua 방언으로 프로그래밍을 가르쳤습니다. (분야를 규정한 영향)
임베디드 및 시스템 소프트웨어. Redis, nginx/OpenResty, Wireshark, Neovim, 그리고 수많은 장치가 Lua를 스크립팅 계층으로 채택했는데, 바로 그것이 그토록 적게 요구하기 때문입니다. 데이터베이스에서 네트워크 분석기를 거쳐 베어메탈 위에서 돌아가는 로봇에까지 손을 뻗는 언어는 거의 없습니다.
작음을 소중히 여기는 언어 설계자들. Lua는 작고 패러다임에 얽매이지 않는 핵심이 임베딩이라는 틈새에서 크고 고집스러운 언어를 능가할 수 있다는 살아 있는 증거로 서 있습니다 – 그 이후 모든 최소 런타임과 “프레임워크보다 메커니즘” 설계에 메아리치는 논증입니다.
관통하는 줄기
Ierusalimschy는 도구가 여러분을 대신해 얼마나 결정해야 하는가에 관한 이 시리즈의 긴 논쟁에서 한쪽 극에 자리합니다. Guido van Rossum은 “단 하나의 명백한 방법이 있어야 한다”를 바탕으로 Python을 만들고 배터리를 포함해 출시했습니다 – 언어가 의견을 가지고 있고, 그것을 따르는 것이 가장 저항이 적은 길입니다. Bjarne Stroustrup은 거의 모든 패러다임을 표현할 만큼 풍부한 C++를 만들었고, 그 풍부함의 대가를 크기와 복잡성으로 치렀습니다. Ierusalimschy는 둘 모두와 정반대로 갔습니다. 규칙도 거의 없고, 기능도 거의 없이, 그저 몇 가지 범용 메커니즘과 17,000줄짜리 런타임을 내놓고 나머지는 사용자가 만들게 했습니다. 그는 Sophie Wilson의 소프트웨어 거울입니다. 그녀의 ARM은 25,000개 미만의 트랜지스터로 벗겨내어 승리했습니다 – Lua는 C로 구현된 동일한 가차 없는 작음이며, ARM의 우연한 저전력처럼 그 작음은 아무도 설계 의도로 삼지 않은 영역(임베딩)을 정복하게 해 준 바로 그 요소로 드러났습니다. van Rossum이 여기 명백한 방법이 있다고 말하고 Stroustrup이 여기 모든 방법이 있다고 말하는 곳에서, Ierusalimschy는 말합니다. 여기 지렛대가 있다 – 무엇을 만들지는 여러분이 정하고, 나는 전체를 어디든 들고 다닐 수 있을 만큼 작게 유지하겠다. (시리즈 가교)
내가 여기서 얻는 것
내가 Ierusalimschy에게서 간직하는 교훈은 누군가에게 건넬 수 있는 가장 강력한 것은 규칙이 아니라 메커니즘이라는 점입니다. 도구를 만들 때, 그것이 어떻게 쓰여야 하는지에 대한 내 의견을 구워 넣고 싶은 유혹이 듭니다 – 클래스 시스템을, 프레임워크를, 축복받은 하나의 워크플로를 내놓고 싶어집니다. Lua의 경력 전체는 그 반대가 더 잘 늙는다는 논증입니다. 객체 모델을 고정하기를 거부하고 대신 메타테이블을 내놓음으로써, 언어는 설계자들이 결코 상상하지 못한 상속 방식을, 그들이 결코 예상하지 못한 게임과 데이터베이스와 에디터에서 사용자들이 만들 수 있게 했습니다. 이제 무언가를 만들 때 내가 Lua에서 빌려 오는 질문은, 내가 결정을 내놓고 있는가 아니면 능력을 내놓고 있는가입니다 – 결정은 오늘 내가 볼 수 있는 경우들을 위해 봉사하지만, 능력은 내가 볼 수 없는 경우들을 위해 봉사하기 때문입니다.
두 번째 교훈은 작음이란 참고 견디는 제약이 아니라 지켜내는 특징이라는 것입니다. 30년에 걸친 사용자 압박 속에서, Lua가 class 키워드와 스레드 라이브러리와 모든 것을 위한 표준 프레임워크를 갖춘 거대한 언어로 자라나게 두는 것은 쉬웠을 것입니다. 팀은 거부했고, 그 거부 덕분에 Lua는 플로피 한 장에 들어가고, 어디서나 컴파일되고, 로봇의 베어메탈 두뇌에까지 임베딩됩니다. 작은 상태를 유지하는 규율 – 축적하는 대신 일반화하고, 아래에 깔린 메커니즘을 찾을 때까지 그 기능을 거절하는 규율 – 은 더하는 규율보다 어렵고, 훨씬 더 가치 있습니다. 이는 절제로 읽은 품질은 유일한 변수입니다. 수십 년간 지켜낸 올바른 작은 것은, 다른 모든 것이 그 위에 설 수 있는 인프라가 됩니다.
자주 묻는 질문
Roberto Ierusalimschy는 누구이며 무엇을 만들었나요?
Roberto Ierusalimschy는 브라질의 컴퓨터 과학자로, 1960년 리우데자네이루에서 태어났으며 PUC-Rio의 정보학 정교수입니다. 그는 1993년 PUC-Rio의 Tecgraf 연구실에서 Luiz Henrique de Figueiredo, Waldemar Celes와 함께 만든 작고 빠르며 임베딩 가능한 스크립트 언어 Lua의 수석 설계자입니다. 또한 그는 책 Programming in Lua의 저자이자 패턴 매칭 라이브러리 LPeg의 창작자이며, 언어의 주된 역사서인 “The Evolution of Lua”를 공동 집필했습니다.356
Lua에서 “규칙이 아니라 메커니즘”은 무엇을 뜻하나요?
그것은 Lua가 고정된 결정을 강요하는 대신 강력하고 범용적인 메커니즘 몇 가지를 제공한다는 뜻입니다. 가장 분명한 예는 객체 지향입니다. Lua에는 내장 클래스 시스템이 없습니다. 대신 테이블(데이터와 메서드를 모두 담을 수 있는)과 메타테이블(테이블의 동작 방식을 커스터마이즈할 수 있게 해 주는)을 제공하고, 상속이든 클래스든 다른 어떤 객체 모델이든 여러분이 직접 만듭니다. 설계자들은 “Lua는 프로그래머에게 어떤 객체 모델이나 클래스 모델도 강요하지 않는다”라고 썼으며 대신 “유연한 메커니즘을 제공”하기로 선택했습니다 – 1993년 이래 지켜 온 입장입니다.3
Lua는 왜 게임과 임베디드 시스템에서 그토록 널리 쓰이나요?
처음부터 작고, 빠르고, 이식 가능하며, 임베딩하기 쉽도록 설계되었기 때문입니다. 참조 구현은 거의 어디서나 컴파일되는 약 17,000줄의 깔끔한 ANSI C이고, 빌드된 인터프리터는 대략 143 KB이며, 잘 정의된 C API가 호스트 프로그램으로 하여금 그것을 완전히 제어하게 해 줍니다. 그 프로필이 바로 게임 엔진이나 임베디드 장치가 필요로 하는 것입니다 – 무거운 작업은 C/C++에, 편집 가능한 로직은 작은 스크립트에 – 그래서 Lua가 World of Warcraft, Roblox(Luau를 통해), Redis, nginx/OpenResty, Adobe Lightroom, 그리고 베어메탈 로봇에 이르는 장치들을 스크립트로 제어하는 것입니다.137
“Lua”라는 이름은 어디서 왔나요?
Lua는 포르투갈어로 “달”을 뜻합니다. 이는 SOL – “단순 객체 언어(Simple Object Language)”이자 포르투갈어로 “태양” – 이라는 이전 Tecgraf 언어의 후속작으로 명명되었습니다. Tecgraf의 동료 Carlos Henrique Levy가 새 언어에 “Lua”라는 이름을 제안하여 태양에서 달로 이어지는 흐름을 완성했습니다. 프로젝트 전체는 브라질 석유 회사 Petrobras를 위해 만든 두 개의 작은 언어 DEL과 SOL에서 자라났습니다.3
출처
-
“Lua (programming language),” Wikipedia. Lua는 1993년 브라질 리우데자네이루 교황청 가톨릭 대학교(PUC-Rio)의 컴퓨터 그래픽스 기술 그룹(Tecgraf)에서 Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes가 만들었으며, ANSI C로 구현되었고 MIT 라이선스이며, Lua 5.0부터 레지스터 기반 가상 머신, 가비지 컬렉션, 코루틴, 일급 함수를 갖추고 있다. 최근 참조 구현도 여전히 작다(이 문서는 Lua 5.5.0이 약 32,000줄의 C로 이루어져 있다고 언급한다). 문서화된 사용처로는 게임 World of Warcraft, Roblox(Lua 파생 언어 Luau를 개발), Dota 2, Crysis, Garry’s Mod와, 게임이 아닌 소프트웨어로 Redis, nginx(OpenResty를 통해), Adobe Lightroom, Wireshark, Neovim이 포함된다. ↩↩↩↩
-
“Roberto Ierusalimschy: Known for Lua Programming Language,” machaddr (전기적 프로필). Ierusalimschy가 PUC-Rio에서 Luiz Henrique de Figueiredo, Waldemar Celes와 함께 개발하여 1993년에 처음 공개한 Lua의 창작자이자 수석 설계자로서의 역할을 요약한다. World of Warcraft와 Adobe Lightroom을 비롯한 소프트웨어에서의 Lua의 전 세계적 사용, Programming in Lua 저술, LPeg 라이브러리 창작을 언급한다. ↩
-
Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes, “The Evolution of Lua,” Proceedings of the Third ACM SIGPLAN Conference on the History of Programming Languages (HOPL III), 2007. 일차 출처. “Lua는 1993년 PUC-Rio에서 탄생한 스크립트 언어다.” “처음부터 Lua는 단순하고, 작고, 이식 가능하고, 빠르며, 애플리케이션에 쉽게 임베딩되도록 설계되었다.” 단일 자료 구조: “그것은 단 한 종류의 자료 구조, 즉 테이블을 제공한다.” “깔끔한 C,” “C와 C++의 교집합”으로 구현되었으며 “대부분의 플랫폼에서 별도 작업 없이 곧바로 컴파일된다.” 작은 크기: Lua 5.1 소스는 “약 17,000줄의 C”이고, tarball은 “플로피 디스크 한 장에 넉넉히 들어가며,” “모든 표준 Lua 라이브러리와 함께 빌드된 Lua 인터프리터는 143K를 차지한다.” “Adobe Lightroom의 40% 이상이 Lua로 작성되어 있다(약 10만 줄의 Lua 코드에 해당한다).” 브라질 무역 정책에 관하여: “1977년부터 1992년까지 브라질은 컴퓨터 하드웨어와 소프트웨어에 강력한 무역 장벽(‘시장 유보’라 불린)을 두는 정책을 폈다,” 그리고 “그런 이유들이 Tecgraf로 하여금 필요한 기본 도구를 처음부터 구현하게 이끌었다”; Lua는 “개발도상국에서 만들어져 전 세계적 의의를 달성한 유일한 언어”다. 선행 언어 DEL(“데이터 입력 언어”)과 SOL(“단순 객체 언어”). 작명: SOL은 포르투갈어로 태양이며, “Tecgraf의 친구(Carlos Henrique Levy)가 ‘Lua’(포르투갈어로 달)라는 이름을 제안했고, 그렇게 Lua가 탄생했다.” 첫 구현은 “가능한 한 가장 단순한 것”을 따라 1993년 7월에 완성되었다. “규칙이 아니라 메커니즘”에 관하여: “우리는 Lua를 객체 지향 언어로 만들고 싶지 않았다. Lua에 프로그래밍 패러다임을 고정하고 싶지 않았기 때문이다”; “Lua는 프로그래머에게 어떤 객체 모델이나 클래스 모델도 강요하지 않는다”; “우리는 프로그래머가 애플리케이션에 적합한 모델을 무엇이든 만들 수 있도록 유연한 메커니즘을 제공하기로 했다”; “확장 가능한 의미론은 Lua의 상징이 되었다.” 메커니즘 진화: 폴백(Lua 2.1, 1995) → 태그 메서드(Lua 3.0, 1997) → 메타테이블과 메타메서드(Lua 5.0, 2003); 테이블 인덱싱 폴백은 “(위임을 통한) 여러 형태의 상속”을 지원했다; “메타테이블”이라는 용어는 2001년 Rici Lake가 제안했다. Lua는 “Lua 코드와 외부 코드 사이의 완전한 통신”을 허용하는 C API를 갖춘 “확장 가능한 확장 언어”다. 게임: 1997년 1월, LucasArts의 Grim Fandango 리드 프로그래머 Bret Mogilefsky가 “게임의 엄청난 부분이 Lua로 작성되었다”고 보고했고, 그 후 “Lua는 게임 개발자들 사이에 입소문으로 퍼져 게임 업계에서 확실히 시장성 있는 기술이 되었다.” 동시성: 선점형 스레드 구현에는 “ANSI C의 일부가 아닌” 원시 기능이 필요하며, “우리는 표준 멀티스레딩 모델을 믿지 않았다(지금도 믿지 않는다)… ‘a=a+1’이 결정론적이지 않은 언어에서는 누구도 올바른 프로그램을 작성할 수 없다”; 코루틴을 통한 협력적 멀티태스킹은 Lua 5.0(2003)에서 제공되었다. VM: “Lua 5.0부터 가상 머신은 레지스터 기반이다,” 그리고 “Lua 5.0의 가상 머신은 널리 사용된 최초의 레지스터 기반 가상 머신이다”; 점진적 가비지 컬렉션은 Lua 5.1에서 등장한다. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩
-
“Lua: about,” Lua.org (공식 사이트). “Lua는 강력하고, 효율적이며, 가벼운, 임베딩 가능한 스크립트 언어다.” 그것은 “표준 C와 C++의 공통 부분집합인 깔끔한 C로 작성된 작은 C 함수 라이브러리로 구현”되며, “온갖 종류의 Unix와 Windows 시스템은 물론 모바일 기기… 임베디드 마이크로프로세서… IBM 메인프레임에서도 실행된다.” Lua를 “연관 배열과 확장 가능한 의미론에 기반한 강력한 데이터 기술 구문과 단순한 절차적 구문을 결합”한 것으로 설명하며, 동적 타이핑, 점진적 가비지 컬렉션을 통한 자동 메모리 관리를 갖추고 “빠르고” “이식 가능”하다고 기술한다. ↩↩
-
“Roberto Ierusalimschy,” Wikipedia, 그의 “faculty profile,” PUC-Rio 정보학과로 교차 확인됨. 1960년 5월 21일 브라질 리우데자네이루 출생; PUC-Rio 컴퓨터 과학 박사(1990); PUC-Rio 정보학 정교수; 워털루 대학교 박사후 연구 및 스탠퍼드 방문 교수(2012). Lua 프로그래밍 언어의 창작자이자 수석 설계자, Programming in Lua(4판)의 저자, 파싱 표현 문법을 구현하기 위한 Lua 라이브러리 LPeg의 개발자. ↩↩
-
“Programming in Lua,” Roberto Ierusalimschy 저, Lua.org. 수석 설계자가 직접 쓴 Lua에 관한 공식 서적으로, 언어의 설계와 사용을 기술한다; 1판은 온라인에서 무료로 제공된다. 유일한 자료 구조화 메커니즘으로서의 테이블, 확장 가능한 동작을 위한 메타테이블, 일급 함수, 협력적 멀티태스킹을 위한 코루틴을 중심으로 한 Lua의 설계를 보강해 준다. ↩
-
Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes, “The Evolution of Lua,” HOPL III, 2007, 임베디드 사용에 관한 각주. “2000년과 2001년 덴마크에서 RoboCup에서 우승한 로봇 Crazy Ivan은 Lua로 구현된 ‘두뇌’를 갖추고 있었다. Lua는 운영체제 없이 Motorola Coldfire 5206e 프로세서 위에서 직접 실행되었다(다시 말해, Lua가 곧 운영체제였다). Lua는 시스템 ROM에 저장되어 시작 시 직렬 포트에서 프로그램을 불러왔다.” 작고 이식 가능한 구현의 결과로 Lua가 베어메탈 임베디드 장치에까지 도달함을 보여 준다. ↩↩↩