ESP32-S3 Bench Guide
ESP32‑S3 N16R8 벤치 가이드: 실시간 핀아웃, 강의, 시뮬레이터 및 벤치 로그
웹 기반 천체물리 시뮬레이터 — Babylon.js WebGPU 기반 멀티스케일 우주 탐험 (태양계 → 관측가능우주)
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
웹 기반 천체물리 시뮬레이터 — Babylon.js WebGPU 기반 멀티스케일 우주 탐험. 태양계를 기점으로 근거리 항성, 은하, 관측가능우주까지 연속 스케일로 탐험 가능하며, 관측 데이터 기반의 정확성과 가상 실험의 자유도를 동시에 제공한다.README 전문 보기 ↗
웹 기반 천체물리 시뮬레이터 — Babylon.js WebGPU 기반 멀티스케일 우주 탐험.
태양계를 기점으로 근거리 항성, 은하, 관측가능우주까지 연속 스케일로 탐험 가능하며, 관측 데이터 기반의 정확성과 가상 실험의 자유도를 동시에 제공한다.
🌐 라이브 데모: https://astro-simulator-web.vercel.app
v0.107.0 — 로드맵 v3 (Incremental Body-by-Body Build) 완주 + 트랙 A/B (몰입·온보딩). 지구 밤면 육지에 도시 불빛이 켜졌다(#1226) — 별도 mesh 없이 표면 셰이더 안에서 합성해 ?nightlights=off 가 픽셀 단위 no-op 이고, 불빛이 어디 몰릴지는 이미 있던 대륙 노이즈를 임계로 재사용해 정한다(추가 hash 0). 그런데 이 릴리스의 이야기는 불빛이 아니라 처방이 두 번 폐기된 것이다. 신규 가드의 변이 하나가 4회 연속 「측정 불가」로 막혔고, 원인은 결함이 아니라 MSAA 4x resolve 가 삼각형 경계 한 픽셀에서 술어의 전제를 깬 것이었다 — antialias:false 개입으로 기전을 확정했다. 첫 처방은 임계 3 을 「기존 관례의 역방향 적용」으로 정당화했는데 외부 교차검증이 **「의사 형식주의」**로 기각했다(1 은 표준편차가 아니라 단일 knife-edge 아티팩트다) — 형식을 빌리는 것은 근거가 아니다. 두 번째 폐기는 더 컸다: 그 술어가 NI_land 안만 보고 있어, 낮면에만 불빛을 새게 하는 결함에서 판정량이 건강판과 완전히 같았다. 확정안은 오히려 단순해졌다 — 기준 프레임을 하나 지우자(NA 불도입) 「전제의 전제」·「기준과 대상이 같은 결함을 공유하는 사각」·「진단을 술어로 올릴지」가 함께 소멸했고 새 임계는 0 개다. 그 교체로 구름이 불빛을 가리는지 재는 게이트의 변이 검출력이 처음 확인됐다. 후속 패치 v0.89.1 은 사용자가 본 결함 둘을 닫았다 — tier 경계 줌은 「경계를 넘는 프레임이 구 단위 radius 로 렌더된다」가 원인이라 tween 을 지우고 즉시 대입으로 바꿨고(#1232), 장면 부팅 20 s 타임아웃은 원인 후보 둘을 실패 표본이 차례로 기각한 끝에 navigator.gpu.requestAdapter() 가 영영 settle 하지 않는 것으로 확정됐다(#1234). 뒤엣것은 마지막 검증 회차에서 자연 발생했고 상한이 흡수했다 — 11.7 s·13.3 s 에 부팅이 끝났다. 고친 것은 미결 자체가 아니라 그것이 부팅 전체를 잡는 구조다. 이어진 v0.89.2 는 가드가 스스로를 재는 회차였다 — bench 판정선이 측정량과 단위가 달라 8 PR 연속 발화하던 것을 상대 판정으로 바꿨고(#1209), 머지된 브랜치 101 개가 쌓인 이유가 삭제를 「집행 주체 없는 별도 단계」로 밀어낸 우리 절차였음을 확인해 주간 workflow 로 이관했다(#1247). 파일로만 있던 browser-verify 2종을 CI 에 걸었는데(#1207), 걸고 보니 그중 하나에 단언 없이 통과하는 경로가 둘 있었다 — 전건 붕괴보다 부분 붕괴가 더 나빴다(매트릭스 절반이 사라진 채 정상 통과). 이어진 v0.90.0 은 URL 을 몰라도 표시 효과를 켜고 끌 수 있게 했다 — 별 배경 · 지구 구름 · 야간 불빛은 로드 시점 ?x=off 로만 끌 수 있었는데, 상단 바 「표시」 패널에서 궤도선과 함께 토글하고 상태는 URL 에 반영돼 새로고침 · 북마크로 복원된다(#1265). 별 배경 · 구름 · 불빛을 런타임으로 끈 화면이 해당 ?x=off 로드 화면과 같다는 것을 가드가 픽셀로 판정하고(구름 · 불빛은 지구 disk, 별 배경은 전체 화면 · 하드웨어 전용), 기존 로드 경로와 그것을 전제로 쓰는 가드들은 한 비트도 바꾸지 않았다. ⚠️ 새 가드를 고칠 때마다 「측정 불가」 전제가 제품 결함을 다시 흡수했다 — 리뷰가 같은 클래스를 세 번 막았고(PR #1267 · #1268), 결국 전제를 게이트별로 나누는 판정 구조로 바꿔서야 수렴했다. 이어진 v0.91.0 은 천왕성 · 해왕성에 위도 밴드를 입혔다(#1274) — 목성의 gas-bands 와 분기가 별도인 IceGiant 표면 타입이라 목성 픽셀은 구조적으로 무접촉이고, 파라미터는 육안 승인 2라운드로 정했으며 천왕성에는 전용 albedo 배율이 붙는다. 두 행성 모두 단색보다 밝고 채도가 높게 렌더되며(절차 표면 광원식이 낮면 전체에 최대 세기를 준다), 다른 body 와 ?surface=off 는 픽셀 불변이다. 선행 작업으로 밴드 파라미터를 body 별 테이블로 옮겼고, 그 이관이 화면을 바꾸지 않는지는 두 빌드의 프레임을 비교하는 도구 verify:1274-invariance 로 쟀다. 이어진 v0.92.0 은 관찰 모드에서 고른 천체의 기본 정보를 모드를 바꾸지 않고 읽게 했다(#1281) — 좌하 카드가 한/영 이름 · 종류 · 태양 거리(현재 시뮬레이션 시각 기준) · 반지름 · 공전주기를 보이고, HUD 의 raw id 칩과 고정 정확도 · T1 관측 문구는 사라졌다. 상단 바의 천체 바로가기 12개는 키보드로도 조작되는 「천체 ▾」 메뉴 하나로 합쳐 1280 폭에서 12개 중 11개가 가려져 누를 수 없던 문제를 없앴고, 1440 미만에서는 카메라 · 북마크 · 조작 가이드가 아이콘 버튼으로 보이며, 모바일 연구 모드에서는 겹치던 두 패널을 [트리] [정보] 탭으로 나눴다. 이어진 v0.93.0 은 시간을 다루는 타임바를 손봤다(#1288) — 「지금」 버튼은 배속을 그대로 둔 채 현재 시각으로 이동하고, 100y 프리셋이 더해졌으며, 아래 행의 1900~2100 스크러버로 드래그 · 키보드로 시점을 옮긴다(재생 중에는 썸이 시각을 따라간다). 날짜 입력은 라벨대로 UTC 로 해석되도록 고쳤고(종전에는 사용자 시간대만큼 어긋났다), 극단 시각에서 타임바 UTC 표시가 예외를 던지던 경로를 막았다. 이어진 v0.94.0 은 천체를 이름으로 찾고 화면에서 이름을 읽게 했다(#1293) — 상단 바 검색 버튼 또는 / · Ctrl/⌘+K 로 32개 천체를 한글 · 영문 이름으로 찾아 이동하고, 3D 화면의 천체 옆에 한국어 이름 라벨이 붙는다. 라벨은 서로 겹치지 않게 우선순위(태양 > 행성 > 왜소행성 > 위성 > 혜성)로 정리되고, 위성 라벨은 모체나 그 위성을 고를 때만 보이며, 클릭하면 그 천체로 이동한다. 「표시」 패널이나 ?labels=off 로 끌 수 있다. 후속 패치 v0.94.1 은 목성 · 토성 위성이 모체에 묻히던 회귀를 고쳤다(#1299) — #762 에서 행성 표시 크기를 키울 때 위성 궤도 배율을 다시 계산하지 않아 이오가 목성 구 안에 묻혀 보이지 않았고 토성 위성은 고리 안을 돌았다. 갈릴레이 위성은 위성별 배율로 바꿔 4개 모두 목성 기본 화면에 들어오고, 재발 방지 테스트가 실제 표시 크기를 읽는다. 함께 온보딩 창을 Esc 로 닫을 때 자유시점까지 켜지던 결함을 고쳤다(#1296). 이어진 v0.95.0 은 명왕성 곁에 카론을 더했다(#1305) — 명왕성-카론은 반경비 0.51 의 이중 천체라 다른 위성처럼 작게 줄이지 않고 실제 비율로 그렸고, 궤도면은 명왕성 자전축을 따라 황도에서 약 113° 기울어 「세로」로 돈다. 위성 공전 계산도 모체와 위성 질량의 합을 쓰도록 바꿔 카론이 실제 주기 6.39일로 돌고 정보 카드 값과 맞는다(달은 0.6% 빨라지는 정도라 눈에 띄지 않는다). 후속 패치 v0.95.1 은 일시정지 상태로 공유 · 북마크 · 새로고침한 URL 이 그 시점의 천체 위치를 보이도록 고쳤다(#1308 — 장면이 시각 변경 알림을 늦게 구독해 J2000 에 머물렀다). 함께 모바일 상단 도구를 「⋯」 메뉴로 모아 360 · 375 폭에서 모든 도구에 닿게 했고, 라벨 위에서 끌어도 장면이 회전하며, 온보딩 안내의 천체 개수를 데이터에서 가져온다(#1313). (2026-10-08)
외부 판정은 기전과 자리를 분리해 받는다 — 외부 교차검증의 Critical 하나는 자리는 옳고 기전은 틀렸다. 자전축 기울기로 반례를 구성했는데 가드 프레임은 기울기가
0°라 그 경로가 발화조차 못 했다. 그렇다고 기각으로 끝낼 수도 없었다 — 반대편의 「구조적으로 불가」라는 전칭 주장도 거짓이었고(여는 축은 카메라 고도였다), 양쪽이 틀린 자리에서 실측이 제3의 답을 냈다. ⚠️ 그 전칭 주장을 쓴 것은 메인이다.
kepler / newton / barnes-hut / webgpu / auto
?belt=N 1~10000 (Kepler 해석해)infiniteDistance 천구 + 단일 draw call shader, 신규 에셋 0, ?stars=off 토글) / 첫 진입 온보딩 + 조작 가이드 모달 (소프트웨어 렌더 환경은 별 배경 자동 비활성 — fill-rate graceful degradation)?surface=off/?rotate=off 토글)
1024×512 육지 마스크 (27,295 B, public domain — 출처·라이선스) 가 저주파 형상을, 기존 fbm 이 고주파 디테일을 담당한다. 저장소의 유일한 런타임 텍스처 에셋이며 마스크 바이트의 JS 번들 유입은 0 B — .png 를 import 하는 소스가 저장소 전체에 없고 파일명 문자열로만 참조되므로 번들러가 인라인할 경로 자체가 없다 (셰이더 코드 자체의 JS 증가는 별개다)| 전체 태양계 | 지구 포커스 | 해왕성 30 AU | 모바일 480×900 |
|---|---|---|---|
| 영역 | 선택 |
|---|---|
| 렌더 엔진 | Babylon.js (WebGPU-first, WebGL2 폴백) |
| UI 프레임워크 | Next.js 16 (App Router) |
| 언어 | TypeScript (strict + exactOptional) |
| 패키지 매니저 | pnpm 10 (workspace 모노레포) |
| 상태 관리 | Zustand + nuqs + mitt + TanStack Query + zod |
| 스타일 | Tailwind v4 + Radix Primitives + CVA |
| 애니메이션 | Framer Motion (LazyMotion) |
| 테스트 | Vitest + Playwright + @axe-core/playwright |
상세: docs/phases/architecture.md
/apps
/web Next.js 애플리케이션 (UI 레이어)
/packages
/core @astro-simulator/core — 순수 TS 시뮬레이션 코어
(engine/coords/physics/scene/ephemeris/time/gpu)
/shared 공용 타입/상수/이벤트 정의
/docs
/phases 기획/아키텍처/Phase 문서
/retrospectives Phase 회고 + 성능/접근성/호환성 보고서
/screenshots 릴리스 스크린샷
/scripts 검증 스크립트 (legacy — 신규 verify 는 apps/web/scripts, #793 규약)
.node-version 고정 — Playwright extract deadlock 회피, #606)pnpm install
pnpm dev # apps/web 개발 서버 → http://localhost:3000
# 개발
pnpm dev # Next.js dev server
pnpm build # 전체 빌드 (core, shared, web)
pnpm typecheck # 타입 체크
pnpm lint # ESLint
pnpm test:unit # Vitest 전체 (core + shared + web + physics-wasm)
pnpm format # Prettier 포맷
# 브라우저 검증 (CRITICAL #3 준수)
pnpm verify:browser # 데스크톱 1280×800 — 3단계 검증
pnpm verify:mobile # 모바일 480×900
pnpm verify:scale # 스케일 전환 (태양~해왕성)
pnpm verify:perf # FPS 측정 (5 시나리오)
pnpm verify:a11y # axe-core + 키보드 + 색약
pnpm verify:smoke # 스모크 체인 순차 실행 (전수 아님 — 아래 계약)
verify:smoke 계약스모크 집합이지 전수가 아니다. 체인의 정본은 루트 package.json 의 verify:smoke 값 하나뿐이며,
개수·목록을 이 문서로 복제하지 않는다 — 사본을 두면 드리프트한다 (종전 이 줄의 # 위 5개 순차 실행 이
실제 체인 9개와 어긋나 있었다).
package.json 이고, 여기 적힌 것은 성격을 보이는 예시다.verify:<이슈번호>-* 꼴의 이슈별 회귀 가드. 필요하면 개별 실행한다.
⚠️ "CI 가 자체 배선한 정적 가드" 를 제외 기준으로 쓰지 않는다 — 체인 원소 verify:test-coverage
자신이 CI 배선분이라 그 술어는 절 안에서 자기모순이 된다 (PR #1111 reviewer).
등록된 verify:* 전건의 정본은 루트와 apps/web 의 package.json 이다.verify:smoke 실행됨. 체인 원소 중 어느 워크플로든 실제로 부르는 것은
verify:test-coverage 뿐이다 (측정 트리 rev 01401dd — 본 PR base. 초판 780cb92 는 그 부모라 라벨 오기였고, 두 rev 각각 측정해 수치 영향 0 을 실증했다). 나머지는 로컬에서만 돈다.verify:smoke 를 돌렸다고 회귀 가드 전수가 돈 것이 아니다.종전 이름은
verify:all이었고 #884 에서 개명했다.all은 전수 커버를 뜻하지 않았는데도 그렇게 읽혀 «잘못된 안심» 을 만들었다 — 이름 자체가 계약을 어기는 상태였다.
browser-verify-*.mjs — body 선택/궤도/focus 정합/fps/a11y 3단계 검증태양부터 하나씩 사용자가 실제로 보이는 body 를 점진 추가하는 재구성. (v2 Fact-First 기반 P10~P17 은 기본 진입 화면 UX 회귀로 전면 폐기 — volt #74)
상세: docs/phases/roadmap-v3-incremental.md. 폐기된 v1/v2 구상은 docs/deprecated/ 참조.
상세: docs/phases/roadmap-track-ab.md
docs/deprecated/이후 단계에서 NASA Exoplanet Archive, Gaia DR3 추가 예정.
MIT