언어를 여러 개 만든 사람이 또 하나를 내놨어요
프로그래밍 언어를 여러 개 만든 사람은 흔치 않은데요, 바우터 판 오르트메르선(Wouter van Oortmerssen)이 그 드문 사람 중 하나예요. 이름은 낯설어도 그가 만든 것들은 한 번쯤 들어보셨을 거예요. 구글에서 만든 직렬화 라이브러리 FlatBuffers, 게임 개발용 언어 Lobster, 오픈소스 3D 게임 엔진 Cube/Sauerbraten, 그리고 90년대 아미가 시절의 Amiga E까지요. 1993년에 장난처럼 만든 초미니 언어 FALSE는 그 유명한 Brainfuck이 나오는 데 영감을 주기도 했고요.
그런 사람이 새 언어 Goose를 공개했어요. 존 카맥(둠, 퀘이크를 만든 그 카맥이요)도 이 언어에 코멘트를 남겼는데, 그가 콕 집은 키워드는 두 개예요. '여러 개의 데이터 스택(multiple data stacks)'과 '상대 참조(relative references)'요. 오늘은 이 두 개념이 뭔지, 왜 흥미로운지를 중심으로 풀어볼게요.
먼저, 스택 기반 언어가 뭐냐면
평소 쓰는 언어에서는 x = (2 + 3) * 4처럼 변수에 이름을 붙이고, 계산 순서는 괄호로 정하죠. 스택 기반 언어는 접근이 완전히 달라요. 접시 쌓듯이 값을 '스택'이라는 더미에 올리고, 연산자는 맨 위의 값들을 꺼내 계산한 다음 결과를 다시 올려놔요.
예를 들어 2 3 + 4 는 이렇게 돌아가요. 2를 올리고, 3을 올리고, +가 둘을 꺼내 5를 올리고, 4를 올리고, 가 5와 4를 꺼내 20을 올려요. Forth, PostScript, Factor 같은 언어가 이 방식이에요. 괄호나 변수 없이 단어를 이어 붙이기만 하면 프로그램이 돼서 '연결형(concatenative) 언어'라고도 불러요.
낯설어 보여도 사실 주변에 정말 많아요. 자바의 JVM 바이트코드, 웹어셈블리(WebAssembly), 파이썬 바이트코드, 이더리움의 EVM이 다 스택 머신 위에서 돌아가거든요. 우리가 쓴 코드도 컴파일러가 결국 이런 모양으로 바꿔준다는 뜻이에요.
스택이 하나뿐이면 생기는 고통
스택 언어를 써본 사람들이 다 같이 겪는 고통이 있어요. 바로 '스택 저글링'이에요. 값이 스택 하나에 몰려 있으니, 원하는 값을 맨 위로 꺼내려면 DUP(복제), SWAP(맞바꾸기), ROT(세 개 돌리기) 같은 명령을 계속 끼워 넣어야 하거든요. 책상에 서류를 한 더미로만 쌓아놓고 일하는 것과 비슷해요. 아래쪽 서류가 필요하면 위에 있는 걸 계속 옮겨야 하죠.
그래서 '스택을 여러 개 두면 어떨까?'라는 아이디어가 나와요. 사실 Forth도 계산용 데이터 스택과 함수 복귀 주소를 담는 리턴 스택, 이렇게 두 개를 쓰긴 해요. 여기서 한 발 더 나가 데이터 스택 자체를 여러 개 두면, 성격이 다른 값들을 다른 더미에 나눠 쌓을 수 있어요. 서류를 '결재용', '참고용', '임시'로 나눠 쌓으면 훨씬 덜 뒤적이게 되는 것처럼요. 스택 언어의 간결함은 살리면서 가장 큰 불편을 줄일 수 있는 방향이라, 카맥이 눈여겨본 것도 그래서일 거예요.
상대 참조는 또 뭐냐면
'상대 참조'는 무언가를 가리킬 때 메모리 주소나 고정된 이름 같은 절대 위치 대신, 지금 위치에서 얼마나 떨어져 있는지로 가리키는 방식이에요. '서울시 OO구 OO로 123' 대신 '여기서 오른쪽으로 세 번째 집'이라고 말하는 거죠.
이 방식의 장점은 데이터를 통째로 다른 곳에 옮겨도 참조가 깨지지 않는다는 거예요. 동네가 바뀌면 주소는 다 틀려지지만, '오른쪽 세 번째 집'은 동네를 통째로 옮겨도 여전히 맞잖아요. 그래서 파일로 저장했거나 네트워크로 받은 데이터를 그대로 메모리에 올려서 바로 쓰기에 좋아요.
재밌는 건 이 아이디어가 만든 사람의 이력과 딱 맞닿아 있다는 점이에요. FlatBuffers가 빠른 것도 내부 참조를 오프셋, 즉 상대 위치로 저장해서 파싱 없이 바로 읽을 수 있기 때문이거든요. 직렬화 라이브러리에서 다듬은 발상을 언어 설계 수준으로 끌어올린 시도로 볼 수 있어요. Goose가 이 개념들을 정확히 어떤 문법과 규칙으로 구현했는지는 공식 페이지에 예제와 함께 정리돼 있으니, 관심 있다면 직접 코드를 읽어보세요.
업계 맥락: 게임 개발자들의 언어 실험
최근 몇 년 사이 게임 쪽 개발자들이 직접 언어를 만드는 흐름이 눈에 띄어요. 조너선 블로우의 Jai, 진저 빌의 Odin, 그리고 판 오르트메르선의 Lobster가 대표적이에요. 다들 C++의 복잡함에 지쳐서 '성능과 단순함을 같이 잡을 수 없을까'를 고민한다는 공통점이 있죠. 스택 언어 쪽에서도 배열 연산과 스택을 섞은 Uiua 같은 새 언어가 나오면서, 오래된 패러다임에 새 숨을 불어넣는 시도가 이어지고 있어요. Goose도 메인스트림을 노린다기보다는 '이런 방식은 어때?'라는 아이디어를 던지는 실험작에 가까워요.
한국 개발자에게 주는 시사점
솔직히 Goose로 당장 실무 프로젝트를 할 일은 없을 거예요. 그래도 배워볼 가치는 충분해요. 스택 머신을 이해하면 JVM이나 웹어셈블리 바이트코드, 스마트 컨트랙트가 어떻게 돌아가는지가 훨씬 잘 보이거든요. 주말에 파이썬이나 자바스크립트로 100줄짜리 스택 계산기 인터프리터를 만들어보는 것도 좋은 연습이에요. '상대 참조' 발상은 직렬화 포맷, 메모리 매핑 파일, 캐시 친화적인 데이터 구조를 설계할 때 바로 써먹을 수 있는 감각이기도 하고요.
마무리
한 줄로 정리하면, Goose는 스택 언어의 오래된 불편함을 '여러 스택'과 '상대 참조'로 풀어보려는, 노련한 언어 설계자의 실험이에요.
여러분은 Forth 같은 스택 기반 언어를 써본 적 있나요? 변수 이름 없이 위치로만 값을 다루는 방식이 생산성을 높일까요, 아니면 머리를 더 아프게 할까요?
🔗 출처: Hacker News