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
동적 렌더링

Auto Scroll

rx.auto_scroll

공식 문서

공방 주문서

고객 상담 채팅창을 만들어 주세요. 새 메시지가 오면 맨 아래로 따라 내려가되, 위로 올려 지난 대화를 읽는 중이면 끌어내리지 않아야 합니다.

rx.auto_scroll은 새 내용이 더해지면 저절로 맨 아래로 스크롤되는 상자(div)입니다. 채팅, 로그, 피드처럼 아래에 계속 쌓이는 내용에서 가장 새로운 것을 늘 보이게 할 때 씁니다. 스크롤 위치를 다루는 코드를 직접 쓸 필요가 없습니다.

Initial message
class AutoScrollBasicState(rx.State):
    messages: list[str] = ["Initial message"]
    count: int = 1

    @rx.event
    def add_message(self):
        self.count += 1
        self.messages = (self.messages + [f"New message #{self.count}"])[-50:]


rx.vstack(
    rx.auto_scroll(
        rx.foreach(
            AutoScrollBasicState.messages,
            lambda message: rx.box(
                message,
                padding="0.5em",
                border_bottom=f"1px solid {rx.color('gray', 4)}",
                width="100%",
            ),
        ),
        height="200px",
        width="300px",
        border=f"1px solid {rx.color('gray', 6)}",
        border_radius="8px",
    ),
    rx.button("Add Message", on_click=AutoScrollBasicState.add_message),
    width="300px",
    align_items="center",
)

Add Message를 누를 때마다 메시지가 더해지고, 상자가 넘치기 시작하면 새 메시지가 보이도록 저절로 내려갑니다.

속성 바꿔 보기

rx.auto_scroll은 rx.el.div를 바탕으로 해서 div의 속성과 스타일을 모두 받습니다. 스크롤 상자이므로 height가 가장 중요합니다. 아래 상자에는 스무 줄이 들어 있는데, 처음부터 마지막 줄(Line 20)이 보입니다. 높이를 줄여 넘치게 만들어도 아래쪽이 보이게 유지됩니다.

속성 바꿔 보기

Line 1

Line 2

Line 3

Line 4

Line 5

Line 6

Line 7

Line 8

Line 9

Line 10

Line 11

Line 12

Line 13

Line 14

Line 15

Line 16

Line 17

Line 18

Line 19

Line 20

height

padding

radius

rx.auto_scroll(
    *[rx.text("Line " + str(i), size="2") for i in range(1, 21)],
    height="160px",
    padding="8px",
    border_radius="8px",
    border=f"1px solid {rx.color('gray', 6)}",
    width="260px",
)
기본으로 overflow="auto"가 걸려 있어, 높이를 넘는 내용은 상자 안에서 스크롤됩니다.
속성값기본값쓰임
heightCSS 길이없음스크롤 상자의 높이. 없으면 내용만큼 늘어나 스크롤이 생기지 않는다
widthCSS 길이없음너비
overflowCSS 값"auto"넘치는 내용 처리. 기본이 스크롤
padding, border, border_radiusCSS 값없음안쪽 여백, 테두리, 모서리
id문자열자동따로 주지 않으면 고유한 id가 자동으로 붙는다
그 밖의 div 속성title, role, on_click …rx.el.div와 같다

언제 쓰나

  • 채팅: 대화창이 늘 최근 메시지를 보이게 합니다.
  • 로그 보기: 새 로그 줄이 생기면 따라 내려갑니다.
  • 피드: 계속 갱신되는 목록에서 새 내용을 보이게 합니다.

동작 방식

내용이 더해질 때 다음 두 경우에만 맨 아래로 내려갑니다.

  1. 사용자가 이미 맨 아래 근처(50픽셀 안)에 있을 때
  2. 전에는 스크롤바가 없었는데 새 내용 때문에 생겼을 때

그래서 사용자가 위로 올려 지난 내용을 읽는 중에는 억지로 끌어내리지 않습니다. 아래 로그 상자를 위로 올린 채 Add 10을 눌러 보세요. 위치가 그대로 있습니다. 다시 맨 아래로 내린 뒤 누르면 따라 내려갑니다.

import random


class AutoScrollLogState(rx.State):
    lines: list[str] = []
    count: int = 0

    @rx.event
    def add(self, n: int):
        levels = ["INFO", "INFO", "INFO", "WARN", "ERROR"]
        new = []
        for _ in range(n):
            self.count += 1
            new.append(f"{self.count:04d} {random.choice(levels)} request handled")
        self.lines = (self.lines + new)[-100:]

    @rx.event
    def clear(self):
        self.lines = []
        self.count = 0


rx.vstack(
    rx.auto_scroll(
        rx.foreach(AutoScrollLogState.lines, lambda line: rx.text(line, size="1", font_family="var(--code-font-family)")),
        height="160px",
        width="100%",
        padding="8px 10px",
        background=rx.color("gray", 2),
        border=f"1px solid {rx.color('gray', 6)}",
        border_radius="8px",
    ),
    rx.hstack(
        rx.button("Add 1", on_click=AutoScrollLogState.add(1), size="1"),
        rx.button("Add 10", on_click=AutoScrollLogState.add(10), size="1", variant="soft"),
        rx.button("Clear", on_click=AutoScrollLogState.clear, size="1", variant="soft", color_scheme="gray"),
    ),
    width="100%",
    max_width="420px",
)

주문서 완성

rx.auto_scroll에 display="flex"와 flex_direction="column"을 주어 말풍선을 세로로 쌓고, 보낸 사람에 따라 rx.cond로 정렬과 색을 바꿉니다. 메시지를 보내면 내 말과 답이 함께 더해지고, 창이 따라 내려갑니다. 위로 올려 읽는 중이면 그대로 둡니다.

Hi! Ask me about your order.
class AutoScrollChatState(rx.State):
    messages: list[dict[str, str]] = [{"who": "bot", "text": "Hi! Ask me about your order."}]

    @rx.event
    def send(self, form_data: dict):
        text = form_data.get("text", "").strip()[:200]
        if not text:
            return
        reply = {"who": "bot", "text": f"Got it: {text}"}
        self.messages = (self.messages + [{"who": "me", "text": text}, reply])[-40:]


rx.vstack(
    rx.auto_scroll(
        rx.foreach(
            AutoScrollChatState.messages,
            lambda m: rx.flex(
                rx.box(
                    m["text"],
                    padding="6px 10px",
                    border_radius="12px",
                    max_width="80%",
                    background=rx.cond(m["who"] == "me", rx.color("indigo", 9), rx.color("gray", 4)),
                    color=rx.cond(m["who"] == "me", "white", rx.color("gray", 12)),
                ),
                justify=rx.cond(m["who"] == "me", "end", "start"),
                width="100%",
            ),
        ),
        display="flex",
        flex_direction="column",
        gap="6px",
        height="240px",
        width="100%",
        padding="10px",
        border=f"1px solid {rx.color('gray', 6)}",
        border_radius="10px",
    ),
    rx.form(
        rx.hstack(
            rx.input(name="text", placeholder="Type a message", flex="1", auto_complete=False),
            rx.button(rx.icon("send", size=16), type="submit", aria_label="Send"),
            width="100%",
        ),
        on_submit=AutoScrollChatState.send,
        reset_on_submit=True,
        width="100%",
    ),
    width="100%",
    max_width="360px",
)

공방 노트

  • rx.auto_scroll(...)은 새 내용이 생기면 맨 아래로 따라가는 div.

  • height를 꼭 준다. overflow="auto"는 기본으로 걸려 있다.

  • 맨 아래 근처(50px)에 있을 때, 또는 스크롤바가 새로 생길 때만 내려간다.

  • 위로 올려 읽는 사용자는 끌어내리지 않는다. 채팅·로그·피드에 알맞다.

← 이전

동적 렌더링 · Foreach

다음 →

미디어 · Image

새 교시·새 강의 소식 받기

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

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

질문과 답변

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

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

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