GITHUB 레포 딥다이브 · 2026-07-30 · REFLEX-DEV/XY · 파이썬용 초고속 GPU 차트 엔진

reflex-dev/xy 딥다이브
1억 점을 브라우저에서 실시간으로 그리는 차트 엔진

XYRust 코어 + WebGL2 + 이진 컬럼 전송을 엮어서, 데이터가 아무리 커도 화면 픽셀 수만큼만 계산하고 그리는 파이썬 차트 라이브러리다. Matplotlib·Plotly가 데이터가 커질수록 느려지는 반면, XY는 10,000개든 1억 개든 거의 같은 속도(약 0.08초)로 렌더한다. 무려 OpenStreetMap 전체(100억 점)까지 그려낸 사례를 공개했다. Reflex 팀이 만든 알파 단계 오픈소스다.

이 문서는 XY가 "왜 빠른가"를 아키텍처 레벨에서 뜯어보고, Rust·WebGL·이진 전송·LOD(레벨 오브 디테일) 같은 핵심 개념을 초보자도 이해할 수 있게 풀어낸 공부자료다.
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가 — 트렌딩 이유와 경쟁 우위
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 — 4겹 파이프라인
  5. 디렉토리 구조 해부
  6. 학습 포인트 — 기술별 배울 것
  7. 하드웨어/시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

XY가 정확히 무엇을 하는 물건인지 한 문단으로

XY는 파이썬에서 차트를 만들고, 그 차트를 브라우저·노트북·정적 파일(HTML/PNG/SVG/PDF) 어디서든 보여주는 시각화 라이브러리다. 겉보기 사용법은 Matplotlib이나 Plotly와 비슷하다. xy.line_chart(...) 한 줄로 선 그래프가 나온다. 하지만 내부는 완전히 다르게 설계됐다.

한 문장 비유

"지도 앱이 도시 전체를 한 번에 안 그리는 것"과 같은 원리

구글 지도는 지구 전체의 도로를 한꺼번에 그리지 않는다. 지금 화면에 보이는 영역·확대 배율에 맞는 타일(tile)만 골라 그린다. 확대하면 그때서야 골목이 나타난다. XY는 이 발상을 데이터 차트에 그대로 적용했다. 1억 개 점이 있어도, 화면이 200만 픽셀이면 200만 개어치의 정보만 계산해서 그린다. 확대하면 그 좁은 구간을 다시 계산해 진짜 점 하나하나를 드러낸다.

핵심 문장은 프로젝트 설계 문서(design dossier)의 첫 줄에 이렇게 적혀 있다: "Plotly의 비용은 데이터가 얼마나 많은가에 비례하고, 이 엔진의 비용은 화면에 픽셀이 몇 개인가에 비례한다." 이 한 번의 발상 전환이 XY의 전부다. 현재 버전은 0.0.4(2026-07-27 릴리스)로 알파 단계이며, 라이선스는 Apache-2.0, 만든 곳은 파이썬 웹 프레임워크 Reflex를 만든 reflex-dev 팀이다.

2왜 주목받는가 — 트렌딩 이유와 경쟁 우위

TrendShift 데일리 상위권에 오른 이유를 벤치마크로 확인

XY가 뜨는 이유는 단순하다. 측정 가능한 압도적 성능 격차를 벤치마크로 공개했기 때문이다. 아래 표는 "모든 점이 화면에 완전히 그려질 때까지 걸린 시간(초)"이다. 낮을수록 좋다. 벤치마크는 실제 브라우저에서, 각 라이브러리 고유의 입력 경로로, "캔버스가 정확하고 10프레임 연속 동일할 때"만 시계를 멈추는 엄격한 방식으로 측정됐다.

점 개수10k100만1000만5000만1억
XY (density)0.0710.0840.0830.0760.081
Matplotlib0.0860.3572.80413.385✕ 실패
Plotly0.3410.6143.367✕ 실패✕ 실패

숫자를 뜯어보면: XY는 4자릿수 규모(1만~1억)를 넘나들어도 시간이 거의 평평하다. 반면 Matplotlib은 5000만 점에서 13초, Plotly는 5000만 점에서 아예 그림을 못 만든다. 5000만 점 기준 XY는 Matplotlib보다 177배 빠르다. 메모리도 마찬가지여서, 1억 점을 파이썬 쪽 2.58 GiB로 처리한다(density=False 순수 모드는 5.26 GiB).

왜 이게 대단한가

기존 차트 라이브러리에서 "점 100만 개"는 사실상 한계선이었다. 그 이상은 브라우저가 멈추거나 몇 초씩 기다려야 했다. XY는 그 천장을 1000배(10억+) 위로 밀어올렸다. 유전체 데이터(수백만 변이), 천문 관측(수십만 별), 금융 틱 데이터, 지리정보 같은 "기존엔 다운샘플링해야만 봤던" 대용량 데이터를 원본 그대로 인터랙티브하게 탐색할 수 있게 됐다.

경쟁 제품 대비 4가지 결정적 차이

항목Matplotlib / Plotly (기존)XY
렌더 방식점마다 SVG 노드 1개 / 메인스레드GPU 인스턴싱(WebGL2)
데이터 전송모든 값을 JSON 문자열로이진 f32 버퍼(파싱 0)
무거운 계산파이썬(느림) 또는 브라우저파이썬 프로세스 안의 네이티브 Rust
데이터 양전부 그림 → N에 비례해 느려짐화면 픽셀 수만큼만(LOD)

그리고 XY는 성능만 파는 게 아니다. Matplotlib 호환 모드(import xy.pyplot as plt)를 제공해 기존 코드를 거의 그대로 이식할 수 있고, Python·CSS·Tailwind로 모든 레이어를 커스터마이즈할 수 있으며, 자기네 웹 프레임워크 Reflex에 어댑터(reflex-xy) 하나로 끼워 넣을 수 있다. "성능과 커스터마이즈, 둘 다 포기 안 시킨다"가 이 프로젝트의 북극성(North Star)이다.

3기술 스택 전체 지도

3개 언어(Rust·Python·TypeScript)가 각자 다른 층을 맡는 구조

XY의 특이한 점은 하나의 라이브러리 안에 3개의 언어가 명확히 분업한다는 것이다. 각 언어가 자기가 제일 잘하는 일만 맡는다. Rust는 무거운 수치 계산, Python은 API와 오케스트레이션, TypeScript는 브라우저 GPU 렌더링이다.

① 네이티브 코어 — Rust

용어 풀이
cdylib (C ABI 동적 라이브러리)
Rust로 컴파일한 코드를 C 언어처럼 호출 가능한 .so/.dll 파일로 만든 것. 이렇게 하면 파이썬이 ctypes로 직접 불러 쓸 수 있고, 파이썬 버전마다 따로 빌드할 필요가 없다(플랫폼당 하나면 모든 CPython이 씀).

src/의 Rust 코드는 총 약 2만 줄이다. 외부 크레이트(라이브러리)를 극도로 아껴서, 의존성이 png 하나뿐이다. 릴리스 빌드는 LTO(전체 프로그램 최적화) + codegen-units=1 + strip으로 최대한 조여서 만든다. 주요 파일:

파일줄 수역할
kernels.rs7,463핵심 수치 커널 — 데시메이션·밀도 집계·존맵
raster.rs4,142정적 내보내기용 래스터화(PNG 등)
lib.rs3,602C ABI 진입점, 패닉 캐치, ABI 버전
font.rs2,535폰트 메트릭·글자 래스터(내장)
tiles.rs1,160타일 피라미드(LOD 저장 구조)
simd.rs448SIMD 가속 경로

② 오케스트레이션 코어 — Python

python/xy/가 실제 사용자가 import xy로 만지는 패키지다. 런타임 의존성은 단 2개: numpy(수치 배열)와 anywidget(주피터 위젯 표준). 내부 구조가 잘 분리돼 있다:

용어 풀이
pyplot 시(shim)
python/xy/pyplot/Matplotlib 흉내내기 층이다. plt.subplots(), ax.plot(), plt.show() 같은 익숙한 명령을 받아서 XY의 공개 API로 번역한다. Matplotlib 코드를 import 한 줄만 바꿔서 XY로 옮기게 해주는 "어댑터"다.

③ 렌더 클라이언트 — TypeScript → WebGL2

js/src/*.ts는 브라우저에서 GPU로 그림을 그리는 얇은 렌더 클라이언트다. 흥미롭게도 파일 이름이 00_header.ts, 40_gl.ts, 50_chartview.ts처럼 숫자 접두사로 되어 있다. 예전엔 하나로 이어붙이던(concat) 코드를 모듈로 쪼갠 흔적이다. node js/build.mjs가 타입 체크·셰이더 린트 후 vite로 번들·압축해서 python/xy/static/index.js(anywidget용)와 standalone.js(window.xy 전역용) 두 개를 만든다.

결정적으로 이 번들은 런타임 의존성이 0이다. vite·typescript·playwright는 전부 빌드/테스트 시점에만 쓰이고, 실제 배포되는 클라이언트에는 외부 JS 라이브러리가 하나도 안 들어간다. 주요 모듈:

모듈역할
10_colormaps.tsCVD(색각이상) 안전 컬러맵 — 256텍셀 LUT 텍스처 1회 생성
30_ticks.ts축 눈금 계산(반드시 f64로, f32 거치지 않음)
40_gl.tsWebGL2 헬퍼 + 셰이더 프로그램
45_lod.ts / 46_worker.tsLOD 판단 / 커널 없는 페이지용 밀도 재비닝 워커
50_chartview.ts차트 뷰 본체(가장 큰 모듈)
53_interaction.ts팬·줌·호버·박스/올가미 선택

④ 빌드·인프라

빌드 시스템은 hatchling + uv-dynamic-versioning이다. 버전 번호를 코드에 안 적고 git 태그에서 자동 유도한다(git tag vX.Y.Z가 릴리스 액션 전부). Rust 코어와 JS 번들은 git에 커밋하지 않고 hatch_build.py가 패키징 시점에 빌드해 휠에 강제 포함한다. 파이썬 의존성 관리는 uv, 린트·포맷은 ruff, 타입 체크는 ty, 벤치마크는 CodSpeed를 쓴다.

4아키텍처 심화 — 4겹 파이프라인

데이터가 파이썬에서 GPU 화면까지 흘러가는 경로를 한 층씩

XY의 전체 데이터 흐름은 5단계 파이프라인으로 요약된다. 각 단계가 "데이터를 얼마나 줄이느냐"의 승부처다.

┌──────────────────────────────────────────────────────────────┐ │ ① Python API xy.scatter_chart( xy.scatter(x, y) ) │ │ 차트를 선언적으로 조립 │ └───────────────┬──────────────────────────────────────────────┘ │ 원본 x, y (예: 1억 개) ▼ ┌──────────────────────────────────────────────────────────────┐ │ ② ColumnStore 캐논 데이터 = CPU측 f64 컬럼 │ │ 원본을 절대 안 버림 (호버·선택 시 진짜 행 반환용) │ └───────────────┬──────────────────────────────────────────────┘ │ f64 컬럼 참조 ▼ ┌──────────────────────────────────────────────────────────────┐ │ ③ Native Rust 코어 (파이썬 프로세스 안, ctypes) │ │ ┌─ direct : 점 < 20만 → 전부 그대로 │ │ ├─ decimated : M4 알고리즘으로 선을 픽셀폭만큼 축약 │ │ └─ density : 화면 격자에 밀도 집계 (200k행 초과) │ └───────────────┬──────────────────────────────────────────────┘ │ 화면에 필요한 양만! (예: 200만 픽셀어치) ▼ ┌──────────────────────────────────────────────────────────────┐ │ ④ Compact payload 데이터 없는 JSON 스펙 │ │ + 오프셋 인코딩된 f32 이진 버퍼 (JSON 숫자 0개!) │ └───────────────┬──────────────────────────────────────────────┘ │ raw f32 buffers (파싱 불필요) ▼ ┌──────────────────────────────────────────────────────────────┐ │ ⑤ Browser / Notebook │ │ WebGL2 마크(GPU) · Canvas 축 · DOM 인터페이스 │ │ 팬·줌 → ③으로 정제된 페이로드 재요청 (라이브 호스트) │ └──────────────────────────────────────────────────────────────┘

핵심 설계 패턴 1 — LOD(레벨 오브 디테일): "화면만큼만 그린다"

용어 풀이
LOD (Level of Detail)
게임·지도 엔진에서 온 개념. 멀리 있는(=많이 축소된) 것은 대충, 가까운(=확대된) 것은 정밀하게 그리는 기법. XY는 데이터 양이 아니라 보이는 픽셀 수를 기준으로 3단계 중 하나를 고른다.

Rust 코어는 매번 3가지 티어(tier) 중 하나를 고른다. js/src/45_lod.tsLOD_DIRECT_POINT_BUDGET = 200000이라는 상수가 있다. 즉:

M4 데시메이션 비유

화면 가로가 1000픽셀인데 데이터가 100만 점인 선 그래프가 있다고 하자. 한 픽셀 열에 1000개 점이 겹친다. 사람 눈엔 그 열의 가장 높은 값·가장 낮은 값·시작·끝 4개만 보이면 선 모양이 똑같이 나온다. M4는 픽셀 열마다 이 4개(Min·Max·First·Last, 그래서 이름이 M4)만 남긴다. 100만 → 4천 점으로 줄어도 그림은 픽셀 단위로 동일하다.

핵심 설계 패턴 2 — 이진 전송: "JSON 숫자를 배선에 안 태운다"

Plotly의 큰 병목 중 하나는 모든 숫자를 JSON 문자열로 만들어 보내고, 브라우저가 그걸 다시 숫자로 파싱하는 것이다. 숫자 3.14159265 하나가 문자 10글자가 되고, 1억 개면 GB 단위 텍스트가 된다. XY의 설계 불변식(invariant) 첫 줄이 바로 이것이다: "배선 위에 JSON 숫자는 없다. 데이터는 raw f32 버퍼로 이동한다(§29)."

용어 풀이
오프셋 인코딩된 f32 (offset-encoded f32)
f32(32비트 실수)는 정밀도가 약 7자리뿐이라, 큰 좌표(예: 경도 127.123456789)를 담으면 오차가 생긴다. 그래서 XY는 뷰포트 원점을 빼서(offset) 작은 상대값으로 만든 뒤 f32로 보낸다. 그리고 눈금·호버 계산 같은 정밀한 수학은 항상 f64로 CPU에서 처리한다. "GPU엔 f32, 계산엔 f64"라는 이중 정밀도 규율이다.

핵심 설계 패턴 3 — 캐논 데이터는 파이썬에 남는다

또 다른 불변식: "정본 데이터는 CPU측 f64이고, 모든 GPU/파생 버퍼는 언제든 다시 만들 수 있는 캐시(cache)일 뿐이다(§27)." 이게 왜 중요하냐면, 밀도 표면으로 뭉뚱그려 그렸어도 사용자가 특정 영역을 호버하거나 선택하면 XY는 원본 f64에서 진짜 원래 행(row)을 그대로 되돌려준다. "시각적으론 요약, 데이터는 손실 없음"이 동시에 성립한다. 그리고 NaN(결측값)은 절대 정점 버퍼(vertex buffer)에 도달하지 않는다(§19) — GPU가 깨지지 않게 Rust 단계에서 걸러낸다.

핵심 설계 패턴 4 — 라이브 호스트 vs 정적 내보내기

파이썬 커널이 살아있는 환경(노트북·Reflex 앱)에서는 팬·줌 때마다 새 범위를 Rust에 보내 정제된 페이로드를 다시 받는다. 반대로 to_html()로 뽑은 커널 없는 정적 파일에서는, 46_worker.ts가 브라우저 안에서 밀도 격자를 재비닝(re-bin)하는 워커를 돌려서 커널 없이도 어느 정도 줌이 되게 한다. 같은 차트가 살아있는 앱에서도, 죽은 HTML에서도 동작하도록 두 경로를 다 갖춘 것이다.

5디렉토리 구조 해부

루트에서 무엇이 어디 있는지 — "언어별 분업"이 폴더로 드러난다
xy/ ├── src/ ← ① Rust 네이티브 코어 (약 2만 줄) │ ├── kernels.rs 핵심 수치 커널 (데시메이션·밀도·존맵) │ ├── raster.rs 정적 내보내기 래스터화 │ ├── lib.rs C ABI 진입점 + ABI_VERSION │ ├── font.rs 내장 폰트 메트릭/래스터 │ ├── tiles.rs 타일 피라미드(LOD 저장) │ └── simd.rs SIMD 가속 │ ├── python/ │ ├── xy/ ← ② 사용자가 import 하는 파이썬 패키지 │ │ ├── components.py 공개 차트 빌드 API (유일한 표면) │ │ ├── marks.py 모든 마크의 단일 구현 │ │ ├── _native.py ctypes로 Rust 코어 바인딩 │ │ ├── columns.py ColumnStore (원본 f64 보관) │ │ ├── lod.py LOD 판단 │ │ ├── _payload.py 이진 전송 페이로드 조립 │ │ ├── export.py / _png.py / _svg.py / _pdf.py 정적 출력 │ │ ├── pyplot/ ← Matplotlib 호환 시(shim) │ │ ├── styling/ CSS/Tailwind 스타일 처리 │ │ └── static/ (빌드 산출물) 번들된 JS │ └── reflex-xy/ ← ③ Reflex 어댑터 (별도 배포 패키지) │ ├── js/ │ ├── src/*.ts WebGL2 렌더 클라이언트 (모듈 17개) │ └── build.mjs 타입체크→셰이더린트→vite 번들 │ ├── spec/ ← 설계의 "단일 진실원" │ ├── design-dossier.md 전체 설계 + 경쟁 리서치 + 감사 로그 │ ├── api/ capability-matrix, lod, chart-roadmap... │ ├── matplotlib/compat.md 호환성 매트릭스 │ └── benchmarks/ 벤치마크 스펙·결과 │ ├── examples/ ← 실전 예제 │ ├── reflex/ Reflex 데모 앱 │ ├── fastapi/ FastAPI 라이브 드릴다운 │ ├── real_world/ Gaia·gnomAD·UKBB·LIGO·NYC 택시 │ ├── pdsh/ "Python Data Science Handbook" 이식 노트북 │ └── bad_apple/ 밀도 애니메이션 데모 │ ├── benchmarks/ ← §12 벤치 하네스 ├── tests/ ← Rust + Python + Reflex 테스트 ├── Cargo.toml Rust 크레이트 정의 ├── pyproject.toml 파이썬 패키지 정의 ├── hatch_build.py 빌드 시 Rust·JS 산출물 휠에 포함 └── CLAUDE.md → AGENTS.md 기여자·에이전트용 지침
구조에서 배울 점
"스펙이 코드보다 위에 있다"

spec/ 디렉토리가 의도된 동작의 단일 진실원(source of truth)이다. CLAUDE.md에 "코드 주석이 dossier 섹션(§16 등)을 인용하고, 스펙이 낡으면 그 변경은 미완성"이라고 못박아 놨다. 구현이 아니라 스펙이 최종 권위라는 규율은 큰 엔지니어링 프로젝트에서 드물게 철저한 사례다.

6학습 포인트 — 기술별 배울 것

이 레포를 뜯으면서 실제로 손에 남는 지식들

① Python ↔ Rust FFI (ctypes / C ABI)

가장 배울 게 많은 부분. "파이썬은 느리다"의 해법으로 흔히 PyO3(러스트-파이썬 바인딩 프레임워크)를 쓰지만, XY는 일부러 순수 C ABI + ctypes를 택했다. 이유는 플랫폼당 .so 하나가 모든 CPython 버전에 통하기 때문(PyO3는 파이썬 버전마다 빌드 필요). src/lib.rsABI_VERSIONpython/xy/_native.py를 시그니처 바뀔 때마다 같이 올려야 한다는 규칙에서, FFI 경계를 안전하게 버전 관리하는 법을 배울 수 있다.

② WebGL2 인스턴싱과 셰이더

js/src/40_gl.ts·50_chartview.ts에 정점/프래그먼트 셰이더(POINT_VS, DENSITY_FS 등)가 들어 있다. 인스턴스드 렌더링(같은 마커 모양을 한 번 정의하고 위치만 바꿔 수백만 개 찍기), LUT 텍스처로 컬러맵 적용, 밀도 표면을 프래그먼트 셰이더로 색칠하는 기법 등 실전 GPU 시각화 패턴을 볼 수 있다.

③ 데이터 시각화 알고리즘

M4 데시메이션(시계열 픽셀 축약), 밀도 비닝(binning), 존맵(zone map) 같은 대용량 시각화의 정석 알고리즘이 Rust로 구현돼 있다. 설계 문서가 datashader·plotly-resampler 같은 선행 연구를 정직하게 인용("우리가 발명한 게 아니라 통합한 것")하는 태도도 배울 만하다.

④ 이진 프로토콜 설계

"JSON 숫자 금지, 오프셋 인코딩 f32, f64는 CPU 유지" 같은 불변식(invariant)을 명문화하고 테스트로 지키는 방식. API 설계에서 "무엇을 절대 안 할지"를 먼저 못박는 규율을 배울 수 있다.

⑤ 호환 레이어(shim) 설계

xy.pyplot이 Matplotlib API를 흉내내되, tests/pyplot/test_boundaries.py"pyplot이 공개 API 위로만 의존한다"는 단방향 규칙을 강제한다. 레거시 호환을 제공하면서도 아키텍처가 오염되지 않게 지키는 실전 기법이다.

실습 아이디어 (맛보기)

1. pip install xy 후 README의 1억 점 나선 예제를 그대로 돌려서, 브라우저에서 줌하며 밀도 표면이 진짜 점으로 뚫리는 순간을 관찰하기.

2. xy.pyplot로 기존 Matplotlib 스크립트를 import만 바꿔 이식해보고, 어떤 함수가 아직 미지원인지 spec/matplotlib/compat.md와 대조하기.

3. js/src/45_lod.tsLOD_DIRECT_POINT_BUDGET 값을 바꿔 빌드하면 티어 전환 임계가 어떻게 달라지는지 실험하기(자세한 과제는 §8).

7하드웨어/시스템 요구사항

돌리려면 뭐가 필요한가
항목요구사항
Python3.11 이상 (필수)
런타임 의존성numpy ≥ 1.24, anywidget ≥ 0.9 (단 2개)
브라우저WebGL2 지원 브라우저(요즘 크롬·파폭·사파리 대부분)
GPU통합 그래픽으로도 동작 — 벤치마크는 Apple M5 Pro 기준
메모리1억 점 직접 모드 ≈ 파이썬 5.26 GiB / density 모드 2.58 GiB
정적 내보내기PNG/PDF는 헤드리스 Chromium(픽셀 프로브)이 필요할 수 있음
OSRust 코어는 플랫폼당 cdylib — Linux/macOS/Windows 휠 제공

일반 사용자는 pip install xy만 하면 Rust 코어와 JS 번들이 이미 빌드된 채로 휠에 들어와 있어서 별도 컴파일이 필요 없다. 소스 체크아웃으로 개발할 때만 npm ci && node js/build.mjs(JS 번들)와 cargo build --release(Rust)를 한 번 돌려주면 된다. 데이터 규모가 수천~수십만이면 어떤 노트북에서도 가볍게 돌아가고, 억 단위는 넉넉한 RAM이 필요하다.

8직접 해볼 수 있는 실습 과제

난이도별로 손을 움직여 보는 과제 5개
난이도 ★☆☆ — 입문

1. 1억 점 나선을 그려보고 줌 관찰

pip install xy numpy 후 README의 100M 나선 예제를 실행. 주피터에서 렌더한 뒤 마우스 휠로 확대하면서 밀도 표면 → 개별 점으로 바뀌는 "드릴다운" 순간을 직접 본다. zoom_size_factor·zoom_opacity 값을 바꿔 그 전환을 조절해본다.

난이도 ★☆☆ — 입문

2. Matplotlib 스크립트를 XY로 이식

기존에 있던 plt.plot()/plt.scatter() 스크립트에서 import matplotlib.pyplot as pltimport xy.pyplot as plt로만 바꿔 실행. 되는 것/안 되는 것을 spec/matplotlib/compat.md 매트릭스와 대조해 "미지원 함수 목록"을 정리한다.

난이도 ★★☆ — 중급

3. FastAPI 라이브 드릴다운 예제 뜯어보기

examples/fastapi/live_drilldown.py를 실행해 서버가 팬·줌 요청마다 어떤 페이로드를 되돌려주는지 네트워크 탭으로 관찰. "라이브 호스트가 어떻게 정제된 데이터를 재요청받는지"를 코드로 확인한다.

난이도 ★★☆ — 중급

4. 실전 데이터셋 노트북 재현

examples/real_world/의 Gaia 별 HR 다이어그램(25만 점)이나 NYC 택시 밀도(30만 픽업)를 열어, 공개 소스에서 데이터를 받아 렌더한다. Datashader/Plotly로 같은 데이터를 그려 렌더 시간을 직접 비교한다.

난이도 ★★★ — 고급

5. LOD 임계값 실험 & 벤치 재현

소스를 클론해 js/src/45_lod.tsLOD_DIRECT_POINT_BUDGET을 바꾸고 node js/build.mjs로 재빌드. 티어 전환점이 어떻게 달라지는지 scripts/bench.py(§12 하네스)로 측정한다. 여유가 되면 src/kernels.rs의 M4 데시메이션 경로를 읽고 픽셀 축약이 실제 어떻게 구현됐는지 추적한다.

9관련 기술 심화 학습 로드맵

XY를 제대로 이해하려면 필요한 배경지식을 주차별로
주차주제목표
1주차NumPy & 컬럼형 데이터f32/f64 정밀도 차이, 배열 메모리 레이아웃, 왜 컬럼 저장이 빠른가
2주차Python ↔ C FFIctypes 기초, C ABI, cdylib 만들기, PyO3와의 트레이드오프
3주차Rust 입문소유권·수명, cargo, 릴리스 최적화(LTO), 패닉을 C 경계에서 잡기
4주차WebGL2 기초정점/프래그먼트 셰이더, 버퍼, 인스턴싱, 텍스처(LUT)
5주차시각화 알고리즘M4 데시메이션, 밀도 비닝, 타일 피라미드, LOD
6주차이진 프로토콜오프셋 인코딩, 타입드 배열, anywidget comm, Arrow IPC
7주차웹 통합Reflex 앱 구조, 웹소켓 네임스페이스, 정적 HTML 내보내기
8주차벤치마킹 규율CodSpeed, "정확+안정 프레임" 판정, 재현 가능한 증거 만들기

10핵심 키워드 사전

문서에서 반복된 용어를 한 자리에
용어
LODLevel of Detail. 보이는 픽셀 수에 맞춰 정밀도를 조절하는 렌더 기법
M4 데시메이션픽셀 열마다 Min·Max·First·Last 4점만 남겨 선을 축약(모양은 동일)
density 모드많은 점을 화면 격자의 밀도 표면으로 집계해 그리는 티어
drill / drill-down밀도 표면을 확대하면 그 구간을 재계산해 진짜 점으로 뚫고 내려감
ColumnStore원본 f64 컬럼을 CPU에 보관하는 정본 저장소(호버·선택 시 원행 반환)
C ABI / cdylibRust를 C처럼 호출 가능한 동적 라이브러리로 빌드 → 모든 CPython이 공유
ctypes파이썬 표준 라이브러리로 C 함수를 직접 호출하는 FFI 방식
오프셋 인코딩 f32큰 좌표에서 뷰포트 원점을 빼 작은 상대값으로 만든 뒤 f32로 전송
불변식(invariant)절대 깨지면 안 되는 설계 규칙(예: "JSON 숫자를 배선에 안 태운다")
WebGL2 인스턴싱같은 마커 모양을 한 번 정의하고 위치만 바꿔 수백만 개를 GPU로 찍기
anywidget주피터 위젯을 프레임워크 독립적으로 만드는 표준 — XY의 노트북 표시 경로
pyplot shimMatplotlib API를 흉내내 XY 공개 API로 번역하는 호환 층
design dossier설계·경쟁 리서치·성능 추정·감사 로그를 한데 모은 XY의 단일 진실원 문서

11참고 링크

더 깊이 파고들 곳