이번 교시에는 상태 없이 고정된 화면만 만듭니다. 끝나면 둥근 모서리 카드 안에 "Customers" 제목과 설명이 있는 헤더가 보입니다.
tutorial_261019/ # 프로젝트 루트 (여기서 reflex 명령 실행)
├── rxconfig.py # 앱 이름과 플러그인 설정
├── pyproject.toml / uv.lock # 파이썬 의존성 (uv가 관리)
├── assets/ # 이미지 등 정적 파일 → "/favicon.ico"처럼 참조
├── reflex.lock/ # 화면 쪽 패키지 잠금 파일 (커밋 대상)
├── .web/ # 컴파일된 React 코드 (자동 생성, 수정 금지)
└── tutorial_261019/ # app_name과 같은 이름의 파이썬 패키지
├── __init__.py
└── tutorial_261019.py # 우리가 작업할 파일 (app = rx.App())rxconfig.py는 다음과 같습니다. app_name이 안쪽 폴더 이름과 같아야 Reflex가 앱을 찾습니다.
import reflex as rx
config = rx.Config(
app_name="tutorial_261019",
plugins=[
rx.plugins.SitemapPlugin(),
rx.plugins.TailwindV4Plugin(),
rx.plugins.RadixThemesPlugin(), # 버튼·테이블 등 기본 디자인 제공
],
)tutorial_261019/tutorial_261019.py의 내용을 모두 지우고 아래처럼 시작합니다.
import reflex as rx
def index() -> rx.Component:
return rx.heading("Customers")
app = rx.App()
app.add_page(index, title="Customer Data App")index()는 화면 조각(컴포넌트)을 돌려주는 함수입니다. 페이지 하나 = 함수 하나입니다.app = rx.App()은 모듈 최상단에 반드시 있어야 합니다. Reflex가 이 변수 이름으로 앱을 찾습니다.add_page(index)는 함수 이름이 index이므로 루트 경로 /에 등록됩니다. title은 브라우저 탭 제목입니다.브라우저 확인 — 저장하면 왼쪽 위에 "Customers" 제목 하나만 남습니다. 여백이 없어 화면 모서리에 붙어 있는 것이 정상입니다.
localhost:3000
실행 화면Reflex 화면 코드는 사실상 이 두 규칙이 전부입니다.
size="6", margin="0"처럼 이름=값으로 줍니다.rx.box( # <div>
rx.heading("Customers", size="6"), # 자식 1
rx.badge("2"), # 자식 2
display="flex", # 스타일
gap="12px",
)align-items → align_items, margin-top → margin_top._를 붙입니다. as → as_, type → type_.rx.color("slate", 11)은 Radix 색상 팔레트입니다. 숫자가 클수록 진하고, 다크모드에서도 자동으로 맞춰집니다. 1~2는 배경, 4~6은 테두리, 11~12는 글자에 주로 씁니다.강사 노트 — "HTML 태그를 함수 호출로 바꾼 것"이라고 설명하면 빠르게 이해합니다. rx.box = <div>, rx.text = <p>, rx.heading = <h1>~<h6>. 브라우저 개발자 도구(F12)에서 실제로 만들어진 태그를 보여주세요.
헤더는 왼쪽(제목 + 배지 + 설명)과 오른쪽(버튼)으로 나뉩니다. 버튼은 4교시에 넣고, 지금은 왼쪽만 만듭니다.
def index() -> rx.Component:
return rx.box(
rx.box(
rx.box(
rx.heading("Customers", size="6", as_="h3", margin="0"),
rx.badge("2", variant="soft", color_scheme="gray", radius="full"),
display="flex",
align_items="center",
gap="12px",
),
rx.text(
"Your customer directory and audience breakdown.",
size="2",
color=rx.color("slate", 11),
margin_top="6px",
),
),
display="flex",
align_items="center",
justify_content="space-between",
flex_wrap="wrap",
gap="16px",
padding="24px",
)"2"는 임시 값입니다. 3교시에 State.users.length()로 바꿔 실제 고객 수를 보여줍니다.justify_content="space-between"은 자식들을 양 끝으로 벌립니다. 버튼이 오른쪽 끝에 붙는 이유입니다.flex_wrap="wrap"은 화면이 좁으면 버튼을 다음 줄로 내립니다(모바일 대응).브라우저 확인 — 제목 옆에 회색 둥근 배지(2), 아래에 회색 설명 문구가 보입니다. 아직 카드 테두리는 없습니다.
localhost:3000
실행 화면Your customer directory and audience breakdown.
헤더를 한 번 더 rx.box로 감싸 카드 모양을 만듭니다. 이 바깥 박스가 앱 전체의 틀이 되고, 이후 테이블과 차트가 이 안에 차례로 들어갑니다.
def index() -> rx.Component:
return rx.box(
header, # 2-4에서 만든 헤더 box
# 테이블 (3교시), 차트 (5교시)가 여기에 추가됨
width="100%",
min_width="0",
max_width="64em", # 카드 최대 폭
margin_x="auto", # 가운데 정렬
margin_y="24px",
border=f"1px solid {rx.color('slate', 5)}",
border_radius="16px",
background=rx.color("slate", 1),
overflow="hidden", # 둥근 모서리 밖으로 내용이 새는 것 방지
box_shadow="0 4px 24px rgba(0, 0, 0, 0.03)",
style={
"& *": {"box_sizing": "border-box"},
"& p, & h3": {"text_align": "left"},
},
)style={...}는 키워드 인자로 표현하기 어려운 CSS 선택자를 쓸 때 씁니다. "& *"는 "이 박스 안의 모든 요소"라는 뜻입니다.rx.color(...)를 쓸 수 있습니다. 작은따옴표와 큰따옴표를 섞어 쓰는 데 주의하세요.브라우저 확인 — 헤더가 둥근 모서리 카드 안으로 들어가고, 카드가 화면 가운데에 놓입니다. 브라우저 창을 좁히면 카드 폭이 함께 줄어듭니다.
localhost:3000
실행 화면Your customer directory and audience breakdown.
border_radius를 "4px"와 "32px"로 바꿔 보고 차이를 비교해 보세요.rx.color_mode.button()을 헤더에 추가해 다크모드에서도 색이 자연스럽게 바뀌는지 확인해 보세요.새 교시·새 강의 소식 받기
이 강의에 새 교시가 더해지거나 이어지는 강의가 열리면 이메일로 알려 드려요.
R
ReflexKR
눌러 보며 배우는 파이썬과 Reflex. 모든 예제는 Reflex 0.10.0에서 직접 실행해 확인했습니다.
ReflexKR은 배너 광고 없이 무료로 운영돼요. 도움이 되셨다면 커피 한 잔으로 응원해 주세요.
© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0
질문과 답변
이 교시에서 궁금한 점을 남겨 주세요. 모든 언어 페이지의 질문이 함께 모입니다.