컴포넌트 공방: 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
rx.clipboard공식 문서
공방 주문서
버그 신고 양식에, 사용자가 화면 캡처를 붙여넣기만 하면 바로 그림이 첨부되는 칸을 만들어 주세요.
rx.clipboard는 붙여넣기(paste) 이벤트를 받아, 붙여넣은 내용을 종류별로 State에 넘깁니다. 글자뿐 아니라 그림 같은 이진 자료도 받습니다.
화면에는 아무것도 그리지 않는 투명한 컴포넌트이고, 감싼 자식에서 일어난 붙여넣기를 듣습니다. Reflex 0.5.6부터 들어 있습니다.
class ClipboardBasicState(rx.State):
items: list[str] = []
@rx.event
def on_paste(self, data: list[tuple[str, str]]):
self.items = [f"{mime_type}: {item[:60]}" for mime_type, item in data]
rx.vstack(
rx.clipboard(
rx.input(placeholder="Copy some text, then paste here"),
on_paste=ClipboardBasicState.on_paste,
),
rx.foreach(ClipboardBasicState.items, lambda line: rx.code(line, size="1")),
width="100%",
max_width="420px",
)rx.clipboard에는 눈에 보이는 속성이 없으므로, 실습대 대신 붙여넣기에 반응하는 예제로 봅니다.
글자를 붙이면 text/plain, 웹 페이지에서 복사한 글을 붙이면 text/html도 함께, 그림을 붙이면 image/png 같은 종류가 들어옵니다.
Paste events: 0
class ClipboardTypesState(rx.State):
count: int = 0
types: list[str] = []
@rx.event
def on_paste(self, data: list[tuple[str, str]]):
self.count += 1
self.types = [mime_type for mime_type, _ in data]
rx.card(
rx.clipboard(
rx.text_area(placeholder="Paste text, an image, or a copied web page", rows="3"),
on_paste=ClipboardTypesState.on_paste,
),
rx.text("Paste events: ", ClipboardTypesState.count, size="2", margin_top="8px"),
rx.flex(rx.foreach(ClipboardTypesState.types, lambda t: rx.badge(t)), spacing="2", wrap="wrap", margin_top="6px"),
max_width="420px",
)| 속성 | 값 | 기본값 | 쓰임 |
|---|---|---|---|
on_paste | 이벤트 핸들러 | 없음 | (MIME 종류, 자료) 튜플의 목록을 받는다 |
targets | 요소 id의 목록 | 자식들, 자식이 없으면 문서 전체 | 붙여넣기를 들을 요소 |
.stop_propagation | 이벤트 동작 | 없음 | 바깥의 붙여넣기 처리기로 전달되지 않게 |
.prevent_default | 이벤트 동작 | 없음 | 입력칸에 실제로 붙여지는 기본 동작을 막는다 |
on_paste가 받는 data는 (mime_type, data) 튜플의 목록입니다. 글자는 그대로 문자열로 오고,
그림 같은 이진 자료는 base64로 인코딩된 data URI(data:image/png;base64,...)로 옵니다. 이 문자열은 rx.image의 src에 바로 넣을 수 있고,
서버에서 바이트가 필요하면 파이썬 urllib.request.urlopen(data_uri).read()로 풀 수 있습니다.
자식 없이 rx.clipboard()만 두면 문서의 paste 이벤트에 붙어서, 페이지 어디에 붙여넣어도 실행됩니다.
이 페이지에 그렇게 두면 다른 예제의 붙여넣기까지 모두 잡으므로, 공식 문서의 예제를 코드로만 보입니다.
class ClipboardPasteState(rx.State):
@rx.event
def on_paste(self, data: list[tuple[str, str]]):
for mime_type, item in data:
yield rx.toast(f"Pasted {mime_type} data: {item}")
def clipboard_example():
return rx.fragment(
rx.clipboard(on_paste=ClipboardPasteState.on_paste), # no children: listens for paste on the whole document
"Paste Content Here",
)붙여넣기를 특정 요소에서만 받으려면 rx.clipboard로 그 요소를 감쌉니다. 바깥에 페이지 전체 처리기가 있다면 .stop_propagation으로 이벤트가 위로 올라가지 않게 합니다.
.prevent_default를 붙이면 입력칸에 글자가 실제로 붙여지지 않습니다. 둘째 입력칸에 글을 붙여 보면 칸이 비어 있습니다.
No image yet. Copy an image (or take a screenshot) and paste above.
class ClipboardImageState(rx.State):
last_image_uri: str = ""
@rx.event
def on_paste(self, data: list[tuple[str, str]]):
for mime_type, item in data:
if mime_type.startswith("image/"):
if len(item) > 2_000_000:
return rx.toast("This image is too large for the demo")
self.last_image_uri = item
break
else:
return rx.toast("Did not find an image in the pasted data")
rx.vstack(
rx.clipboard(
rx.input(placeholder="Paste Image (stop propagation)"),
on_paste=ClipboardImageState.on_paste.stop_propagation,
),
rx.clipboard(
rx.input(placeholder="Paste Image (prevent default)"),
on_paste=ClipboardImageState.on_paste.prevent_default,
),
rx.cond(
ClipboardImageState.last_image_uri != "",
rx.image(src=ClipboardImageState.last_image_uri, alt="Image pasted from clipboard", max_width="240px", border_radius="6px"),
rx.text("No image yet. Copy an image (or take a screenshot) and paste above.", size="2", color_scheme="gray"),
),
width="100%",
max_width="420px",
)targets에 요소의 id를 주면 감싸지 않고도 그 요소만 듣습니다. 자식을 감쌀 때는 Reflex가 자식에게 id를 붙여 targets를 자동으로 채웁니다.
Pasted characters: 0
class ClipboardTargetState(rx.State):
pasted_chars: int = 0
@rx.event
def on_paste(self, data: list[tuple[str, str]]):
self.pasted_chars += sum(len(item) for mime_type, item in data if mime_type == "text/plain")
rx.vstack(
rx.clipboard(on_paste=ClipboardTargetState.on_paste, targets=["clipboard_target_note"]),
rx.text_area(id="clipboard_target_note", placeholder="Only this box is watched", rows="2"),
rx.input(placeholder="This box is not watched"),
rx.text("Pasted characters: ", ClipboardTargetState.pasted_chars, size="2"),
width="100%",
max_width="420px",
)점선 상자를 눌러 초점을 둔 뒤 캡처를 붙이면 그림이 첨부됩니다. 상자는 입력칸이 아니므로 tab_index=0으로 초점을 받게 했고,
.prevent_default.stop_propagation처럼 이벤트 동작을 이어 붙였습니다. 그림은 State에 data URI로 들어가므로 너무 큰 그림은 거릅니다.
Click here, then paste a screenshot (Ctrl + V)
class ClipboardTicketState(rx.State):
shot: str = ""
note: str = ""
@rx.event
def on_paste(self, data: list[tuple[str, str]]):
for mime_type, item in data:
if mime_type.startswith("image/") and len(item) <= 2_000_000:
self.shot = item
return
return rx.toast("Paste a screenshot (an image) here")
@rx.event
def change_note(self, value: str):
self.note = value
@rx.event
def clear_shot(self):
self.shot = ""
rx.card(
rx.heading("Bug report", size="3"),
rx.text_area(
value=ClipboardTicketState.note,
on_change=ClipboardTicketState.change_note,
placeholder="What went wrong?",
rows="2",
margin_y="8px",
),
rx.clipboard(
rx.box(
rx.cond(
ClipboardTicketState.shot != "",
rx.image(src=ClipboardTicketState.shot, alt="Pasted screenshot", max_height="160px"),
rx.text("Click here, then paste a screenshot (Ctrl + V)", size="2", color_scheme="gray"),
),
tab_index=0,
padding="16px",
border=f"2px dashed {rx.color('gray', 7)}",
border_radius="8px",
text_align="center",
),
on_paste=ClipboardTicketState.on_paste.prevent_default.stop_propagation,
),
rx.button("Remove screenshot", on_click=ClipboardTicketState.clear_shot, variant="soft", color_scheme="gray", size="1", margin_top="8px"),
max_width="420px",
)공방 노트
rx.clipboard(자식, on_paste=...)는 자식에서 일어난 붙여넣기를 듣는다. 자식이 없으면 문서 전체.
on_paste는 [(mime_type, data), ...]를 받는다. 이진 자료는 base64 data URI.
data URI는 rx.image의 src에 바로 쓸 수 있다.
.stop_propagation은 바깥 처리기로 가지 않게, .prevent_default는 실제 붙여넣기를 막는다.
targets=[id, ...]로 감싸지 않고 특정 요소만 듣는다.
새 교시·새 강의 소식 받기
이 강의에 새 교시가 더해지거나 이어지는 강의가 열리면 이메일로 알려 드려요.
R
ReflexKR
눌러 보며 배우는 파이썬과 Reflex. 모든 예제는 Reflex 0.10.0에서 직접 실행해 확인했습니다.
ReflexKR은 배너 광고 없이 무료로 운영돼요. 도움이 되셨다면 커피 한 잔으로 응원해 주세요.
© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0
질문과 답변
이 교시에서 궁금한 점을 남겨 주세요. 모든 언어 페이지의 질문이 함께 모입니다.