컴포넌트 공방: Reflex 라이브러리 100
·
강의 개요
레이아웃
·
Box
·
Flex
·
Stack
·
Grid
·
Container
·
Section
·
Center
·
Spacer
·
Separator
·
Card
·
Inset
·
Aspect Ratio
·
Fragment
타이포그래피
·
Text
·
Heading
·
Link
·
Code
·
Markdown
·
Blockquote
·
Quote
·
Strong
·
Em
·
Kbd
폼
·
Button
·
Input
·
Text Area
·
Checkbox
·
Switch
·
Radio Group
·
Select
·
Slider
·
Form
·
Upload
데이터 표시
·
Badge
·
Avatar
·
Icon
·
Callout
·
List
·
Data List
·
Code Block
·
Progress
·
Spinner
·
Scroll Area
·
Moment
펼침과 전환
·
Tabs
·
Accordion
·
Segmented Control
오버레이
·
Tooltip
·
Popover
·
Hover Card
·
Dialog
·
Alert Dialog
·
Drawer
·
Dropdown Menu
·
Context Menu
·
Toast
동적 렌더링
·
Cond
·
Match
·
Foreach
·
Auto Scroll
미디어
·
Image
·
Audio
·
Video
표와 데이터 그리드
·
Table
·
Data Table
·
Data Editor
차트
·
Area Chart
·
Bar Chart
·
Line Chart
·
Composed Chart
·
Pie Chart
·
Radar Chart
·
Radial Bar Chart
·
Scatter Chart
·
Funnel Chart
·
Treemap
·
Sankey Chart
·
Error Bar
차트 부품
·
Axis
·
Cartesian Grid
·
Chart Tooltip
·
Legend
·
Label
·
Reference
·
Brush
다른 차트 라이브러리
·
Plotly
·
Pyplot
HTML 요소
·
HTML
·
HTML Text
·
HTML Layout
·
HTML Forms
·
HTML Media
·
HTML Tables
·
SVG
그 밖의 도구
·
Theme
·
Skeleton
·
Clipboard
·
Html Embed
·
Script
·
Memo
reflex_pyplot.pyplot공식 문서
공방 주문서
연구실에서 쓰던 matplotlib 그림 코드를 그대로 웹 화면에 올리고, 제품을 고르면 그림이 바뀌게 해 주세요.
pyplot은 Matplotlib 그림을 Reflex 화면에 보여 주는 컴포넌트입니다. 별도 패키지 reflex-pyplot에 들어 있습니다. matplotlib.pyplot으로 만든 Figure를 넘기면 브라우저에 그려 주므로, Flask 경로나 이미지 base64 변환 같은 작업이 필요 없습니다.
이 페이지의 예제는 코드로만 보입니다. 이 사이트에는 matplotlib과 reflex-pyplot이 설치되어 있지 않기 때문입니다. 아래 코드를 내 앱에서 실행하려면 먼저 두 패키지(예제에 따라 numpy도)를 설치해야 합니다.
matplotlib.pyplot은 Matplotlib을 MATLAB처럼 쓰게 해 주는 함수 모음입니다. plt.plot, plt.scatter, plt.bar 같은 호출이 선, 막대, 글자, 범례를 하나씩 그림에 더합니다. 스크립트에서는 마지막에 plt.show()로 창을 띄우지만, Reflex 앱에서는 Figure를 pyplot 컴포넌트에 넘기고, State가 바뀌면 다시 그려집니다.
이미 Jupyter 노트북, 연구 스크립트, 데이터 파이프라인에 matplotlib 코드가 있다면 다른 차트 라이브러리로 옮기지 않고 그대로 웹 앱에 씁니다.
막대·선·원 같은 일반 업무용 차트는 Reflex에 들어 있는 Recharts 차트(rx.recharts)가, 확대·회전이 되는 대화형·3D 그림은 rx.plotly가 더 잘 맞습니다.
reflex-pyplot을 설치하면 matplotlib도 필요합니다. 아래 예제 몇 개는 numpy도 씁니다.
pip install reflex-pyplot
# in a project that uses uv
uv add reflex-pyplotfrom reflex_pyplot import pyplot으로 가져와, 그림(Figure)을 첫 번째 자식으로 넘깁니다. 화면에는 이미지로 그려지므로 alt(대체 글자), loading, decoding 같은 이미지 속성과 width, height를 함께 줍니다.
import matplotlib.pyplot as plt
import numpy as np
import reflex as rx
from reflex_pyplot import pyplot
def create_contour_plot():
X, Y = np.meshgrid(np.linspace(-3, 3, 256), np.linspace(-3, 3, 256))
Z = (1 - X / 2 + X**5 + Y**3) * np.exp(-(X**2) - Y**2)
levels = np.linspace(Z.min(), Z.max(), 7)
fig, ax = plt.subplots()
ax.contourf(X, Y, Z, levels=levels)
plt.close(fig)
return fig
def pyplot_simple_example():
return rx.card(
pyplot(
create_contour_plot(),
alt="Filled contour plot of a two-dimensional function",
loading="lazy",
decoding="async",
width="100%",
height="400px",
),
bg_color="#ffffff",
width="100%",
)그림을 만든 뒤에는 반드시 plt.close(fig)로 닫습니다. 닫지 않으면 서버가 그림을 계속 붙잡고 있어 메모리가 늘어납니다. 그림 색은 Matplotlib이 정하므로, 어두운 테마에서도 흰 바탕이 보이도록 rx.card(bg_color="#ffffff")로 감쌌습니다.
가장 흔한 그림입니다. 스크립트에서처럼 plt.subplots()와 ax.plot()으로 만들고 그림을 pyplot에 넘깁니다.
import matplotlib.pyplot as plt
import numpy as np
import reflex as rx
from reflex_pyplot import pyplot
def create_line_plot():
x = np.linspace(0, 10, 100)
fig, ax = plt.subplots()
ax.plot(x, np.sin(x), label="sin(x)")
ax.plot(x, np.cos(x), label="cos(x)")
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.legend()
plt.close(fig)
return fig
def pyplot_line_example():
return rx.card(
pyplot(
create_line_plot(),
alt="Sine and cosine curves from zero to ten",
loading="lazy",
decoding="async",
width="100%",
height="400px",
),
bg_color="#ffffff",
width="100%",
)ax.bar()에 범주와 값을 넘기는 것 말고는 같은 방식입니다.
import matplotlib.pyplot as plt
import reflex as rx
from reflex_pyplot import pyplot
def create_bar_chart():
fruits = ["apples", "oranges", "bananas", "pears"]
counts = [23, 17, 35, 29]
fig, ax = plt.subplots()
ax.bar(fruits, counts, color="#4e79a7")
ax.set_ylabel("count")
ax.set_title("Fruit inventory")
plt.close(fig)
return fig
def pyplot_bar_example():
return rx.card(
pyplot(
create_bar_chart(),
alt="Fruit inventory: apples 23, oranges 17, bananas 35, pears 29",
loading="lazy",
decoding="async",
width="100%",
height="400px",
),
bg_color="#ffffff",
width="100%",
)임의의 점을 찍는 산점도에, 다시 섞기 버튼과 점 개수 슬라이더를 붙입니다. 그림은 @rx.var 계산 값이 만들므로, State 값이 바뀌면 다시 그려집니다. 이벤트에 throttle=500을 주어 0.5초에 한 번만 다시 그리게 했습니다.
Matplotlib 그림의 색은 앱 테마를 따르지 않습니다. 그래서 밝은 그림과 어두운 그림을 둘 다 만들고, rx.color_mode_cond로 지금 모드에 맞는 쪽을 보입니다.
import random
import matplotlib.pyplot as plt
import numpy as np
import reflex as rx
from matplotlib.figure import Figure
from reflex_pyplot import pyplot
def create_plot(theme: str, plot_data: tuple, scale: list):
bg_color, text_color = ("#1e1e1e", "white") if theme == "dark" else ("white", "black")
grid_color = "#555555" if theme == "dark" else "#cccccc"
fig, ax = plt.subplots(facecolor=bg_color)
ax.set_facecolor(bg_color)
for (x, y), color in zip(plot_data, ["#4e79a7", "#f28e2b"]):
ax.scatter(x, y, c=color, s=scale, label=color, alpha=0.6, edgecolors="none")
ax.legend(loc="upper right", facecolor=bg_color, edgecolor="none", labelcolor=text_color)
ax.grid(True, color=grid_color)
ax.tick_params(colors=text_color)
for spine in ax.spines.values():
spine.set_edgecolor(text_color)
for item in [ax.xaxis.label, ax.yaxis.label, ax.title]:
item.set_color(text_color)
plt.close(fig)
return fig
class PyplotState(rx.State):
num_points: int = 25
plot_data: tuple = tuple(np.random.rand(2, 25) for _ in range(2))
scale: list = [random.uniform(0, 100) for _ in range(25)]
@rx.event(temporal=True, throttle=500)
def randomize(self):
self.plot_data = tuple(np.random.rand(2, self.num_points) for _ in range(2))
self.scale = [random.uniform(0, 100) for _ in range(self.num_points)]
@rx.event(temporal=True, throttle=500)
def set_num_points(self, num_points: list[int | float]):
self.num_points = int(num_points[0])
yield PyplotState.randomize()
@rx.var
def fig_light(self) -> Figure:
return create_plot("light", self.plot_data, self.scale)
@rx.var
def fig_dark(self) -> Figure:
return create_plot("dark", self.plot_data, self.scale)
def pyplot_example():
return rx.vstack(
rx.card(
rx.color_mode_cond(
pyplot(PyplotState.fig_light, alt="Scatter plot of the current randomized points", width="100%", height="100%"),
pyplot(PyplotState.fig_dark, alt="Scatter plot of the current randomized points", width="100%", height="100%"),
),
rx.hstack(
rx.button("Randomize", on_click=PyplotState.randomize),
rx.text("Number of Points:"),
rx.slider(default_value=25, min=10, max=100, on_value_commit=PyplotState.set_num_points),
width="100%",
),
width="100%",
),
justify_content="center",
align_items="center",
width="100%",
)공식 문서 예제의 슬라이더는 min_=10이라고 적혀 있지만, Reflex 0.10의 rx.slider에서 그 이름은 최솟값이 아니라 CSS 스타일로 들어갑니다. 위 코드는 min=10으로 고쳤습니다. 또 이 예제는 numpy 배열을 State에 담는데, 실제 앱에서는 State에 리스트처럼 단순한 값을 두고 그림을 만들 때 배열로 바꾸는 편이 안전합니다.
웹 페이지에 Matplotlib 그림을 어떻게 보이나요? 평소처럼 그림을 만들고 그 Figure를 pyplot 컴포넌트에 넘깁니다. Flask, REST 경로, base64 변환은 필요 없습니다.
Matplotlib 그림을 대화형으로 만들 수 있나요? 네. State에 기대는 rx.var 안에서 그림을 만들고, 버튼·슬라이더 같은 이벤트로 State를 바꾸면 그림이 저절로 다시 그려집니다(위의 State 예제).
plt.show()를 불러야 하나요? 아니요. plt.show()는 데스크톱 창을 띄우는 함수라서 웹 앱에서는 쓰지 않습니다. 그림을 돌려주고 plt.close(fig)로 닫습니다.
pyplot은 Matplotlib 그림 하나를 보여 줍니다. 따로 정의된 속성이나 이벤트는 없고, 모든 컴포넌트에 있는 기본 이벤트(on_click, on_mount 등)를 받습니다.
| 인자 | 값 | 쓰임 |
|---|---|---|
| 첫 번째 자식 | matplotlib.figure.Figure 또는 그것을 돌려주는 State 값 | 보여 줄 그림 |
alt · loading · decoding | 문자열 | 이미지 대체 글자, 늦게 불러오기, 비동기 해독 |
width · height | CSS 크기 | 그림이 차지하는 크기 |
State에는 고른 제품 이름만 두고, 계산 값이 그 제품의 막대 그림을 만듭니다. 이 코드도 reflex-pyplot과 matplotlib을 설치한 앱에서 실행합니다.
import matplotlib.pyplot as plt
import reflex as rx
from matplotlib.figure import Figure
from reflex_pyplot import pyplot
MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
SALES = {"Chairs": [32, 41, 38, 52, 61, 58], "Tables": [12, 15, 21, 19, 24, 30]}
class PyplotReportState(rx.State):
product: str = "Chairs"
@rx.event
def set_product(self, value: str):
self.product = value
@rx.var
def figure(self) -> Figure:
fig, ax = plt.subplots(figsize=(6, 3))
ax.bar(MONTHS, SALES[self.product], color="#4e79a7")
ax.set_title(f"{self.product} sales")
ax.set_ylabel("units")
fig.tight_layout()
plt.close(fig)
return fig
def pyplot_report():
return rx.vstack(
rx.select(["Chairs", "Tables"], value=PyplotReportState.product, on_change=PyplotReportState.set_product),
rx.card(
pyplot(PyplotReportState.figure, alt="Monthly sales of the selected product", width="100%"),
bg_color="#ffffff",
width="100%",
),
width="100%",
)공방 노트
pip install reflex-pyplot (matplotlib 필요). from reflex_pyplot import pyplot.
pyplot(fig, alt=…, width=…)처럼 Figure를 첫 번째 자식으로 넘긴다. plt.show()는 쓰지 않는다.
그림을 만든 뒤 plt.close(fig)로 꼭 닫는다.
@rx.var 계산 값이 Figure를 돌려주면 State가 바뀔 때 다시 그려진다.
색은 테마를 따르지 않으므로 color_mode_cond로 밝은·어두운 그림을 나눈다.
새 교시·새 강의 소식 받기
이 강의에 새 교시가 더해지거나 이어지는 강의가 열리면 이메일로 알려 드려요.
R
ReflexKR
눌러 보며 배우는 파이썬과 Reflex. 모든 예제는 Reflex 0.10.0에서 직접 실행해 확인했습니다.
ReflexKR은 배너 광고 없이 무료로 운영돼요. 도움이 되셨다면 커피 한 잔으로 응원해 주세요.
© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0
질문과 답변
이 교시에서 궁금한 점을 남겨 주세요. 모든 언어 페이지의 질문이 함께 모입니다.