제로부터 프로그래밍 언어: 완전 구현 가이드

발행: (2026년 1월 5일 오전 12:19 GMT+9)
12 min read
원문: Dev.to

I’m happy to translate the article for you, but I’ll need the actual text you’d like translated. Could you please paste the content (or the portions you want translated) here? I’ll keep the source link at the top and preserve all formatting, code blocks, URLs, and technical terms as you requested.

Python, JavaScript, 혹은 Go가 실제로 내부에서 어떻게 동작하는지 궁금해 본 적 있나요?

저는 몇 달 동안 다양한 언어 설계를 연구하고 구현하는 데 시간을 보냈으며, 기본적인 어휘 분석부터 JIT 컴파일에 이르기까지 모든 내용을 포괄적인 가이드로 정리했습니다.

만들게 될 내용

이 가이드를 따라 하면 간단한 계산기부터 시작해 점진적으로 다음을 추가하면서 완전한 프로그래밍 언어 구현을 만들게 됩니다:

  • Lexer & Parser – 소스 코드를 추상 구문 트리(Abstract Syntax Trees)로 변환
  • Interpreters – AST를 직접 실행 (가장 간단한 접근법)
  • Bytecode VMs – Python의 CPython과 같은 스택 기반 가상 머신
  • LLVM Integration – 네이티브 머신 코드를 생성
  • Garbage Collection – 자동 메모리 관리 전략

왜 이 가이드는 다를까

대부분의 컴파일러 튜토리얼은 조각만 제공합니다. 이 가이드는 Go에서 완전하고 실행 가능한 코드를 제공하므로 실제로 실행하고 수정할 수 있습니다.

실제 성능 수치

여기서는 얇은 설명이 없습니다. 이 가이드는 실제 벤치마크를 포함합니다:

Tree‑Walking Interpreter:  10‑100× slower than native
Bytecode VM:               5‑50× slower than native
JIT Compiled:              1‑5× slower (can match native)
AOT Compiled:              Baseline (native speed)

실제 사례 – 피보나치(40)

  • C (gcc -O3): 0.5 s
  • Python (CPython): 45 s (≈90× slower)
  • Python (PyPy JIT): 2.5 s (≈5× slower)

진행 학습 경로

WeekGoal
1주차인터프리터 구축 – 트리 워킹 인터프리터부터 시작합니다, 가장 단순한 실행 모델입니다. 주말이 끝날 때쯤 작동하는 언어를 갖게 될 것입니다.
2주차바이트코드 VM 추가 – 바이트코드로 컴파일하고 스택 기반 가상 머신을 구축합니다. Python과 Java가 내부적으로 어떻게 동작하는지 이해합니다.
3‑4주차네이티브 코드 생성 – LLVM을 사용해 최적화된 머신 코드를 생성합니다. Rust와 Swift가 빠른 이유를 배웁니다.
그 이후JIT 컴파일 – V8과 HotSpot이 런타임 최적화를 통해 거의 네이티브 수준의 성능을 달성하는 방식을 연구합니다.

완전한 작동 예제

가이드는 전체 계산기 언어 구현을 포함합니다:

  • Lexer (토큰화)
  • Recursive‑descent parser
  • AST 생성
  • Tree‑walking 인터프리터
source := `
x = 10
y = 20
z = x + y * 2
`

lexer := NewLexer(source)
parser := NewParser(lexer)
ast := parser.Parse()

interpreter := NewInterpreter()
interpreter.Eval(ast)

fmt.Printf("z = %d\n", interpreter.vars["z"]) // z = 50

이것은 의사코드가 아니라 실제 실행 가능한 Go 코드이며, 여러분이 기반으로 사용할 수 있습니다.

다루는 내용

컴파일 파이프라인

  • Lexical Analysis – 소스 코드를 토큰으로 분해
  • Syntax Analysis – 추상 구문 트리 구축
  • Semantic Analysis – 타입 검사 및 심볼 해석
  • Code Generation – 바이트코드, LLVM IR, 혹은 직접 해석

실행 모델 심층 탐구

  • Interpreters

    • 직접 AST 실행
    • 구현이 가장 간단
    • 스크립팅 및 설정 언어에 최적
  • Virtual Machines

    • 스택 기반 vs 레지스터 기반 아키텍처
    • 바이트코드 설계 및 명령어 집합
    • 함수 호출 및 스택 프레임
    • 제어 흐름 구현
  • LLVM Integration

    • LLVM IR 생성
    • 타입 시스템 매핑
    • 최적화 패스
    • 크로스 플랫폼 네이티브 코드 생성
  • JIT Compilation (Advanced)

    • 프로파일링 및 핫패스 탐지
    • 런타임 코드 생성
    • 디옵티마이제이션 전략
    • 타입 특수화

가비지 컬렉션

자동 메모리 관리 심층 탐구:

  • Reference Counting – 즉시 회수, 사이클 처리 불가
  • Mark‑and‑Sweep – 사이클 처리, 정지‑세계 일시정지
  • Copying / Generational – 최고의 성능, 가장 복잡

각 접근법은 실용 구현과 트레이드오프 분석을 포함합니다.

실제 사례 인사이트

이 가이드는 이론만 가르치는 것이 아니라 실용적인 결정들을 설명합니다:

  • 왜 파이썬은 직접 해석 대신 바이트코드를 사용하는가?
  • 자바스크립트는 어떻게 거의 네이티브 수준의 성능을 달성하는가?
  • 왜 Go의 컴파일 시간이 이렇게 빠른가?
  • 러스트의 빌림 검사기가 가능한 이유는 무엇인가?

트레이드오프 명확히

측면인터프리터바이트코드 VMJIT 컴파일러LLVM 기반 AOT
개발 복잡도주말 프로젝트1‑2주수개월2‑4주
실행 속도네이티브보다 10‑100배 느림5‑50배 느림1‑5배 느림 (네이티브와 동등 가능)네이티브 속도
시작 시간즉시매우 빠름느림 (워밍업 필요)즉시 (사전 컴파일)

주요 하이라이트

완전한 구현

모든 주요 구성 요소에 완전하고 작동하는 코드가 포함됩니다:

  • 위치 추적 및 오류 처리를 포함한 렉서
  • 연산자 우선순위를 지원하는 재귀 하강 파서
  • 전체 명령어 집합을 갖춘 스택 기반 VM
  • 제어 흐름을 포함한 LLVM IR 생성

핸드웨이빙 없이

가이드는 어려운 부분을 다룹니다:

  • JIT 컴파일을 위한 실행 가능한 메모리 만들기
  • 플랫폼별 호출 규약
  • 참조 카운팅이 사이클을 처리할 수 없는 이유
  • 명령 포인터와 호출 스택 관리

실용적인 예제

구현 방법을 배웁니다:

  • 변수와 할당
  • 올바른 우선순위를 가진 산술 표현식
  • 바이트코드의 제어 흐름(if / while)
  • 적절한 스택 프레임을 갖는 함수 호출
  • 타입 검사 및 의미 분석

대상 독자

다음에 해당한다면 읽어보세요:

  • 프로그래밍 언어가 어떻게 작동하는지 이해하고 싶다면
  • DSL 또는 설정 언어를 만들고 있다면
  • 컴파일러 설계에 관심은 있지만 Dragon Book이 겁나는 경우
  • 언어 프로젝트(Rust, Go, Python)에 기여하고 싶다면
  • 애플리케이션에 스크립팅 시스템을 구현해야 한다면

사전 요구 사항

  • Go에 익숙하거나(코드를 읽고 적용할 수 있다면)
  • 데이터 구조(트리, 스택)에 대한 기본 이해
  • 내부 구현이 어떻게 동작하는지에 대한 호기심

CS 학위 필요

컴파일러에 대한 사전 지식은 필요하지 않습니다.

학습 경로 추천

  1. 전체 계산기 예제부터 시작 – 바로 작동하는 것을 얻으세요.
  2. 제어 흐름 추가 – 바이트코드 예제를 사용해 if 문과 루프를 구현하세요.
  3. 함수 추가 – 제공된 호출‑프레임 구현을 사용하세요.
  4. LLVM 탐색 – 더 높은 성능이 필요할 때 네이티브 코드를 생성하세요.
  5. GC 학습 – 자동 메모리 관리 방식을 이해하세요.

각 단계는 이전 단계 위에 쌓이며, 모든 단계에서 작동하는 언어를 갖게 됩니다.

얻을 수 있는 것

  • 깊은 이해 of how interpreters, compilers, and VMs work.
  • 실전 경험 building complex systems from scratch.
  • 감사 for language‑design trade‑offs.
  • 기초 for contributing to real language projects.
  • 자신감 to build domain‑specific languages.

Resources Included

The guide references essential learning materials:

  • Bob Nystrom의 “Crafting Interpreters”
  • LLVM 튜토리얼 및 문서
  • 연구할 실제 언어 구현들
  • 성능 벤치마킹 기법

시작하기

전체 가이드와 모든 코드 예제는 GitHub에서 확인할 수 있습니다:

github.com/codetesla51/how-to-build-a-programming-language

레포를 클론하고, 예제를 실행한 뒤, 오늘 바로 자신만의 언어를 만들어 보세요.

Feedback Welcome

이 가이드는 살아있는 문서입니다. 문제가 있거나 질문이 있거나 개선에 기여하고 싶다면 GitHub에서 이슈나 PR을 열어 주세요.

프로그래밍 언어를 만드는 것은 컴퓨터 과학에서 가장 보람 있는 프로젝트 중 하나입니다. 전체 소프트웨어 스택을 이해하고 어떤 코드베이스든 파악할 수 있는 초능력을 줍니다.

  • 작게 시작하세요. 계산기를 만들어 보세요.
  • 기능을 점진적으로 추가하세요.
  • 무언가를 부수세요. 고치세요.

그게 바로 배우는 방법입니다.

행복한 언어 만들기!

Back to Blog

관련 글

더 보기 »

함수

markdown !Lahari Tennetihttps://media2.dev.to/dynamic/image/width=50,height=50,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%...