# Fabrice Bellard, MicroQuickJS 공개

> Clean Markdown view of GeekNews topic #25292. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=25292](https://news.hada.io/topic?id=25292)
- GeekNews Markdown: [https://news.hada.io/topic/25292.md](https://news.hada.io/topic/25292.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2025-12-24T09:40:27+09:00
- Updated: 2025-12-24T09:40:27+09:00
- Original source: [github.com/bellard](https://github.com/bellard/mquickjs/blob/main/README.md)
- Points: 7
- Comments: 2

## Summary

**MicroQuickJS**는 약 10kB RAM과 100kB ROM만으로 동작하는 초경량 **JavaScript 엔진**으로, 임베디드 환경에서도 QuickJS에 가까운 실행 속도를 유지합니다. 메모리 절약을 위해 **트레이싱 가비지 컬렉터**와 **UTF-8 문자열 저장 방식**을 채택했으며, **strict mode 기반의 ES5 부분집합**만 지원해 안정성과 일관성을 확보했습니다. REPL 도구 `mqjs`를 통해 스크립트 실행과 바이트코드 저장이 가능하며, 전체 엔진과 표준 라이브러리가 ROM에 상주해 초기화 속도와 메모리 효율을 극대화합니다.

## Topic Body

- **MicroQuickJS(MQuickJS)** 는 임베디드 시스템용으로 설계된 초경량 **JavaScript 엔진**으로, 약 10kB RAM과 100kB ROM만으로 실행 가능  
- **QuickJS와 유사한 속도**를 유지하면서도 메모리 사용량을 줄이기 위해 **트레이싱 가비지 컬렉터**와 **UTF-8 문자열 저장 방식**을 채택  
- 지원 언어는 **ES5에 가까운 제한된 JavaScript 부분집합**이며, 오류 가능성이 높은 구문을 금지하는 **엄격 모드(strict mode)** 만 허용  
- **REPL 도구 `mqjs`** 를 통해 스크립트 실행, 바이트코드 저장 및 메모리 제한 설정이 가능하며, 생성된 바이트코드는 ROM에서 직접 실행 가능  
- 전체 엔진과 표준 라이브러리가 ROM에 상주해 **빠른 초기화와 낮은 메모리 소비**를 실현, 임베디드 환경에서의 **JavaScript 실행 효율성**을 높임  

---

### 소개
- **MicroQuickJS(MQuickJS)** 는 임베디드 시스템을 대상으로 하는 **JavaScript 엔진**으로, 10kB RAM과 100kB ROM(ARM Thumb-2 코드 포함)에서 동작  
  - 속도는 QuickJS와 유사  
- **ES5에 가까운 부분집합**만 지원하며, **비효율적이거나 오류 가능성이 높은 구문을 금지**하는 **엄격 모드(strict mode)** 로만 작동  
- QuickJS와 코드 일부를 공유하지만, 내부 구조는 **메모리 절약을 위해 완전히 다르게 설계**됨  
  - **트레이싱 가비지 컬렉터**, **CPU 스택 미사용**, **UTF-8 문자열 저장** 방식 사용  

### REPL
- REPL 명령은 `mqjs`이며, 스크립트 실행, 평가, 인터랙티브 모드, 메모리 제한 설정, 바이트코드 저장 등을 지원  
  - 예: `./mqjs --memory-limit 10k tests/mandelbrot.js`  
- `-o` 옵션으로 **컴파일된 바이트코드**를 파일로 저장 가능  
  - 저장된 바이트코드는 `./mqjs mandelbrot.bin`으로 실행 가능  
- 바이트코드는 CPU의 **엔디언 및 워드 길이(32/64비트)** 에 따라 다르며, `-m32` 옵션으로 32비트용 바이트코드 생성 가능  
- `--no-column` 옵션으로 **디버그 정보의 열 번호 제거** 가능  

### 엄격 모드
- **strict mode**만 허용하며, `with` 키워드 사용 불가, 전역 변수는 반드시 `var`로 선언해야 함  
- **배열의 구멍(hole)** 허용 안 함  
  - 예: `a[10] = 2`는 TypeError 발생  
  - 구멍이 있는 배열이 필요하면 일반 객체 사용  
- **전역 eval만 지원**, 지역 변수 접근 불가  
- **값 박싱(value boxing)** 비지원 (`new Number(1)` 등)  

### JavaScript 부분집합
- **strict mode** 기반, **ES5 호환성** 중심  
- **Array 객체**는 구멍이 없으며, 범위를 벗어난 인덱스 접근은 오류  
- `for in`은 객체의 **자체 속성만 순회**, `for of`는 배열만 지원  
- **글로벌 객체**는 존재하지만 getter/setter 불가, 직접 생성한 속성은 전역 변수로 노출되지 않음  
- **정규식(Regexp)** 은 ASCII만 대소문자 구분 처리, `/./`은 UTF-16 대신 유니코드 코드포인트 단위로 매칭  
- **문자열 함수**는 ASCII만 처리 (`toLowerCase`, `toUpperCase`)  
- **Date**는 `Date.now()`만 지원  
- 추가 지원 기능:  
  - `for of`, **Typed arrays**, `\u{hex}` 문자열 리터럴  
  - **Math 함수**: `imul`, `clz32`, `fround`, `trunc`, `log2`, `log10`  
  - **지수 연산자**, **정규식 플래그(s, y, u)** , **문자열 함수**(`replaceAll`, `trimStart`, `trimEnd`), **globalThis**  

### C API
- **C 라이브러리 의존성 최소화**, `malloc`, `free`, `printf` 미사용  
- **메모리 버퍼를 직접 제공**해야 하며, 엔진은 해당 버퍼 내에서만 메모리 할당  
  - 예: `ctx = JS_NewContext(mem_buf, sizeof(mem_buf), &js_stdlib)`  
- **가비지 컬렉션 방식**으로 인해 `JS_FreeValue()` 호출 불필요  
- 객체 주소는 할당 시마다 이동 가능하므로, **`JSValue` 포인터 사용 권장**  
  - `JS_PushGCRef()` / `JS_PopGCRef()`로 안전한 참조 관리  
- **표준 라이브러리**는 ROM에 저장 가능한 C 구조체로 컴파일되어, **빠른 초기화와 낮은 RAM 사용량** 달성  
- **바이트코드 실행**은 ROM에서 가능하며, `JS_RelocateBytecode()`로 재배치 후 `JS_LoadBytecode()`와 `JS_Run()`으로 실행  
- **수학 라이브러리(libm.c)** 와 **부동소수점 에뮬레이터** 내장  

### 내부 구조 및 QuickJS 비교
- **가비지 컬렉션**: 참조 카운팅 대신 **트레이싱·압축형 GC** 사용  
  - 메모리 단편화 방지, 객체 크기 축소  
- **값 표현**: CPU 워드 크기(32/64비트)에 맞춰 설계  
  - 31비트 정수, 유니코드 코드포인트, 부동소수점, 메모리 블록 포인터 저장 가능  
- **문자열은 UTF-8로 저장**, QuickJS의 8/16비트 배열 방식보다 효율적  
- **C 함수**는 단일 값으로 저장 가능, 속성 추가 불가  
- **표준 라이브러리**는 ROM에 상주하며, RAM 객체 최소화로 **빠른 엔진 초기화** 가능  
- **바이트코드**는 스택 기반이며, **간접 참조 테이블**을 통해 읽기 전용 처리  
  - **Golomb 코드**로 행·열 번호 압축  
- **컴파일러**는 QuickJS와 유사하지만 **비재귀적 파서**를 사용해 C 스택 사용량 제한  
  - 파스 트리 없이 **단일 패스 바이트코드 생성**  

### 테스트 및 벤치마크
- 기본 테스트: `make test`  
- QuickJS 마이크로 벤치마크: `make microbench`  
- **Octane 벤치마크**(엄격 모드용 수정 버전)는 별도 다운로드 가능  
  - 실행: `make octane`  

### 라이선스
- **MIT 라이선스**로 배포  
- 소스코드 저작권은 **Fabrice Bellard**와 **Charlie Gordon** 소유

## Comments



### Comment 48203

- Author: xguru
- Created: 2025-12-24T10:40:45+09:00
- Points: 2

Fabrice Bellard 에 대한 소개는 예전에 제가 댓글로 적은 것을 참고하세요. 이분 참 꾸준하면서 놀라운 괴물..  
https://news.hada.io/comment?id=51

### Comment 48199

- Author: neo
- Created: 2025-12-24T09:40:27+09:00
- Points: 1

###### [Hacker News 의견들](https://news.ycombinator.com/item?id=46367224) 
- 2010년에 이런 게 있었다면 Redis 스크립팅 언어는 Lua가 아니라 **JavaScript**였을 것 같음  
  Lua는 언어적 이유가 아니라 구현상의 제약(작고, 빠르고, ANSI-C 기반) 때문에 선택된 것임  
  Lua의 몇몇 아이디어는 좋지만, 개인적으로는 **Algol 계열 문법**에서 벗어난 점이 불필요하게 느껴졌음  
  SmallTalk이나 FORTH처럼 새로운 추상 개념을 배우는 대가로 생기는 혼란은 가치가 있지만, Lua의 변화는 그만큼의 이유가 없다고 생각함
  - Lua의 문법이 마음에 드는 건 아니지만, 개발자들이 선택한 이유는 충분히 납득할 만하다고 생각함  
    Lua는 **tail call optimization(TCO)** 을 지원하는 유일한 경량 언어로, 이 덕분에 루프 없이 재귀로만 프로그램을 짤 수 있음  
    JavaScript는 이런 최적화가 없어 같은 방식으로는 불가능함  
    Lua는 **컴파일러 작성**에도 특히 적합함. 재귀적 구조가 많기 때문임  
    Redis 스크립팅에는 JS가 더 어울릴 수도 있지만, Lua를 폄하하는 건 아쉬움
  - Lua가 1993년에 처음 나왔다는 점을 고려하면, 당시로서는 꽤 **전통적인 문법**이었음  
    브라질에서는 C보다 Pascal과 Ada가 더 널리 쓰였기 때문에 그 영향을 받은 것임  
    Ruby나 Perl도 비슷한 시기에 나왔지만 훨씬 더 급진적인 문법 변화를 시도했음
  - 처음엔 13살 때 Lua를 쉽게 배웠다는 얘기를 하려다 멈췄는데, 댓글 작성자가 **antirez** 본인이라는 걸 깨닫고 놀랐음
  - 문법 문제를 해결하진 못하겠지만, **“language skins”** 개념이 흥미로움  
    파서와 렉서를 분리해두면서도, `{}` 대신 `then`/`end` 같은 토큰을 바꿔 끼우는 시도는 거의 없었음  
    관련 논의: [HN 스레드](https://hn.algolia.com/?type=comment&prefix=true&query=cxr%20language%20skin), [Reddit 토론](https://old.reddit.com/r/Oberon/comments/1pcmw8n/is_this_sacrilege/nt18w18/?context=3)
  - 혹시 Redis 스크립팅 언어로 **Tcl**은 고려되지 않았는지 궁금함. 원조 임베디드 언어이기 때문임

- 이 엔진은 예전에 JSC 작업할 때 내가 원하던 방식으로 **JS를 제한**함  
  웹에서는 호환성 때문에 이런 제약이 불가능하지만, 임베디드 환경에서는 오히려 이런 제약이 **기쁨을 주는 설계**가 될 수 있음
  - 이미 이런 제약이 없는 JS 엔진을 가지고 있음
  - JSC에서 하던 **멀티스레딩 작업**은 어떻게 되었는지 궁금함. 애플을 떠난 뒤 중단된 건지, 코드가 여전히 남아 있는지 알고 싶음

- 브라우저에서 MicroQuickJS를 바로 실행해볼 수 있는 **플레이그라운드**를 만들었음  
  [MicroQuickJS WebAssembly 버전](https://tools.simonwillison.net/microquickjs)  
  참고로 원본 [QuickJS 버전](https://tools.simonwillison.net/quickjs)도 있음  
  QuickJS는 2.28MB, MicroQuickJS는 303KB로 훨씬 가벼움
  - 빌드에 이름 정보 등이 포함돼서 크기가 커진 듯함  
    `emcc -O3` 옵션이나 `--closure 1`을 추가하면 더 줄일 수 있을 것 같음  
    QuickJS는 이미 최적화돼 있고, MicroQuickJS만 개선 여지가 있음

- Jeff Atwood의 유명한 말처럼, “**JavaScript로 쓸 수 있는 모든 앱은 결국 JavaScript로 쓰이게 됨**”  
  이제 그 말이 임베디드 시스템에도 적용되는 듯함  
  [Jeff Atwood 위키](https://en.wikipedia.org/wiki/Jeff_Atwood)
  - 동의함. 관련 강연: [The Birth and Death of JavaScript](https://www.destroyallsoftware.com/talks/the-birth-and-death-of-javascript)
  - Fabrice Bellard가 브라우저 안에서 **Linux를 실행할 수 있는 JS 기반 VM**도 만든 적 있음  
    [JSLinux 링크](https://bellard.org/jslinux/vm.html?cpu=riscv64&url=fedora33-riscv.cfg&mem=256)
  - 이건 거의 인터넷의 **Rule 35** 같은 느낌임

- 커밋 히스토리 없이 업로드된 게 아쉬움  
  이런 수준의 개발자가 프로젝트를 얼마나 빨리 완성하는지 보고 싶었음  
  어차피 QuickJS 기반이라 비교 자체가 큰 의미는 없을 듯함
  - “public repository of…”라는 표현을 보면, 실제 작업 히스토리는 비공개 저장소에 있을 가능성이 있음  
  - 아마 그냥 **원샷으로 완성**했을 수도 있음

- 이게 **yt-dlp의 YouTube JS 챌린지**를 해결하는 가장 가벼운 방법이 될 수 있을지 궁금함  
  [yt-dlp EJS 문서](https://github.com/yt-dlp/yt-dlp/wiki/EJS) 참고  
  QuickJS는 이미 지원 중임
  - 가능성은 낮음. ES5 수준의 **부분 구현**만 지원하기 때문임  
    YouTube의 JS 퍼즐은 너무 복잡해서, Python으로 만든 JS 에뮬레이터도 포기했을 정도임
  - ES5만 구현된 상태라 현실적으로 어렵다고 봄

- 임베디드 시스템은 잘 모르지만, 이런 엔진이 **ESP32나 Arduino를 JavaScript로 프로그래밍**할 수 있게 해줄 수 있을지 궁금함  
  MicroPython처럼 말임
  - 이미 비슷한 프로젝트들이 있음  
    * [Espruino](https://www.espruino.com/)  
    * [Elk](https://github.com/cesanta/elk)  
    * [DeviceScript](https://github.com/microsoft/devicescript) (Microsoft Research의 중단된 프로젝트)
  - [Moddable/Kinoma의 XS 엔진](https://www.moddable.com/faq#comparison)은 ES6 이상을 지원함  
    MicroQuickJS는 ES5 일부만 구현돼 있고, 환경 바인딩도 제공하지 않음
  - 예전에 **Tessel**이라는 JS 프로그래밍 보드가 있었음  
    JS 코드를 Lua VM 바이트코드로 변환해 실행했는데, 꽤 영리한 접근이었음  
    최근 그 옛날 Node 0.8 CLI를 Rust로 다시 써봤지만, 결국 장비는 서랍으로 돌아감
  - 핵심은 **malloc()이 없는 구조**라는 점임. 그게 가능성을 열어줌

- 타이밍이 정말 중요함. 어젯밤에 올렸을 땐 아무 반응이 없었음
  - 아마 **운의 문제**일 뿐임
  - 다른 사람도 시도했지만 반응이 없었음  
    미국 아침 시간대에 다시 올리거나, 주기적으로 재게시하는 전략이 있음

- **Fabrice Bellard**는 현존하는 가장 생산적이고 다재다능한 프로그래머 중 한 명임  
  대표작: [FFmpeg](https://bellard.org), [QEMU](https://bellard.org/qemu/), [JSLinux](https://bellard.org/jslinux/), [TCC](https://bellard.org/tcc/), [QuickJS](https://bellard.org/quickjs/)  
  전설적인 인물임
  - 그가 높이 평가받는 만큼, 그의 **개발 방식**에 관심을 가지는 사람은 적음  
    최소한의 의존성과 도구로 완전한 프로그램을 만드는 접근이 인상적임
  - 이제는 그가 한 명이 아니라 **숙련된 해커 집단의 코드네임**일지도 모른다는 생각이 듦  
    진짜 사람이라면 잠은 자야 하니까
  - 그는 **LLM 추론 엔진**도 직접 개발해 GPT-2 시절부터 유지 중임  
    [ts_server](https://bellard.org/ts_server/), [TextSynth](https://textsynth.com/)
  - 흥미로운 점은, 그가 만든 프로그램 대부분이 **GUI 중심의 사용자 인터페이스**를 다루지 않는다는 것임  
    사용자가 매개변수를 설정하면 프로그램이 완결적으로 실행되는 구조를 선호하는 듯함
  - **국제 난독화 C 코드 콘테스트(IOCCC)** 에서 3회 우승한 경력도 있음  
    [IOCCC 수상자 목록](https://www.ioccc.org/authors.html#Fabrice_Bellard)

- “10kB RAM에서도 JS를 컴파일하고 실행할 수 있다”는 점이 인상적임  
  요즘처럼 **RAM이 비싸지는 시기**에 딱 맞는 타이밍임  
  이걸 Chromium이나 Electron에 넣을 수 있을지 궁금함
  - 웹 호환성 때문에 어렵겠지만, 어차피 Chromium의 **메모리 절감 효과**는 크지 않을 듯함
