- Published on
2026년 새로운 파이썬 노트북 스택 — Marimo·Quarto, 그리고 Jupyter 이후의 데이터 워크플로 (Observable·Pluto·Polars·DuckDB까지)
- Authors

- Name
- Youngju Kim
- @fjvbn20031
프롤로그 — Jupyter의 숨은 상태 문제
2026년에도 매주 어딘가에서 같은 장면이 반복된다. 데이터 과학자가 노트북을 동료에게 넘기고, 동료가 "Run All"을 누르면 셀이 다섯 번째에서 폭발한다. 변수가 정의되지 않았다고 한다. 그런데 보낸 사람의 화면에서는 멀쩡히 돈다.
원인은 거의 항상 같다 — **숨은 상태(hidden state)**다. 셀을 위에서 아래로 한 번도 돌리지 않은 채, 중간 셀만 여러 번 실행하다 보면 노트북의 텍스트와 커널의 메모리 상태가 어긋난다. 보낸 사람의 커널에는 df가 살아 있지만, 노트북 파일에는 df를 만드는 셀이 지워져 있다.
이건 Jupyter의 버그가 아니다. 설계 결정이다. Jupyter는 셀을 임의 순서로 실행할 수 있게 해 주는 것이 자산이라고 봤다 — 그게 REPL의 본질이니까. 그러나 그 자유가 협업·재현성·CI에 들어가면 부채가 된다.
"노트북은 1인용 환경에서는 천국이고, 2인 이상의 환경에서는 지옥이다."
2024~2026년에 이 부채를 새 방식으로 풀려는 움직임이 본격화됐다. Marimo는 셀 사이 데이터플로 그래프를 정적으로 분석해서 의존성에 따라 자동으로 다시 실행한다 — 셀 순서가 아니라 데이터 의존성이 진실이다. Quarto는 노트북을 입력으로 받아 HTML·PDF·웹사이트·논문 보조자료로 퍼블리시하는 멀티-언어·멀티-포맷 엔진이다. Observable Framework는 JS-네이티브 노트북을 정적 사이트로 빌드한다. 그 아래의 컴퓨트 레이어도 Pandas에서 Polars·DuckDB로 옮겨가고 있다.
이 글은 그 스택을 깊게 본다 — Jupyter가 무엇을 잘못했고, Marimo는 어떻게 풀었고, Quarto로 어떻게 퍼블리시하고, 언제 여전히 Jupyter를 써야 하는지까지.
1장 · Jupyter의 네 가지 부채
Jupyter (정확히는 IPython 커널 + ipynb JSON + Notebook/Lab UI 조합)는 2014년 이래 데이터 사이언스의 표준 환경이었다. 잘 한 일이 많다 — 출력을 코드 옆에 두고, 인라인 시각화·Markdown·LaTeX를 합쳐서 "실행 가능한 문서"를 만들었다. 그러나 12년이 지나면서 네 가지 부채가 쌓였다.
부채 1 — 숨은 상태
셀을 In[14], In[3], In[27] 순서로 실행해도 노트북 파일에는 그 순서가 남지 않는다. 누군가가 "Run All"을 눌렀을 때 같은 결과가 나온다는 보장이 없다. 진실은 노트북 파일이 아니라 메모리 안에 사는 커널에 있고, 그 커널은 종료되는 순간 사라진다.
부채 2 — 비-diff 가능 (.ipynb는 JSON)
.ipynb는 코드·Markdown·이미지·출력·실행 카운터를 모두 한 JSON 파일에 박아 둔다. PR 리뷰어가 GitHub에서 diff를 열면 base64로 인코딩된 PNG 한 줄이 끝없이 펼쳐진다. nbstripout이나 jupytext 같은 우회책이 필요한 것 자체가 신호다 — 포맷이 git과 본질적으로 안 맞는다.
부채 3 — 재현 불가
위 두 부채가 합쳐지면 재현이 불가능해진다. "이 노트북을 돌렸다"는 말이 "이 환경, 이 순서, 이 데이터로 돌렸다"를 의미하지 않는다. 논문 부록 노트북을 6개월 뒤에 다시 열면 의존성이 깨져 있고, 출력은 코드와 어긋나 있다.
부채 4 — UI 단방향성
Jupyter는 "위→아래" 선형 모델을 가정한다. 데이터 의존성을 보여주는 그래프 뷰가 없다 — 이 셀의 출력이 어디로 흘러가는지, 어떤 셀이 어떤 셀을 부르는지 알려면 인간이 머리로 추적해야 한다. 셀이 50개를 넘으면 사실상 불가능하다.
이 네 부채는 서로를 강화한다. 숨은 상태가 있으니 재현이 안 되고, 재현이 안 되니 diff를 봐도 의미가 없고, diff가 의미가 없으니 협업이 안 된다.
2장 · Marimo — 노트북을 다시 설계하다
Marimo는 2023년 후반에 등장해 2026년 중반 기준 0.10.x 시리즈에 도달한 오픈소스 파이썬 노트북이다. 출발점은 단순하다 — "노트북을 처음부터 다시 설계하면 무엇이 달라질까?"
Marimo의 세 가지 핵심 설계 결정:
결정 1 — .py 파일로 저장
Marimo 노트북은 .ipynb가 아니라 순수 파이썬 파일이다. 각 셀은 데코레이터가 붙은 함수다.
import marimo as mo
app = mo.App()
@app.cell
def __():
import polars as pl
df = pl.read_csv("sales.csv")
return (df,)
@app.cell
def __(df):
summary = df.group_by("region").agg(pl.col("revenue").sum())
return (summary,)
@app.cell
def __(summary):
summary
return ()
if __name__ == "__main__":
app.run()
여기서 두 가지가 일어난다. 첫째, 이 파일은 그냥 파이썬 스크립트로도 돌아간다 — python notebook.py만 치면 끝이다. 둘째, git diff가 의미가 있다. 변수 이름이 바뀌면 diff에 변수 이름이 보인다. base64로 인코딩된 PNG는 어디에도 없다.
결정 2 — 데이터플로 그래프, 셀 순서가 아니라
Marimo는 노트북을 정적으로 분석해 각 셀이 어떤 변수를 정의하고 어떤 변수를 참조하는지 알아낸다. 이게 **방향성 비순환 그래프(DAG)**가 된다. 셀을 실행하면, Marimo는 그 셀에 의존하는 모든 셀을 자동으로 다시 실행한다 — Excel 스프레드시트와 같은 모델이다.
결과: 숨은 상태가 불가능하다. 변수를 새로 할당하면 그 변수를 쓰는 모든 셀이 즉시 갱신된다. 어떤 셀을 지워도, 그 셀이 정의한 변수를 쓰는 셀은 즉시 "정의되지 않음" 오류를 띄운다. "Run All"이 항상 작동하는 노트북 파일과, 메모리 안의 커널 상태가 일치한다.
결정 3 — 노트북-as-앱 모드
Marimo는 두 가지 모드로 같은 파일을 띄울 수 있다:
- 편집 모드 — 셀을 작성·실행하는 일반 노트북.
- 실행 모드 —
marimo run notebook.py로 띄우면, 셀이 숨겨지고 UI 컴포넌트(슬라이더·드롭다운·테이블)만 보이는 인터랙티브 앱이 된다.
UI 컴포넌트는 mo.ui 모듈로 정의한다.
@app.cell
def __(mo):
region = mo.ui.dropdown(
options=["US", "EU", "APAC"],
value="US",
label="Region",
)
region
return (region,)
@app.cell
def __(df, region):
filtered = df.filter(pl.col("region") == region.value)
filtered
return (filtered,)
드롭다운 값이 바뀌면 그 값을 쓰는 셀이 자동으로 다시 실행된다. Streamlit/Gradio 없이 노트북 자체가 앱이 된다.
Marimo가 잘 푸는 추가 문제들
- WASM 배포 — Pyodide를 통해 노트북을 그냥 정적 HTML로 export 할 수 있다. 서버가 필요 없다. 사람들이 브라우저에서 직접 만진다.
- AI 보조 — 셀별 AI completion (모델 비종속)이 내장되어 있다.
- 타입 검사 —
.py파일이라 mypy/pyright가 그냥 동작한다. - 테스트 — 노트북 셀을 pytest로 import해서 테스트할 수 있다.
- 순수 함수 셀 — 각 셀이 명시적 입력·출력을 가진 함수라 단위 테스트가 자연스럽다.
3장 · Jupyter vs Marimo — 같은 작업, 다른 코드
같은 워크플로(데이터 로드 → 필터 → 시각화)를 두 노트북에서 어떻게 표현하는지 보자.
Jupyter 셀들
# Cell 1
import pandas as pd
df = pd.read_csv("sales.csv")
df.head()
# Cell 2
df_us = df[df["region"] == "US"]
df_us.shape
# Cell 3
import matplotlib.pyplot as plt
df_us.groupby("month")["revenue"].sum().plot(kind="bar")
plt.show()
# Cell 4 — 30분 뒤, df 정의를 잊고 다시 쓴다
df = pd.read_csv("sales_v2.csv") # 이전 df_us는 여전히 옛 데이터를 가리킨다!
Cell 4를 실행하고 그래프(Cell 3)를 다시 보면 — df_us가 옛 df를 캡처했기 때문에 그래프가 갱신되지 않는다. 메모리 상태와 코드 상태가 어긋났다. 숨은 상태.
Marimo 셀들
@app.cell
def __():
import polars as pl
df = pl.read_csv("sales.csv")
df
return (df, pl)
@app.cell
def __(df, pl):
df_us = df.filter(pl.col("region") == "US")
df_us
return (df_us,)
@app.cell
def __(df_us):
chart = df_us.group_by("month").agg(pl.col("revenue").sum())
chart
return (chart,)
여기서 첫 셀의 df를 sales_v2.csv로 바꾸면 — Marimo는 df에 의존하는 두 번째 셀, 거기 의존하는 세 번째 셀을 자동으로 다시 실행한다. 그래프가 즉시 갱신된다. 메모리 상태와 코드 상태가 본질적으로 동기화된다.
추가로, Marimo는 같은 변수를 두 셀에서 재정의하는 것을 막는다. "그 변수는 다른 셀에서 이미 정의되어 있다"는 오류를 내고, 작성자에게 둘 중 하나를 고르라고 강요한다. 이게 처음에는 답답하지만, 숨은 상태가 영원히 사라진다.
4장 · Quarto — 노트북을 퍼블리싱 가능한 문서로
Marimo가 "노트북을 다시 설계하기"라면, Quarto는 "노트북을 출판하기"다. Quarto는 RStudio의 RMarkdown 후계자로 2022년에 1.0을 찍었고, 2026년 기준 1.5+에 도달했다. 다국어(Python·R·Julia·Observable JS)·다포맷(HTML·PDF·EPUB·Word·웹사이트·책)을 한 도구로 처리한다.
Quarto 문서의 모양
Quarto 문서는 .qmd 확장자를 쓰고, YAML frontmatter + Markdown + 코드 펜스로 구성된다.
---
title: "2025 Sales Analysis"
author: "Data Team"
date: "2026-05-14"
format:
html:
code-fold: true
toc: true
pdf:
documentclass: article
execute:
echo: true
warning: false
---
## 데이터 로드
이번 분기 매출을 분석한다.
\`\`\`{python}
import polars as pl
df = pl.read_csv("sales.csv")
df.head()
\`\`\`
## 지역별 합계
\`\`\`{python}
df.group_by("region").agg(pl.col("revenue").sum())
\`\`\`
(위 예시에서는 MDX 파서가 헷갈리지 않도록 백틱 펜스를 이스케이프했다. 실제 .qmd 파일에서는 그냥 백틱 세 개를 쓴다.)
이 파일 하나를 quarto render report.qmd --to html로 빌드하면 인터랙티브 HTML이, --to pdf로 빌드하면 LaTeX-품질의 PDF가 나온다. 코드는 실행되고, 출력이 문서에 박힌다.
Quarto의 출력 포맷
- HTML — 검색·테마·인터랙티브 위젯·Mermaid 다이어그램·MathJax.
- PDF (LaTeX) — 학술 논문 수준의 조판.
book클래스로 책도 만든다. - 웹사이트 — 여러
.qmd를 묶어 정적 사이트를 빌드한다 (Jekyll/Hugo와 같은 모델). - 책 — 다챕터 PDF/HTML 책. 실제로 R for Data Science가 Quarto로 빌드된다.
- Reveal.js 슬라이드 — 코드 실행 결과를 슬라이드에 넣는다.
- Word·EPUB — 출판사 워크플로용.
다국어 — Python·R·Julia·Observable JS를 한 파일에서
Quarto는 코드 펜스의 언어 식별자를 보고 적절한 커널을 띄운다. python 펜스는 Jupyter 커널, r 펜스는 knitr, julia 펜스는 IJulia, {ojs} 펜스는 Observable JS 런타임으로 실행된다. 같은 문서 안에서 파이썬으로 데이터를 가공하고, R로 통계 모델을 돌리고, Observable JS로 인터랙티브 차트를 그리는 게 가능하다.
Quarto + Marimo, Quarto + Jupyter
Quarto는 입력으로 .qmd 외에도 Jupyter 노트북(.ipynb), Marimo 노트북을 받는다. 즉 Quarto는 노트북 포맷에 비종속적이다. "Marimo로 작업하고 Quarto로 출판한다"는 워크플로가 자연스럽다.
학술 논문·논문 부록
Quarto는 Journal of Statistical Software 같은 학술지의 공식 템플릿이 있다. APA·IEEE·Nature·Elsevier 스타일을 frontmatter 한 줄로 바꾼다. 인용은 BibTeX 또는 Zotero에서 직접 끌어오고, CSL 스타일로 포맷팅한다. 논문과 그 논문의 분석 코드가 같은 파일에 들어간다 — 재현성의 끝판왕.
5장 · Observable Framework — JS-네이티브 노트북의 진화
Observable은 2018년경 Mike Bostock(d3.js 창시자)이 만든 JS-네이티브 노트북이다. 셀이 반응형으로 묶이고 (Marimo의 영감 원천), 시각화가 일등 시민이다. 그러나 호스팅이 Observable.com에 종속되어 있다는 단점이 있었다.
2024년 발표된 Observable Framework는 이 모델을 정적 사이트 빌더로 가져왔다. .md 파일에 JS 셀을 박고, observable build를 치면 정적 HTML/CSS/JS가 나온다. 호스팅은 Vercel·Netlify·GitHub Pages 어디든 된다.
Observable Framework가 잘하는 영역:
- 데이터 대시보드 — 회사 내부 분석 사이트, KPI 추적, 운영 대시보드.
- 인터랙티브 데이터 스토리텔링 — d3 시각화, 사용자 입력에 반응하는 그래프, 데이터 저널리즘.
- 빌드 타임 데이터 로더 — Python·R·Shell 스크립트로 빌드 시 데이터를 갱신하고, 결과를 정적 자산으로 굳힌다.
Marimo가 "Python 사용자가 인터랙티브를 원할 때"의 답이라면, Observable Framework는 "JS·시각화 중심의 데이터 출판"의 답이다. 둘은 경쟁이라기보다 다른 시장이다.
6장 · Pluto.jl — Julia의 반응형 노트북, 그리고 원조
Pluto.jl은 Julia용 반응형 노트북으로, Marimo의 직접적인 영감 원천이다. 2020년에 처음 등장했고, "셀 사이 데이터플로 그래프 → 자동 재실행" 모델을 노트북 세계에 최초로 도입했다.
Pluto가 제시한 핵심 원칙들:
- 노트북 파일이 진실의 단일 원천이다 — 메모리 안 커널이 아니라 파일이 상태를 정의한다.
- 셀 순서가 의미가 없다 — 파일 어디에 있어도 의존성 그래프로 실행 순서가 결정된다.
- 같은 변수를 두 셀에서 재정의할 수 없다 — 그래프가 모호해지니까.
.jl파일로 저장 — 그냥 Julia 스크립트로도 돈다.
Marimo가 이 모델을 Python 세계로 가져왔고, 그 사이 Pluto는 Julia 데이터 사이언스 커뮤니티(SciML·Plots.jl·DataFrames.jl)와 더 깊이 결합했다. Julia를 쓴다면 Pluto가 사실상 기본 선택이다.
7장 · 새로운 컴퓨트 레이어 — Polars·DuckDB
노트북 UX만 바뀐 게 아니다. 그 아래에서 데이터를 실제로 굴리는 컴퓨트 레이어도 바뀌었다.
Polars — Rust 기반 DataFrame
Polars는 Rust로 작성된 DataFrame 라이브러리로, Apache Arrow를 기본 메모리 포맷으로 쓴다. Pandas 대비:
- 빠르다 — 멀티스레드 기본, 컬럼나 메모리 레이아웃, 쿼리 최적화기.
- lazy evaluation — 쿼리를 빌드하고
.collect()로 한 번에 실행 (Spark·SQL과 같은 모델). - API가 일관적 — Pandas의 누적된 비일관성(
applyvsapplymap, 인덱스 지옥 등) 없음. - 메모리가 작다 — Arrow zero-copy로 같은 데이터를 여러 도구가 공유.
대용량 노트북에서 Polars로 옮기면 5~30배 빨라지는 게 흔하다.
DuckDB — 인-프로세스 OLAP DB
DuckDB는 SQLite의 OLAP(분석) 버전이다. 임베디드, 컬럼나, 단일 노드 분석에 최적화. 파일·Parquet·CSV·JSON·Arrow를 직접 쿼리한다.
노트북에서 DuckDB가 빛나는 순간:
import duckdb
duckdb.sql("""
SELECT region, SUM(revenue)
FROM 'sales/*.parquet'
WHERE date >= '2026-01-01'
GROUP BY region
""").to_df()
Spark 클러스터 없이 노트북에서 100GB Parquet를 직접 쿼리한다. Polars와 DuckDB는 Arrow를 통해 zero-copy로 데이터를 주고받는다 — 같은 파이프라인에서 둘을 섞어도 비용이 없다.
이 컴퓨트 레이어가 Marimo·Quarto 위에 깔리면, 단일 노트북이 처리할 수 있는 데이터 규모가 한 자릿수 GB에서 세 자릿수 GB로 올라간다.
8장 · 비교 매트릭스
| 항목 | Jupyter | Marimo | Quarto | Observable Framework | Pluto.jl |
|---|---|---|---|---|---|
| 언어 | Python (커널 다수) | Python | 다국어 | JS 중심 | Julia |
| 파일 포맷 | .ipynb (JSON) | .py | .qmd | .md | .jl |
| 반응형 실행 | 없음 | 있음 (DAG) | 없음 (출판 도구) | 있음 | 있음 (원조) |
| Git diff | 나쁨 | 좋음 | 좋음 | 좋음 | 좋음 |
| 노트북-as-앱 | 별도 (Voila·Panel) | 내장 | 별도 | 정적 사이트 빌드 | 부분적 |
| 정적 export | HTML (재실행 없음) | HTML/WASM | HTML·PDF·웹사이트·책 | 정적 사이트 | HTML |
| 학습 곡선 | 낮음 | 낮음~중간 | 중간 | 중간 (JS 필요) | 낮음 |
| 생태계 크기 | 거대함 | 성장 중 | 큼 | 시각화 중심 | Julia 중 |
| 대표 사용처 | EDA·교육·연구 | EDA·내부 도구·앱 | 보고서·논문·책·블로그 | 대시보드·데이터 저널리즘 | Julia 과학 컴퓨팅 |
| 라이선스 | BSD-3 | Apache-2.0 | MIT | ISC | MIT |
9장 · 실제 워크플로 시나리오
시나리오 A · 데이터 과학자의 일일 EDA
- 이전: Jupyter Lab + Pandas. 셀을 재실행하다 숨은 상태에 빠진다. 결과는 동료에게 PNG 스크린샷으로 보낸다.
- 이후: Marimo + Polars + DuckDB. 노트북이
.py라 PR로 올린다. 동료가marimo run으로 같은 결과를 즉시 재현한다. 셀에 슬라이더를 박아 "지역 선택" UI를 만들면, 비-데이터 동료도 그걸 직접 만진다.
시나리오 B · 분기 리포트 → 사내 임원진
- 이전: Jupyter로 분석 → PowerPoint 캡처. 다음 분기에 데이터가 갱신되면 캡처를 다시 한다.
- 이후: Quarto 웹사이트. 분기마다 데이터만 갱신하고
quarto render. 결과는 회사 인트라넷에 정적 HTML로 배포. 검색·테마·인쇄용 PDF까지 한 빌드에서 나온다.
시나리오 C · 학술 논문 + 보조자료
- 이전: LaTeX로 논문, 별도
.ipynb로 분석 코드. 6개월 뒤 리뷰어 코멘트가 오면 어느 노트북에서 어느 그림이 나왔는지 찾지 못한다. - 이후: Quarto + Marimo. 논문 본문과 분석 코드가 같은
.qmd파일에.quarto render --to pdf로 LaTeX 출력. 보조자료는 같은 파일을--to html로 빌드. 재현 가능한 논문.
시나리오 D · 회사 내부 데이터 도구
- 이전: Streamlit/Gradio로 짠 별도 앱. 데이터 과학자가 노트북에서 작업하고, 엔지니어가 그것을 앱으로 옮긴다 — 두 번 작성.
- 이후: Marimo 노트북-as-앱. 노트북에
mo.ui컴포넌트를 박고marimo run으로 띄운다. 엔지니어링 핸드오프 없음. 같은 파일이 노트북이자 앱.
시나리오 E · 데이터 저널리즘·인터랙티브 스토리
- Observable Framework. d3.js 시각화·사용자 입력에 반응하는 차트·빌드 타임 데이터 로더(Python으로 데이터 가공 → 정적 JSON으로 굳힘) → 정적 사이트.
시나리오 F · Julia 과학 컴퓨팅
- Pluto.jl. SciML·DifferentialEquations.jl 같은 Julia 생태계가 깊고, 반응형 모델이 시뮬레이션·매개변수 탐색에 잘 맞는다.
10장 · 언제 여전히 Jupyter를 써야 하는가
Marimo·Quarto가 강력하지만, Jupyter가 더 나은 자리는 여전히 있다.
여전히 Jupyter
- 다언어 커널 의존이 강할 때 — Spark·PyTorch Distributed·Wolfram Language 등 특수 커널이 필요한 환경. Jupyter의 커널 프로토콜이 표준이다.
- JupyterHub·Binder 인프라가 이미 있을 때 — 학교·연구소가 운영 중인 시스템을 갈아엎기는 어렵다.
- 빠른 일회용 스크래치 — "5줄짜리 실험" 하나라면 셋업 오버헤드가 작은 Jupyter가 빠르다.
- 교육 — 학생들에게 셀 순서·
In[N]/Out[N]의 멘탈 모델을 가르치는 게 강의 목적인 경우. (다만 2026년에는 점점 Marimo로 가르치는 강의도 늘었다.) - VS Code·Cursor의 통합 노트북 UI —
.ipynb를 그냥 열어서 보는 워크플로가 IDE에 깊이 박혀 있다.
Marimo로 가야 할 신호
- 노트북을 협업 자산으로 쓰고 있다 (PR·리뷰).
- "Run All"이 깨지는 일이 자주 생긴다.
- 내부 도구로 노트북을 배포하고 싶다.
- 비-데이터 동료가 노트북을 만질 일이 있다.
Quarto로 가야 할 신호
- 분석 결과를 정기적으로 외부에 출판한다 (블로그·리포트·논문).
- 같은 콘텐츠를 여러 포맷(HTML·PDF)으로 내야 한다.
- 책·다챕터 문서를 만든다.
- 다국어(Python·R·JS) 분석을 한 문서로 묶고 싶다.
11장 · 마이그레이션 — 어떻게 옮길까
Jupyter → Marimo
Marimo는 marimo convert notebook.ipynb로 자동 변환을 제공한다. 한 번에 깨끗하게 옮기진 않는다 — 같은 변수를 여러 셀에서 재정의하는 등 Jupyter에서 합법이었던 패턴이 Marimo에서는 오류다. 첫 변환 후 30분~한 시간 정도 손볼 각오는 해야 한다.
권장: 새 노트북부터 Marimo로 쓰고, 기존 .ipynb는 그대로 둔다. 한 번에 다 옮기지 말 것.
Jupyter → Quarto
Quarto는 .ipynb를 그대로 입력으로 받는다 — 변환이 사실상 필요 없다. quarto render notebook.ipynb만 치면 된다. 출력 포맷이 늘어나는 게 핵심 가치.
Marimo + Quarto 조합
가장 강력한 조합. Marimo로 작성·인터랙티브 탐색 → 결과를 Quarto로 출판. 둘 다 .py 또는 .ipynb를 입출력으로 쓰니까 파이프라인이 깨끗하다.
12장 · 안티-패턴
이 새 스택에서도 피해야 할 함정이 있다.
안티-패턴 1 — Marimo를 단순 Jupyter 대체품으로 쓰기
Marimo의 진짜 가치는 반응형·.py 저장·노트북-as-앱이다. 그걸 안 쓰고 그냥 셀 단위로 코드 쓰는 도구로만 쓰면, 학습 곡선만 지불하고 이득이 없다. UI 컴포넌트를 박고, 반응형 의존성을 활용하라.
안티-패턴 2 — Quarto 문서에 거대한 분석을 그대로 박기
Quarto 빌드 시간이 폭발한다. 무거운 데이터 가공은 별도 스크립트로 분리하고, Quarto에는 결과 데이터(Parquet/CSV)만 로드하게 한다. 또는 freeze: true로 캐시.
안티-패턴 3 — 노트북을 영원히 노트북으로 두기
Marimo·Quarto가 좋다고 모든 코드를 노트북으로 두는 건 함정이다. 안정적인 데이터 파이프라인은 일반 .py 모듈로 옮기고, 노트북은 탐색·문서·인터페이스 역할로 한정한다. 노트북은 종착지가 아니라 인터페이스다.
안티-패턴 4 — Polars/DuckDB를 안 써보고 Pandas만 고집
데이터가 GB대를 넘으면 Pandas는 메모리·속도 양쪽에서 무너진다. Polars로 옮기는 비용은 일주일 이하다. 그 일주일이 다음 1년의 대기 시간을 절반으로 줄인다.
안티-패턴 5 — Marimo의 변수 재정의 제약을 우회하려 들기
처음에 답답하다고 globals() 해킹으로 우회하지 마라. 그 제약이 숨은 상태를 막는 핵심 메커니즘이다. 답답하면 변수 이름을 새로 짓거나, 셀을 합쳐라.
에필로그 — 노트북의 다음 10년
Jupyter는 2014~2024년 데이터 사이언스 워크플로의 표준이었다. 2026년에 그 표준이 깨지고 있는 게 아니다 — 표준이 분화하고 있다.
- 탐색·내부 도구·앱 → Marimo (또는 Pluto for Julia).
- 출판·논문·책·다포맷 → Quarto.
- JS-네이티브 시각화·정적 사이트 → Observable Framework.
- 빠른 일회용·다언어 커널 → 여전히 Jupyter.
그리고 모두의 아래에 Polars·DuckDB·Arrow가 새 컴퓨트 레이어로 깔린다.
핵심은 노트북이 더는 "코드를 한 번 굴리는 도구"가 아니라는 점이다. 노트북은 재현 가능한 협업 자산(Marimo의 .py), 출판 가능한 문서(Quarto), 인터랙티브 앱(Marimo run mode), 데이터 스토리(Observable)의 네 가지 인터페이스를 한 파일이 모두 제공할 수 있는 시대가 됐다.
노트북은 종착지가 아니라 인터페이스다. 좋은 인터페이스는 모든 독자에게 다른 모양으로 열린다 — 데이터 과학자에게는 코드, 동료에게는 앱, 임원에게는 PDF, 인터넷에게는 정적 사이트.
체크리스트 — 새 노트북 워크플로로 옮길지 결정
- 노트북을 PR로 리뷰하는 일이 있는가? (있으면 Marimo로 가라.)
- "Run All"이 깨진 적이 있는가? (있으면 Marimo로 가라.)
- 결과를 외부에 출판하는가? (있으면 Quarto를 추가하라.)
- 비-데이터 동료가 결과를 직접 만지길 원하는가? (있으면 Marimo 노트북-as-앱.)
- 데이터가 수 GB를 넘는가? (있으면 Polars·DuckDB로 옮겨라.)
- Julia 생태계를 쓰는가? (있으면 Pluto.jl.)
- JS·시각화 중심인가? (있으면 Observable Framework.)
안티-패턴 요약
- Marimo를 그냥 Jupyter 대체품으로만 쓰기 (반응형·앱 모드를 안 쓰면 이득 없음).
- Quarto에 무거운 가공 박기 (별도 스크립트로 분리).
- 노트북을 영원히 노트북으로 두기 (안정화되면 모듈로).
- Polars/DuckDB를 안 써보고 Pandas만 고집 (GB대 이상에서는 무너진다).
- Marimo의 재정의 제약 우회 (숨은 상태가 다시 돌아온다).
다음 글 예고
- 데이터 파이프라인의 새 표준 — Dagster·Prefect·Airflow를 2026년 관점에서 비교. 노트북이 탐색이라면, 파이프라인은 생산이다.
- Polars 깊게 보기 — Pandas에서 옮길 때 알아야 할 표현식 모델·lazy 평가·Streaming engine.
- DuckDB로 단일 노드 100GB Parquet 쿼리하기 — Spark 없는 분석 워크플로.
참고 / References
- Marimo 공식 문서 — https://docs.marimo.io
- Marimo GitHub — https://github.com/marimo-team/marimo
- Quarto 공식 — https://quarto.org
- Quarto GitHub — https://github.com/quarto-dev/quarto-cli
- Observable Framework — https://observablehq.com/framework
- Pluto.jl — https://plutojl.org
- Polars — https://pola.rs
- DuckDB — https://duckdb.org
- "I Don't Like Notebooks" — Joel Grus, JupyterCon 2018 — https://www.youtube.com/watch?v=7jiPeIFXb6U
- "Reactive Notebooks for Python" — Marimo 발표, PyData 2024
- R for Data Science (2nd ed.) — Quarto로 빌드된 표준 교재 — https://r4ds.hadley.nz
- Arrow Columnar Format — https://arrow.apache.org/docs/format/Columnar.html