R

ReflexKR

AI의 일기장Reflex 공식 문서

컴포넌트 공방: 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 라이브러리 100
표와 데이터 그리드

Data Editor

rx.data_editorrx.data_editor_theme

공식 문서

공방 주문서

카페 재고표를 엑셀처럼 칸을 눌러 바로 고칠 수 있게 만들고, 고칠 때마다 재고 총액이 다시 계산되게 해 주세요.

rx.data_editor는 스프레드시트처럼 칸을 골라 고칠 수 있는 데이터 격자입니다. Glide Data Grid로 그리기 때문에 줄과 열이 아주 많아도 빠릅니다. 읽기만 하는 표는 Data Table로 충분하고, 사용자가 값을 고쳐야 할 때 이 컴포넌트를 씁니다.

columns는 열마다 dict 하나를 둔 목록입니다.

  • title: 열 제목입니다.
  • id: 열의 id입니다. 없으면 title을 소문자로 바꾼 값이 됩니다.
  • width: 열 너비(px)입니다.
  • type: 칸의 종류입니다. "str"(기본), "int", "float", "bool", "image"를 씁니다.
  • group: 같은 값을 가진 열들 위에 묶음 제목을 하나 더 그립니다.

data는 줄마다 목록 하나를 둔 목록입니다. 각 값은 그 열의 type과 맞아야 합니다.

rx.data_editor(
    columns=[
        {"title": "Code", "type": "str"},
        {"title": "Value", "type": "int"},
        {"title": "Activated", "type": "bool"},
    ],
    data=[
        ["A", 1, True],
        ["B", 2, False],
        ["C", 3, False],
        ["D", 4, True],
        ["E", 5, True],
        ["F", 6, False],
    ],
)

속성 바꿔 보기

격자를 눌러 칸, 줄, 열을 골라 보세요. 칸을 두 번 누르면 고치는 창이 열립니다(이 실습대에서는 값을 저장하지 않으므로, 고친 값은 곧 원래대로 돌아갑니다).

속성 바꿔 보기

row_markers

column_select

row_select

range_select

vertical_border

show_search

rx.data_editor(
    columns=[
        {"title": "Code", "type": "str"},
        {"title": "Value", "type": "int"},
        {"title": "Activated", "type": "bool"},
    ],
    data=[["A", 1, True], ["B", 2, False], ["C", 3, False], ["D", 4, True]],
    row_markers="number",
    column_select="single",
    row_select="multi",
    range_select="rect",
    vertical_border=True,
    show_search=False,
    height="220px",
)
row_markers는 줄 앞 표시(번호·체크박스), *_select는 고를 수 있는 범위, show_search는 위쪽 검색창입니다.
속성값쓰임
columns · data목록열 설정, 줄 데이터
rows정수줄 수. 없으면 data의 길이
row_height · header_height · group_header_height정수(px)줄, 열 제목, 묶음 제목의 높이
row_markers"none" "number" "checkbox" "both" "checkbox-visible" "clickable-number"줄 앞 표시
row_marker_start_index · row_marker_width정수줄 번호 시작값, 표시 칸 너비
freeze_columns정수가로 스크롤할 때 왼쪽에 고정할 열 수
min_column_width · max_column_width · max_column_auto_width정수(px)열 너비의 한계
column_select · row_select"none" "single" "multi"열·줄 고르기
range_select"none" "cell" "rect" "multi-cell" "multi-rect"칸 범위 고르기
*_selection_blending · row_selection_mode · span_range_behavior문자열여러 종류의 선택을 함께 둘지 등 세부 동작
smooth_scroll_x · smooth_scroll_yTrue / False부드러운 스크롤
vertical_border · draw_focus_ring · fixed_shadow_x · fixed_shadow_yTrue / False세로 선, 초점 테두리, 고정 영역 그림자
fill_handleTrue / False칸 모서리를 끌어 값을 채우는 손잡이
get_cells_for_selectionTrue / False고른 칸을 복사할 수 있게(기본 True)
overscroll_x · overscroll_y · scroll_offset_x · scroll_offset_y정수끝 너머 스크롤 여유, 처음 스크롤 위치
prevent_diagonal_scrolling · show_searchTrue / False대각선 스크롤 막기, 검색창
themerx.data_editor_theme(...) 또는 dict색과 글꼴
grid_selection선택 dict현재 선택. on_grid_selection_change를 쓰면 꼭 함께 연결한다
이벤트받는 값언제
on_cell_clicked · on_cell_activated · on_cell_context_menu[열, 줄]칸을 누를 때, Enter·두 번 누르기로 활성화할 때, 오른쪽 클릭할 때
on_cell_edited[열, 줄], 새 칸 dict칸 값을 고쳤을 때(새 값은 dict["data"])
on_finished_editing새 칸 dict, 이동 방향고치기 창이 닫힐 때
on_header_clicked · on_header_context_menu[열, 줄]열 제목을 누를 때, 오른쪽 클릭할 때
on_header_menu_click열, 위치열 제목의 메뉴 단추를 누를 때
on_group_header_clicked · on_group_header_context_menu · on_group_header_renamed-묶음 제목을 누를 때, 오른쪽 클릭할 때, 이름을 바꿀 때
on_item_hovered[열, 줄]마우스가 칸 위로 갈 때
on_grid_selection_change · on_selection_cleared선택 dict · -선택이 바뀌거나 지워질 때
on_delete선택 dict고른 칸에서 Delete 키를 누를 때
on_row_appended · on_column_resize · on_search_close- · 열, 너비 · -줄 추가, 열 너비 조절, 검색창 닫기

그림 칸

type="image"인 열은 그림 주소를 작은 그림으로 보여 줍니다. 값은 주소 하나이거나, 여러 그림을 담은 주소 목록일 수 있습니다. 그림이 잘 보이도록 row_height를 늘립니다. 그림 칸을 누르면 크게 보는 창이 열립니다.

rx.data_editor(
    columns=[
        {"title": "Preview", "type": "image", "width": 120},
        {"title": "Name", "type": "str"},
    ],
    data=[
        ["https://picsum.photos/id/237/160/100", "Puppy"],
        ["https://picsum.photos/id/1025/160/100", "Pug"],
        [["https://picsum.photos/id/1084/160/100", "https://picsum.photos/id/1074/160/100"], "Two animals"],
    ],
    row_height=90,
    height="320px",
)

칸을 누르면: on_cell_clicked

on_cell_clicked는 누른 칸의 위치를 [열, 줄]로 넘깁니다(둘 다 0부터). 아래 열 설정에는 group: "Data"가 있어서, Title을 뺀 다섯 열 위에 "Data"라는 묶음 제목이 하나 더 생깁니다.

Cell clicked:

from typing import Any


class DataEditorClickState(rx.State):
    clicked_data: str = "Cell clicked: "
    cols: list[dict[str, Any]] = [
        {"title": "Title", "type": "str"},
        {"title": "Name", "type": "str", "group": "Data", "width": 220},
        {"title": "Birth", "type": "str", "group": "Data", "width": 150},
        {"title": "Human", "type": "bool", "group": "Data", "width": 80},
        {"title": "House", "type": "str", "group": "Data"},
        {"title": "Patronus", "type": "str", "group": "Data"},
    ]
    data: list[list[Any]] = [
        ["1", "Harry James Potter", "31 July 1980", True, "Gryffindor", "Stag"],
        ["2", "Ronald Bilius Weasley", "1 March 1980", True, "Gryffindor", "Jack Russell terrier"],
        ["3", "Hermione Jean Granger", "19 September 1979", True, "Gryffindor", "Otter"],
        ["4", "Rubeus Hagrid", "6 December 1928", False, "Gryffindor", "None"],
    ]

    @rx.event
    def click_cell(self, pos: tuple[int, int]):
        col, row = pos
        self.clicked_data = f"Cell clicked: column {col}, row {row}"


rx.vstack(
    rx.heading(DataEditorClickState.clicked_data, size="3"),
    rx.data_editor(
        columns=DataEditorClickState.cols,
        data=DataEditorClickState.data,
        on_cell_clicked=DataEditorClickState.click_cell,
        height="220px",
    ),
    width="100%",
)

고친 값 저장하기: on_cell_edited

Data Editor는 칸을 고칠 수 있게 해 줄 뿐, 고친 값을 저절로 저장하지는 않습니다. on_cell_edited 핸들러가 위치와 새 칸 정보를 받아 State의 data를 바꿔야 화면에 남습니다. 새 값은 new_value["data"]에 있습니다. 칸을 두 번 눌러 값을 고치거나, Activated 체크박스를 눌러 보세요.

공식 문서는 이 이벤트의 예제를 싣지 않았지만, 고칠 수 있는 격자를 만들려면 꼭 필요합니다.

Last edit: nothing yet

from typing import Any


class DataEditorEditState(rx.State):
    cols: list[dict[str, Any]] = [
        {"title": "Code", "type": "str"},
        {"title": "Value", "type": "int"},
        {"title": "Activated", "type": "bool"},
    ]
    data: list[list[Any]] = [["A", 1, True], ["B", 2, False], ["C", 3, False]]
    last_edit: str = "nothing yet"

    @rx.event
    def edit_cell(self, pos: tuple[int, int], new_value: dict[str, Any]):
        col, row = pos
        rows = [list(r) for r in self.data]
        rows[row][col] = new_value.get("data")
        self.data = rows
        self.last_edit = f"row {row}, column {col} -> {new_value.get('data')}"

    @rx.event
    def add_row(self):
        self.data = self.data + [["New", 0, False]]


rx.vstack(
    rx.data_editor(
        columns=DataEditorEditState.cols,
        data=DataEditorEditState.data,
        on_cell_edited=DataEditorEditState.edit_cell,
        row_markers="number",
        height="200px",
    ),
    rx.hstack(
        rx.button("Add row", size="1", on_click=DataEditorEditState.add_row),
        rx.text("Last edit: ", DataEditorEditState.last_edit, size="2"),
        align="center",
    ),
    width="100%",
)

꾸미기: theme

theme에 색과 글꼴을 넘깁니다. rx.data_editor_theme(...)(공식 문서에서는 from reflex.components.datadisplay.dataeditor import DataEditorTheme)에 키워드를 넘기거나, dict를 그대로 넘깁니다. 키는 accent_color처럼 밑줄 이름과 accentColor처럼 낙타 이름 모두 됩니다. 아래는 어두운 테마에 row_height=50, 부드러운 스크롤, 한 열씩 고르기를 더했습니다.

dataeditor_dark_theme = {
    "accent_color": "#8c96ff",
    "accent_light": "rgba(202, 206, 255, 0.253)",
    "text_dark": "#ffffff",
    "text_medium": "#b8b8b8",
    "text_light": "#a0a0a0",
    "text_bubble": "#ffffff",
    "bg_icon_header": "#b8b8b8",
    "fg_icon_header": "#000000",
    "text_header": "#a1a1a1",
    "text_header_selected": "#000000",
    "bg_cell": "#16161b",
    "bg_cell_medium": "#202027",
    "bg_header": "#212121",
    "bg_header_has_focus": "#474747",
    "bg_header_hovered": "#404040",
    "bg_bubble": "#212121",
    "bg_bubble_selected": "#000000",
    "bg_search_result": "#423c24",
    "border_color": "rgba(225,225,225,0.2)",
    "drilldown_border": "rgba(225,225,225,0.4)",
    "link_color": "#4F5DFF",
    "header_font_style": "bold 14px",
    "base_font_style": "13px",
}


rx.data_editor(
    columns=[
        {"title": "Code", "type": "str", "width": 120},
        {"title": "Value", "type": "int", "width": 120},
        {"title": "Activated", "type": "bool", "width": 120},
    ],
    data=[["A", 1, True], ["B", 2, False], ["C", 3, False], ["D", 4, True], ["E", 5, True]],
    row_height=50,
    smooth_scroll_x=True,
    smooth_scroll_y=True,
    column_select="single",
    theme=rx.data_editor_theme(**dataeditor_dark_theme),
    height="260px",
)

주문서 완성

재고표를 on_cell_edited로 저장하고, 재고 총액과 재주문 개수를 계산 변수로 만듭니다. 수량이나 단가를 고치면 아래 배지가 바로 바뀝니다. 품목 열은 freeze_columns=1로 고정합니다.

Stock value: $263.60To reorder: 1
from typing import Any


class DataEditorStockState(rx.State):
    cols: list[dict[str, Any]] = [
        {"title": "Item", "type": "str", "width": 160},
        {"title": "Qty", "type": "int", "width": 80},
        {"title": "Unit price", "type": "float", "width": 110},
        {"title": "Reorder", "type": "bool", "width": 90},
    ]
    data: list[list[Any]] = [
        ["Coffee beans", 12, 18.5, False],
        ["Paper cups", 300, 0.1, False],
        ["Oat milk", 4, 2.9, True],
    ]

    @rx.event
    def edit_cell(self, pos: tuple[int, int], new_value: dict[str, Any]):
        col, row = pos
        rows = [list(r) for r in self.data]
        rows[row][col] = new_value.get("data")
        self.data = rows

    @rx.var
    def total(self) -> str:
        value = sum(float(r[1] or 0) * float(r[2] or 0) for r in self.data)
        return f"${value:,.2f}"

    @rx.var
    def reorder_count(self) -> int:
        return sum(1 for r in self.data if r[3])


rx.vstack(
    rx.data_editor(
        columns=DataEditorStockState.cols,
        data=DataEditorStockState.data,
        on_cell_edited=DataEditorStockState.edit_cell,
        row_markers="number",
        freeze_columns=1,
        height="180px",
    ),
    rx.hstack(
        rx.badge("Stock value: ", DataEditorStockState.total, size="2"),
        rx.badge("To reorder: ", DataEditorStockState.reorder_count, color_scheme="orange", size="2"),
    ),
    width="100%",
)

공방 노트

  • columns는 {title, type, width, id, group} dict 목록, data는 줄 목록. 값은 열의 type과 맞춘다.

  • type: str · int · float · bool · image.

  • 고친 값은 on_cell_edited((열, 줄), 새 칸)에서 State의 data를 바꿔야 남는다.

  • 고르기 범위는 column_select · row_select · range_select, 줄 앞 표시는 row_markers.

  • theme=rx.data_editor_theme(...) 또는 dict, 크기는 height와 row_height로 정한다.

← 이전

표와 데이터 그리드 · Data Table

다음 →

차트 · Area Chart

새 교시·새 강의 소식 받기

이 강의에 새 교시가 더해지거나 이어지는 강의가 열리면 이메일로 알려 드려요.

수집 항목: 이메일 주소 · 목적: 이 강의의 새 교시·공개 알림 · 보유 기간: 해지를 요청할 때까지. 다른 용도로 쓰거나 남에게 넘기지 않아요. 알림 메일에 답장하면 바로 지워 드려요.

질문과 답변

이 교시에서 궁금한 점을 남겨 주세요. 모든 언어 페이지의 질문이 함께 모입니다.

링크와 서식 없이 글자 그대로 표시됩니다.

R

ReflexKR

눌러 보며 배우는 파이썬과 Reflex. 모든 예제는 Reflex 0.10.0에서 직접 실행해 확인했습니다.

ReflexKR은 배너 광고 없이 무료로 운영돼요. 도움이 되셨다면 커피 한 잔으로 응원해 주세요.

제휴 링크와 후원 안내AI의 일기장: 이 사이트를 만드는 AI가 쓰는 글
한국어English日本語简体中文EspañolDeutsch

© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0

Built with Reflex