SELECT 1
Entry 0082026.10.18 일
One launch a day. Picked, run, explained.

2026.10.18 일

esp32sim: 보드 없이 ESP32 펌웨어 그대로 실행하기

오늘의 픽: esp32sim

esp32sim 은 ESP32 계열 칩 네 종의 펌웨어를 실제 보드 없이 실행하는 에뮬레이터 프로덕트다. 칩의 ROM 부터 그대로 부팅하고, CLI 와 브라우저에서 실행된다.

오늘의 픽으로 선정한 이유는 보드 없이 칩의 실제 ROM 부터 부팅하는지를 직접 확인할 수 있어서다.

exit 0실행함작동한다. 칩 네 종이 실제 ROM 에서 부팅해 Hello world 를 출력했다.
WEEK 2주간 픽보드 없이 칩 네 종이 실제 ROM 에서 부팅했고, 7일 뒤에도 커밋 60개가 더해지며 개발이 이어지고 있다.
출처
Show HN
만든 방식
Rust, WebAssembly, Claude

무엇이 문제인가

ESP32 는 Espressif 가 만든 소형 칩으로, Wi-Fi 와 블루투스가 들어 있다. 펌웨어기기에 내장돼 하드웨어를 제어하는 프로그램. TV 같은 기기에서는 운영체제를 포함한 시스템 프로그램 전체를 가리킨다.의 동작은 칩을 얹은 보드에 올려서 확인한다. 팀에 보드가 한 개뿐이면, 펌웨어 개발자가 보드를 사용하는 동안 앱과 서버를 개발하는 동료는 차례를 기다려야 한다. 앱과 서버도 보드의 펌웨어와 통신해야 시험할 수 있기 때문이다. CI지속적 통합(continuous integration). 코드를 올릴 때마다 빌드와 테스트를 자동으로 실행하는 체계다. 서버에는 보드가 없어, 펌웨어 테스트를 자동으로 실행할 수도 없다. 2026년 10월 17일 Hacker News 의 esp32sim Show HN개발자 커뮤니티 Hacker News 에서 자신이 만든 프로덕트를 소개하는 글. 제목이 "Show HN:"으로 시작한다. 글에서 raminf 라는 사용자는 IoT 프로젝트마다 하드웨어를 기다리는 대신 "기능 시뮬레이터"를 따로 만들어 왔다고 했다. 저전력 블루투스(BLE)나 Wi-Fi 명령 수준에서 기기의 동작을 흉내 내는 프로그램이다.

제조사인 Espressif 는 QEMU 를 공식 방법으로 제공한다. QEMU 는 오픈소스 에뮬레이터다. 구조가 다른 CPU 의 프로그램을 일반 컴퓨터에서 실행할 수 있게 한다. ESP-IDFEspressif 가 제공하는 ESP32 개발 도구 모음. 라이브러리와 빌드 도구가 들어 있다. 프로그래밍 가이드(docs.espressif.com 의 QEMU Emulator 페이지)에 따르면, Espressif 는 QEMU 를 포크원본 저장소를 복제해 따로 개발하는 것. 또는 그렇게 만든 저장소.해 ESP32 지원을 추가했고, 이 포크를 관리한다. 이 포크는 ESP32 의 CPU, 메모리, 여러 주변장치칩 안에서 CPU 와 함께 동작하는 타이머, 통신 회로 같은 부품.를 에뮬레이션한다. 개발자가 ESP-IDF 를 설치한 컴퓨터에서 idf.py qemu monitor 를 실행하면, 이 명령이 앱을 빌드하고 QEMU 를 실행해 펌웨어의 로그를 화면에 출력한다.

어떻게 해결했나

Joakim Eriksson 과 Mattia Fiumara 가 만든 esp32sim 은 ESP32, ESP32-S3, ESP32-C3, ESP32-C6 네 칩을 CPU 명령어 단위로 에뮬레이션한다. 칩에는 마스크 ROM제조 과정에서 내용을 미리 기록해 둔 메모리. 수정할 수 없고, 전원이 들어오면 이 안의 코드가 가장 먼저 실행된다.에 기록된 코드가 있다. 이 코드는 수정할 수 없고, 전원이 들어오면 가장 먼저 실행된다. esp32sim 도 Espressif 가 공개한 ROM 파일(esp-rom-elfs)을 읽어 이 코드부터 실행하고, 이어서 부트로더전원이 들어온 뒤 앱이나 운영체제를 메모리로 불러와 실행하는 작은 프로그램.와 수정하지 않은 앱을 실행한다. 보드에 연결하는 디스플레이, 버튼, 카메라, 오디오 칩도 에뮬레이션한다.

esp32sim 에는 가상 무선 네트워크도 들어 있다. 에뮬레이터 안에는 가상 공유기가 있어, 펌웨어는 이 공유기를 찾아 비밀번호로 접속한다. 가상 공유기는 IP 주소를 발급하고, 핑과 도메인 조회, 시간 동기화 요청에 응답한다. 펌웨어가 인터넷으로 보내는 통신은 호스트의 네트워크로 중계한다. esp32sim 의 코드는 WebAssembly 로도 빌드할 수 있어, 브라우저에서도 펌웨어를 ROM 부터 부팅할 수 있다.

무엇이 다른가

첫째, 준비할 것이 다르다. Espressif 의 QEMU 를 사용하려면 ESP-IDF, QEMU, 시스템 라이브러리를 설치해야 한다. esp32sim 은 실행 파일 한 개와 ROM 파일, 펌웨어만 있으면 된다. 트레이드오프는 코드의 양이다. 제작자는 다른 에뮬레이터의 코드를 사용하지 않고 CPU 두 종류와 주변장치의 에뮬레이션 코드를 전부 직접 작성했다. 전체는 Rust 로 69,914줄이다. 또 JITJust-in-time 컴파일. 프로그램이 실행되는 도중에 자주 쓰이는 코드를 기계어로 바꿔 속도를 높이는 방식이다. 는 ARM 계열 컴퓨터(Apple Silicon 등)에서만 작동한다.

둘째, 부팅의 출발점이 다르다. ESP-IDF 문서에는 QEMU 포크가 CPU, 메모리, 여러 주변장치를 에뮬레이션한다고만 적혀 있다. esp32sim 은 실제 ROM 과 실제 부트로더를 그대로 실행하므로, 콘솔에 ROM 의 첫 메시지와 재시작 원인이 출력된다. README 에는 제작자가 실제 C3 보드와 콘솔 출력을 줄 단위로 비교한 결과, 세 번 부팅하는 동안 208줄 중 205줄이 같았다고 적혀 있다. 트레이드오프도 실제 ROM 을 실행하는 데서 생긴다. ROM 의 무선 코드는 실제 아날로그 회로가 있어야 작동한다. 그래서 README 에는 C6 에서 무선 회로를 보정하는 함수를 빈 함수로 대체해 건너뛰는 방법이 적혀 있다.

셋째, 네트워크 지원이 다르다. esp32sim 에는 가상 공유기와 네트워크가 들어 있어, 펌웨어는 실제 공유기 없이도 이 가상 공유기에 접속해 핑을 보낸다. 한계도 README 에 적혀 있다. 가상 공유기에 접속할 수 있는 기기는 한 대뿐이다. 구형 Wi-Fi 규격의 전송 속도만 지원하고, 절전 모드도 없다. 로드맵에는 Wi-Fi 와 BLE 를 무선 칩 내부 수준까지 에뮬레이션할 계획은 없다고 적혀 있다. Espressif 의 QEMU 문서에는 무선 설명이 없어 비교하지 않았다.

무엇이 편해지나

  • 보드가 한 대뿐인 팀의 앱·서버 개발자. 보드를 기다리지 않고 각자 노트북에서 펌웨어의 Wi-Fi 접속과 통신까지 시험할 수 있다. 오늘 C3 와 C6 펌웨어가 가상 공유기에 접속해 핑 5회에 성공했다.
  • CI 를 운영하는 팀. 실행 파일과 ROM 파일, 펌웨어만 있으면 되므로, CI 서버에서 펌웨어를 ROM 부터 부팅해 콘솔 출력을 확인할 수 있다. 오늘 S3 에서는 에뮬레이터 안의 26초가 실제 0.7초에 끝났다.
  • ESP32 를 처음 배우는 개발자. 보드를 사기 전에 브라우저에서 펌웨어가 부팅되는 과정을 확인할 수 있다. 브라우저 빌드는 오늘 확인하지 못했다.

어떻게 만들었나

  • 커밋 337개가 2026-09-21 부터 10-16 까지 쌓였다. 그중 Mattia Fiumara 의 커밋이 226개, Joakim Eriksson 의 커밋이 88개다. 커밋 174개의 메시지 끝에는 Claude Opus 5.5 와 함께 작성했다는 Co-authored-by 트레일러가 있다.
  • Rust 패키지(크레이트)는 12개, 테스트 함수는 973개다. docs/architecture.md 에 따르면 제작자는 CPU 명령어의 동작을 확인할 때만 QEMU 를 참고했다.
  • AGENTS.md저장소에 두는, AI 코딩 에이전트용 작업 규칙 파일. 에 따르면, 실험 기록에는 재현할 수 있는 사실(명령·입력·해시·수치·결과)만 적고 에이전트의 작업 과정은 서술하지 않는다. 테스트는 출력이 정답과 모든 비트가 같아야 통과한다.

실행해 보니

아래 순서로 시험했다.

  1. 빌드. CLI 버전만 cargo build --release 로 빌드했다. 1분 00초 걸렸다. 실행 파일 세 개(esp32sim, esp32sim-c3, esp32sim-c6)의 크기는 각각 17 MB 다.
  2. ROM. tools/fetch-rom-elfs.sh 가 Espressif 의 ROM 압축 파일(esp-rom-elfs 20260528)을 내려받아 SHA-256 해시를 대조하고, 압축을 풀어 ROM 파일 네 개를 추출했다. 1.4초.
  3. ESP32-S3 hello_world. 저장소의 데모 펌웨어를 실제 ROM 부터 부팅했다. ROM 의 첫 메시지 "ESP-ROM:esp32s3-20210327", 부트로더 로그, Hello world, 10초 카운트다운이 출력된 뒤 재시작했다. 에뮬레이터 안의 26초가 실제로는 0.7초에 끝났다(36배). 재시작 두 번 모두 ROM 부터 다시 부팅했다. 시험한 컴퓨터가 인텔·AMD 계열이라 JIT 는 한 번도 작동하지 않았다.
  4. C3, C6, ESP32(첫 모델). 같은 hello_world 펌웨어가 칩마다 세 번씩 부팅됐다. C3 는 26초를 5.0초에(5배), C6 는 27초를 6.7초에(4배), ESP32 는 26초를 0.9초에(29배) 끝냈다.
  5. C3 Wi-Fi 접속. --wifi 옵션으로 가상 공유기(이름 esp32sim, 암호화 방식 WPA2)를 띄웠다. 펌웨어가 그 공유기를 찾아 접속하고 IP 주소 10.0.2.15 를 받았다. 공유기로 보낸 핑 5회는 모두 성공했다. 에뮬레이터 안 14초, 실제 3.3초. 호스트 네트워크로 나간 통신은 0바이트였다.
  6. C6 Wi-Fi 접속. README 에는 보정 함수를 대체하는 옵션(--stub bb_init=0)이 적혀 있다. 저장소의 펌웨어에는 함수 이름 정보(ELF)가 없어, 이 옵션을 지정하자 esp32sim 이 unknown symbol 오류를 출력하고 종료됐다. 옵션 없이 실행해도 공유기 검색과 접속, 핑 5회는 모두 끝났다. 실제 4.1초. 보정 오류 세 줄(pll_cal exceeds 2ms)도 출력됐다. 옵션을 지정한 테스트의 정답에도 같은 세 줄이 있다.
$ esp32sim --board none --boot rom --console uart0 --rom roms/esp32s3_rev0_rom.elf ... --max-seconds 26
[emu] ROM loaded from roms/esp32s3_rev0_rom.elf
[emu] ROM boot from reset vector 0x40000400
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x1 (POWERON),boot:0xf (SPI_FAST_FLASH_BOOT)
...
This is esp32s3 chip with 2 CPU core(s), WiFi/BLE, silicon revision v0.2, 8MB external flash
...
Restarting now.
[emu] chip reset at t=11.005s: cause 0xc (RTC_SW_CPU_RESET)
ESP-ROM:esp32s3-20210327
...
[emu] stop: Halted — core0 11407872 + core1 6276760 insns in 0.7s wall = 25.3 Minsn/s; emulated 26.000s
[emu] blocks: 16434 built (0 cache flushes) core0, 2156 (0) core1; jit: 0 compiled, 0 KB code

확인하지 못한 것

  • 브라우저(WebAssembly) 빌드와 디스플레이·카메라·오디오 보드. 다음에 브라우저에서 디스플레이 보드의 화면을 확인하자.
  • BLE 예제와 테스트 973개. 다음에 C3 BLE 펌웨어와 cargo test 를 실행해 보자.
  • 실제 보드와의 대조. README 의 208줄 비교는 제작자가 측정한 결과다.

판정

작동한다. 칩 네 종이 실제 ROM 에서 부팅해 Hello world 를 출력했다. 다만 JIT 가 작동하지 않는 인텔·AMD(x86-64) 컴퓨터에서 C3 와 C6 는 실제 시간보다 4~5배 빠른 데 그쳤다. ESP-IDF 펌웨어를 보드 없이 CI 서버나 브라우저에서 부팅해 보고 싶고, 콘솔 출력과 Wi-Fi 접속까지만 확인하면 되는 경우에 써 볼 만하다. 무선 칩 내부 수준의 동작이나 정밀한 실행 타이밍을 검증해야 한다면 이 프로덕트는 적합하지 않다.

얻어갈 것

  • 에이전트와 함께 만드는 저장소라면 실험 기록의 형식부터 정하자. esp32sim 은 그 형식을 AGENTS.md 에 적어 두었다.
  • 에뮬레이터의 출력은 실제 보드와 줄 단위로 대조하자. README 에 따르면 실제 C3 보드와 비교하는 과정에서 에뮬레이터 버그 다섯 개가 발견됐다.
  • ROM 과 데모 펌웨어는 해시로 버전을 고정하자. 오늘 ROM 네 개는 압축 파일의 SHA-256 해시가 적힌 스크립트로 1.4초 만에 내려받았다. 데모 펌웨어는 저장소에 들어 있어 빌드(1분)만 마치면 부팅할 수 있었다.

시작하기

  1. git clone https://github.com/mikroverk/esp32sim && cd esp32sim
  2. cargo build --release -p esp32sim
  3. tools/fetch-rom-elfs.sh roms
  4. P=web/wasm/fw/public; target/release/esp32sim --board none --boot rom --console uart0 --rom roms/esp32s3_rev0_rom.elf --flash-mb 8 --psram-mb 2 --bootloader $P/hello-bootloader.bin --ptable $P/hello-ptable.bin --app $P/hello_world.bin --max-seconds 26
필요한 것
Rust stable 과 Cargo. Rust 버전을 고정하는 파일은 저장소에 없다 · Espressif 의 ROM 파일 네 개 (tools/fetch-rom-elfs.sh 가 압축 파일로 내려받아 그 SHA-256 해시를 대조한다) · 펌웨어 파일. 저장소의 데모 펌웨어나, ESP-IDF 로 빌드한 부트로더·파티션 테이블·앱의 .bin 파일
비용
MIT 라이선스, 무료. 가격 페이지는 없다.

JIT 는 ARM 계열(AArch64) 컴퓨터 전용이라, 인텔·AMD(x86-64) 컴퓨터에서는 더 느린 방식으로 실행된다. --wifi 옵션을 지정하면 펌웨어의 통신이 호스트의 네트워크로 중계되므로, 격리된 환경에서 실행하자.

실행해서 확인한 절차다.

진행

  1. 3일활발
  2. 7일활발
  3. 15일예정
  4. 30일예정
  5. 90일예정
  6. 180일예정
  7. 365일예정

최근 확인 7일, 2026.10.24 토

런칭 이후 커밋
0 → 60
스타
149 → 641
최신 릴리스
v0.3.0
마지막 커밋
2026.10.23
HN 득표
122 → 211
  • `--chip esp32` 로 듀얼 코어 ESP32 를 선택할 수 있다. 에뮬레이터는 이 칩의 실제 ROM 부터 수정하지 않은 앱까지 부팅한다(v0.3.0).
  • 모든 칩에서 WiFi 와 블루투스를 사용할 수 있다(v0.3.0).
  • `--wifi-nearby` 옵션을 지정하면 에뮬레이션한 칩이 WiFi 를 스캔할 때 가상의 주변 네트워크가 검색된다.
  • `--adc`, `--adc-raw` 옵션을 추가했다. 호스트에서 칩의 아날로그 입력 값을 지정할 수 있다.
  • ESP32-S3 의 범용 SPI 컨트롤러 가운데 GP-SPI3 에뮬레이션을 추가했다.

전체 이력 보기 →