Skip to content

n-y-kim/pynecone-play

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

12 Commits
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Test repo for pynecone! ๐ŸŒฒ ๊ณต์‹ ๋ฌธ์„œ ๋ฒˆ์—ญํ•˜๋ฉด์„œ ๋„์ ๋„์  ํ…Œ์ŠคํŠธ

๐ŸŒฑ Table of contents ๐ŸŒฑ

Getting Started

Introduction

ํŒŒ์ธ์ฝ˜(Pynecone)์€ ์›น์•ฑ์„ ๋นŒ๋“œํ•˜๊ณ  ๋ฐฐํฌํ•˜๊ธฐ ์œ„ํ•œ ํ’€์Šคํƒ ํ”„๋ ˆ์ž„์›Œํฌ๋‹ค.

Motivation

ํŒŒ์ธ์ฝ˜์€ ์•„๋ž˜์˜ ๋ชฉํ‘œ๋“ค์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋งŒ๋“ค์–ด์กŒ๋‹ค:

  • ์ˆœ์ˆ˜ Python
    ๋ชจ๋“  ๊ฒƒ์— ํŒŒ์ด์ฌ์„ ์“ธ ๊ฒƒ. ์ƒˆ๋กœ์šด ์–ธ์–ด๋ฅผ ๋ฐฐ์›Œ์•ผ ํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ๊ฑฑ์ •์€ ํ•  ํ•„์š” ์—†๋‹ค.
  • ๋ฐฐ์šฐ๊ธฐ ์‰ฌ์šธ ๊ฒƒ
    ๋ช‡ ๋ถ„ ์•ˆ์— ๋ณธ์ธ๋งŒ์˜ ์ƒˆ๋กœ์šด ์•ฑ์„ ๋งŒ๋“ค๊ณ  ๊ณต์œ ํ•˜์ž. ์–ด๋– ํ•œ ์›น ๊ฐœ๋ฐœ ๊ฒฝํ—˜๋„ ํ•„์š” ์—†๋‹ค.
  • ์™„๋ฒฝํ•œ ์œ ๋™์„ฑ
    ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์›น ํ”„๋ ˆ์ž„์›Œํฌ๋“ค์ฒ˜๋Ÿผ ์œ ๋™์ ์ธ ์„ฑ๋Šฅ์„ ์œ ์ง€ํ•  ๊ฒƒ. ํŒŒ์ธ์ฝ˜์€ ์‹œ์ž‘ํ•˜๊ธฐ ๋งค์šฐ ์‰ฝ์ง€๋งŒ, ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ ๋ฐ ์˜ˆ์ œ๋ฅผ ๋งŒ๋“ค์–ด ๋‚ผ ์ˆ˜ ์žˆ๋Š” ํŒŒ์›Œํ’€ํ•จ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.
  • ๋ฐฐํ„ฐ๋ฆฌ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์„ ๊ฒƒ(์˜์—ญ: ๋ชจ๋“  ๊ฒƒ์„ ๊ฐ–์ถœ ๊ฒƒ)
    ๋‹ค๋ฅธ ๋‹ค์–‘ํ•œ ์™ธ๋ถ€ ํˆด์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋…ธ๋ ฅํ•  ํ•„์š” ์—†๋‹ค. ํŒŒ์ธ์ฝ˜์€ ํ”„๋ก ํŠธ์—”๋“œ, ๋ฐฑ์—”๋“œ, ๊ทธ๋ฆฌ๊ณ  ๋ฐฐํฌ๊นŒ์ง€ ๋ชจ๋‘ ๋‹ด๋‹นํ•œ๋‹ค.

First Example

์ด ๋ถ€๋ถ„์€ ์ง์ ‘ pynecone์— ๋ฐฉ๋ฌธํ•ด ํ™•์ธํ•˜์ž. ๋งŒ์•ฝ ์ด ๋ ˆํฌ๊ฐ€ ํŒŒ์ธ์ฝ˜ ๋ฒˆ์—ญ ํŽ˜์ด์ง€๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ ๋‹ค๋ฉด ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•ด์„œ ๋„ฃ์–ด๋‘๊ฒ ๋‹ค.

๊ฐ„๋‹จํ•œ ๋งˆ์ด๋„ˆ์Šค/ํ”Œ๋Ÿฌ์Šค ๋ฒ„ํŠผ์ด ์žˆ๋Š” ํ™”๋ฉด ์˜ˆ์ œ ์ฝ”๋“œ:

import pynecone as pc


class State(pc.State):
    count: int = 0

    def increment(self):
        self.count += 1

    def decrement(self):
        self.count -= 1


def index():
    return pc.hstack(
        pc.button(
            "Decrement",
            color_scheme="red",
            border_radius="1em",
            on_click=State.decrement,
        ),
        pc.heading(State.count, font_size="2em"),
        pc.button(
            "Increment",
            color_scheme="green",
            border_radius="1em",
            on_click=State.increment,
        ),
    )


app = pc.App(state=State)
app.add_page(index)
app.compile()

The Structure of a Pynceone App(ํŒŒ์ธ์ฝ˜ ์•ฑ์˜ ๊ตฌ์กฐ)

ํŒŒ์ธ์ฝ˜ ์•ฑ์˜ ๊ตฌ์กฐ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋˜์–ด ์žˆ๋Š”์ง€ ์ž์„ธํžˆ ๋“ค์—ฌ๋‹ค ๋ณด์ž.

Import
import pynecone as pc

pynecone ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ import ํ•˜๋ฉด์„œ ๋ชจ๋“  ๊ฒƒ์ด ์‹œ์ž‘๋œ๋‹ค. ๋ชจ๋“  ํŒŒ์ธ์ฝ˜ ํ•จ์ˆ˜๋“ค๊ณผ ํด๋ž˜์Šค๋“ค์€ pc. ์ ‘๋‘์‚ฌ๋กœ ์‹œ์ž‘ํ•œ๋‹ค.

State(์ •์˜)
class State(pc.State):
    count: int = 0

State๋Š” ์•ฑ ๋‚ด์—์„œ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๋ณ€์ˆ˜๋“ค(vars๋ผ๊ณ  ํ•จ)๊ณผ ๋ณ€์ˆ˜๋“ค์„ ๋ณ€๊ฒฝํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•œ๋‹ค.

์œ„์˜ ์˜ˆ์‹œ ์ฝ”๋“œ์—์„œ ์šฐ๋ฆฌ์˜ state๋Š” counter์˜ ํ˜„์žฌ ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ํ•˜๋‚˜์˜ ๋ณ€์ˆ˜(var), count ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ์šฐ๋ฆฌ๋Š” count๋ฅผ 0์œผ๋กœ ์ดˆ๊ธฐํ™”ํ–ˆ๋‹ค.

Event Handlers
def increment(self):
    self.count += 1

def decrement(self):
    self.count -= 1

State ์•ˆ์—๋Š” state ๋ณ€์ˆ˜(var)๋“ค์„ ๋ณ€๊ฒฝํ•˜๋Š” ํ•จ์ˆ˜, ์ฆ‰ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ(event handler) ๋“ค์„ ์ •์˜ํ•œ๋‹ค.

์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋“ค์€ ํŒŒ์ธ์ฝ˜ ๋‚ด์˜ state๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋Š” ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์ด๋‹ค. ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋Š” ๋ฒ„ํŠผ ํด๋ฆญ์ด๋‚˜ ํ…์ŠคํŠธ ์ž…๋ ฅ ๋“ฑ๊ณผ ๊ฐ™์€ ์‚ฌ์šฉ์ž์˜ ์•ก์…˜์— ๋”ฐ๋ฅธ ์‘๋‹ต์œผ๋กœ ํ˜ธ์ถœ๋  ์ˆ˜ ์žˆ๋‹ค. ์ด๋Ÿฌํ•œ ์•ก์…˜๋“ค์€ ์ด๋ฒคํŠธ๋ผ๊ณ  ํ•œ๋‹ค.

ํ˜„์žฌ ์šฐ๋ฆฌ์˜ ์นด์šดํŒ… ์•ฑ์€ increment ๊ณผ decrement ๋ผ๋Š” ๋‘ ๊ฐœ์˜ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

Frontend
def index():
    return pc.hstack(
        pc.button(
            "Decrement",
            color_scheme="red",
            border_radius="1em",
            on_click=State.decrement,
        ),
        pc.heading(State.count, font_size="2em"),
        pc.button(
            "Increment",
            color_scheme="green",
            border_radius="1em",
            on_click=State.increment,
        ),
    )

์ด ํ•จ์ˆ˜๋Š” ์•ฑ์˜ ํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ์ •์˜ํ•œ๋‹ค.

์šฐ๋ฆฌ๋Š” pc.hstack, pc.button, pc.heading ๋“ฑ๊ณผ ๊ฐ™์€ ํŒŒ์ธ์ฝ˜์˜ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ์ •์˜ํ•œ๋‹ค. ์ปดํฌ๋„ŒํŠธ๋“ค์€ ์ค‘์ฒฉ๋˜์–ด์„œ ๋” ๋ณต์žกํ•œ ๋ ˆ์ด์•„์›ƒ์„ ๋งŒ๋“œ๋Š”๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , CSS๋ฅผ ํ™œ์šฉํ•ด์„œ ์Šคํƒ€์ผ๋ง ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

ํŒŒ์ธ์ฝ˜์€ ์‹œ์ž‘์„ ์‰ฝ๊ฒŒ ๋•๊ธฐ ์œ„ํ•ด์„œ 50๊ฐœ ์ด์ƒ์˜ ๋นŒํŠธ์ธ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์ง€์›ํ•œ๋‹ค. ํŒŒ์ธ์ฝ˜ ๊ฐœ๋ฐœํŒ€์€ ๊ณ„์†ํ•ด์„œ ๋” ๋งŽ์€ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์žˆ๊ณ , ๋ณธ์ธ์˜ ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋„ ์‰ฝ๊ฒŒ ํฌ์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.

pc.heading(State.count, font_size="2em"),

์ปดํฌ๋„ŒํŠธ๋“ค์€ ์•ฑ์˜ state ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค. pc.heading ์ปดํฌ๋„ŒํŠธ๋Š” State.count์„ ์ฐธ์กฐํ•˜์—ฌ ์นด์šดํ„ฐ(counter)์˜ ํ˜„์žฌ ๊ฐ’์„ ๋ณด์—ฌ์ค€๋‹ค. state๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๋“ค์€ state๊ฐ€ ๋ณ€๊ฒฝ๋  ๋–„๋งˆ๋‹ค ๋ฐ˜์‘ํ˜•์œผ๋กœ ์—…๋ฐ์ดํŠธ๋œ๋‹ค.

pc.button(
    "Decrement",
    color_scheme="red",
    border_radius="1em",
    on_click=State.decrement,
),

์ปดํฌ๋„ŒํŠธ๋“ค์€ ์ด๋ฒคํŠธ ํŠธ๋ฆฌ๊ฑฐ๋“ค์„ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์— ๋ฐ”์ธ๋”ฉํ•ด์„œ state์™€ ํ†ต์‹ ํ•œ๋‹ค. ์˜ˆ์‹œ๋กœ, on_click ์€ ์‚ฌ์šฉ์ž๊ฐ€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํด๋ฆญํ–ˆ์„ ๋•Œ ํŠธ๋ฆฌ๊ฑฐ๋˜๋Š” ์ด๋ฒคํŠธ๋‹ค.

์˜ˆ์‹œ ์•ฑ์˜ ์ฒซ ๋ฒˆ์งธ ๋ฒ„ํŠผ์€ on_click ์ด๋ฒคํŠธ๋ฅผ State.decrement ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์— ๋ฐ”์ธ๋”ฉํ•˜๊ณ , ๋‘ ๋ฒˆ์งธ ๋ฒ„ํŠผ์€ State.increment ํ•ธ๋“ค๋Ÿฌ์— ๋ฐ”์ธ๋”ฉํ•œ๋‹ค.

Routing
app = pc.App(state=State)

๊ทธ ๋‹ค์Œ, ์•ฑ์„ ์ •์˜ํ•˜๊ณ  ์–ด๋–ค state๋ฅผ ์“ธ ์ง€ ์•Œ๋ ค์ค€๋‹ค.

app.add_page(index)

๊ทธ๋ฆฌ๊ณ  counter ์ปดํฌ๋„ŒํŠธ์— ์•ฑ์˜ ๋ฃจํŠธ URL ๊ฒฝ๋กœ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

Compiling
app.compile()

๋งˆ์ง€๋ง‰์œผ๋กœ ์•ฑ์„ ์ปดํŒŒ์ผ ํ•˜๊ณ  ๋‚˜๋ฉด ์•ฑ์„ ์‹คํ–‰ํ•  ์ค€๋น„๋Š” ๋ชจ๋‘ ๋๋‚ฌ๋‹ค.

Next Steps

์ด์ œ ๋์ด๋‹ค! ์šฐ๋ฆฌ๋Š” ํ”„๋ก ํŠธ์—”๋“œ ๋ฐฑ์—”๋“œ ๋ชจ๋‘๋ฅผ 40 ์ค„๋„ ์•ˆ๋˜๋Š” ์ฝ”๋“œ๋กœ ๋งŒ๋“ค์–ด ๋ƒˆ๋‹ค. ์ด์ œ๋ถ€ํ„ฐ ์šฐ๋ฆฌ๋Š” ํ•˜๋‚˜์˜ ๋ช…๋ น์–ด๋กœ ๊ณ„์†ํ•ด์„œ ์›น์„ ๊ฐœ๋ฐœ ๋˜๋Š” ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ณ„์†ํ•ด์„œ ๋ฌธ์„œ๋ฅผ ์ฝ๊ณ  ์Šค์Šค๋กœ Pynecone์„ ์–ด๋–ป๊ฒŒ ์“ธ ์ˆ˜ ์žˆ๋Š”์ง€ ๋ฐฐ์›Œ๋ณด์ž!


Project Structure

myapp์ด๋ผ๋Š” ์ƒˆ๋กœ์šด ์•ฑ ์ƒ์„ฑํ•˜๊ธฐ

mkdir myapp
cd myapp
pc init

์ƒ์„ฑ๋˜๋Š” ํŒŒ์ผ ๊ตฌ์กฐ:

myapp
โ”œโ”€โ”€ .web
โ”œโ”€โ”€ assets
โ”œโ”€โ”€ myapp
โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ””โ”€โ”€ myapp.py
โ””โ”€โ”€ pcconfig.py

.web

ํŒŒ์ด์ฝ˜ ํ”„๋ก ํŠธ์—”๋“œ๋Š” NextJS ์•ฑ์œผ๋กœ ์ปดํŒŒ์ผ์„ ํ•œ๋‹ค. ์ปดํŒŒ์ผ ๊ฒฐ๊ณผ๋ฌผ(output)์€ .web ํด๋”์— ์ €์žฅ๋œ๋‹ค. ํ•ด๋‹น ํด๋”๋ฅผ ๋งŒ์ ธ์•ผ ํ•  ์ผ์€ ์—†์ง€๋งŒ, ์ด ํด๋” ๋‚ด์šฉ๋ฌผ์„ ๋ณด๋Š” ๊ฑด ๋””๋ฒ„๊น…์— ๋„์›€์ด ๋œ๋‹ค.

๊ฐ๊ฐ pynecone ํŽ˜์ด์ง€๋Š” .web/pages ํด๋” ๋‚ด์— ์ƒ์‘ํ•˜๋Š” .js ํŒŒ์ผ๋กœ ์ปดํŒŒ์ผ ๋œ๋‹ค.

assets

assets ์€ ๊ณต๊ฐœ์ ์œผ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ์ •์ ์ธ asset์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ณณ์ด๋‹ค. asset์—๋Š” ์ด๋ฏธ์ง€, ํฐํŠธ, ๊ทธ๋ฆฌ๊ณ  ๊ธฐํƒ€ ๋‹ค๋ฅธ ํŒŒ์ผ์„ ๋งํ•œ๋‹ค.

์˜ˆ์‹œ๋กœ, assets/image.png ์„ ์ €์žฅํ–ˆ๋‹ค๋ฉด ์•ฑ์—์„œ ์ด๋Ÿฐ ์ฝ”๋“œ๋กœ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ๋‹ค:

pc.image(src="image.png")

Main Project

์ฒ˜์Œ ํ”„๋กœ์ ํŠธ๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๋ฉด ์•ฑ ์ด๋ฆ„๊ณผ ๋™์ผํ•œ ํด๋”๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค. ์—ฌ๊ธฐ๊ฐ€ ๋ฐ”๋กœ ์•ฑ์˜ ๋กœ์ง์„ ์ž‘์„ฑํ•˜๋Š” ๊ณณ์ด๋‹ค. ํŒŒ์ธ์ฝ˜์€ myapp/myapp.py ํŒŒ์ผ์— ๊ธฐ๋ณธ ๋””ํดํŠธ ์•ฑ์„ ์ƒ์„ฑํ•œ๋‹ค. ์ด ํŒŒ์ผ์„ ์ˆ˜์ •ํ•ด์„œ ์•ฑ์„ ์ทจํ–ฅ๋Œ€๋กœ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ํ•  ์ˆ˜ ์žˆ๋‹ค.

Config

pcconfig.py ํŒŒ์ผ์—๋Š” ์•ฑ์˜ ํ™˜๊ฒฝ์„ค์ •์ด ๋‹ด๊ฒจ์žˆ๋‹ค. ์ฒ˜์Œ์— ๊ธฐ๋ณธ์€ ์ด๋ ‡๊ฒŒ ์ƒ๊ฒผ๋‹ค:

import pynecone as pc

config = pc.Config(
    app_name = "myapp",
    bun_path="$HOME/.bun/bin/bun",
    db_url="sqlite:///pynecone.db",
    env=pc.Env.DEV,
)

ํŒŒ์ธ์ฝ˜์€ bun ์„ ์‚ฌ์šฉํ•ด์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค. Bun์€ pc init ์ดˆ๊ธฐํ™” ๋ช…๋ น ์‹œ ~/.bun/bin/bun์— ์ž๋™์œผ๋กœ ์„ค์น˜๋œ๋‹ค. config ํŒŒ์ผ์—์„œ ๋‹ค๋ฅธ ํŠน์ • ๊ฒฝ๋กœ๋ฅผ ์ž…๋ ฅํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค url์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„น์…˜์—์„œ ์ถ”๊ฐ€์ ์œผ๋กœ ์„ค๋ช…ํ•œ๋‹ค.

ํ™˜๊ฒฝ(env)์€ pc.Env.Dev ๋˜๋Š” pc.Env.PROD ๋กœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. self hosting ์„น์…˜์—์„œ ์ถ”๊ฐ€์ ์œผ๋กœ ์„ค๋ช…ํ•œ๋‹ค.


Components

Overview

Component๋Š” ํŒŒ์ด์ฝ˜์˜ ํ”„๋ŸฐํŠธ ์—”๋“œ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ์š”์†Œ์ด๋‹ค. ์ปดํฌ๋„ŒํŠธ๋Š” UI๋ฅผ ๋…๋ฆฝ์ ์ด๊ณ , ์žฌ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๋Š” ์กฐ๊ฐ์œผ๋กœ ๋ถ„๋ฆฌํ•ด ์ค„ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ๊ฐ ์กฐ๊ฐ์— ๋Œ€ํ•ด์„œ๋„ ๋…๋ฆฝ์ ์œผ๋กœ ๊ตฌ์ƒํ•˜๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.

๋งŒ์•ฝ ๋ฆฌ์•กํŠธ(React)์— ์นœ์ˆ™ํ•˜๋‹ค๋ฉด, ํŒŒ์ธ์ฝ˜ ์ปดํฌ๋„ŒํŠธ๋“ค์€ ๋‹จ์ˆœํžˆ ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ์‹ธ๊ณ  ์žˆ๋Š” 'ํฌ์žฅ์ง€' ์ž„์„ ์‰ฝ๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋‹ค.

์ปดํฌ๋„ŒํŠธ๋“ค์€ ํŒŒ์ด์ฌ ํ•จ์ˆ˜๋กœ ์ƒ์„ฑ๋œ๋‹ค. ์ปดํฌ๋„ŒํŠธ๋“ค์€ props ๋ผ๋Š” ํ‚ค์›Œ๋“œ ์ธ์ž๋กœ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ณต์žกํ•œ UI๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ ์ค‘์ฒฉ๋  ์ˆ˜ ์žˆ๋‹ค.

Component Basics

์ปดํฌ๋„ŒํŠธ๋“ค์€ Children๊ณผ Props๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.

Children Props
  • pynecone ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์— ์†ํ•ด ์žˆ๋Š” ๊ฒƒ
  • Children์€ ์ปดํฌ๋„ŒํŠธ์— ๋Œ€ํ•œ ์œ„์น˜ ์ธ์ˆ˜(positional arguments)๋กœ ์ „๋‹ฌ ๋จ.
  • ์ปดํฌ๋„ŒํŠธ์˜ ๋™์ž‘ ๋ฐ ๋ชจ์–‘์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š” ์†์„ฑ
  • Props๋Š” ์ปดํฌ๋„ŒํŠธ์— ๋Œ€ํ•œ ํ‚ค์›Œ๋“œ ์ธ์ˆ˜(keyword arguments)๋กœ ์ „๋‹ฌ ๋จ.

pc.text ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ†ตํ•ด ์˜ˆ์‹œ๋ฅผ ์‚ดํŽด๋ณด์ž.

pc.text("Hello World!", color="blue", font_size="1.5em")

์—ฌ๊ธฐ์„œ "Hello World!"๋Š” ํ‘œ์‹œํ•  child ํ…์ŠคํŠธ์ด๊ณ , color์™€ font_size๋Š” ๊ธ€์ž์˜ ๋ชจ์–‘์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋Š” props์ด๋‹ค.

์ผ๋ฐ˜์ ์ธ Python ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์ปดํฌ๋„ŒํŠธ์˜ children์œผ๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋Š” ๋ฌธ์ž์—ด, ์ˆซ์ž, ๊ทธ๋ฆฌ๊ณ  ๋‹ค์–‘ํ•œ ๊ธฐํƒ€ ๊ฐ„๋‹จํ•œ ๋ฐ์ดํ„ฐ ํƒ€์ž…๋“ค์„ ์ „๋‹ฌํ•˜๋Š” ๋ฐ ์œ ์šฉํ•˜๋‹ค.

Another Example

์ด์ œ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋“ค์ด ์ปดํฌ๋„ŒํŠธ ๋‚ด์— ํฌํ•จ๋˜์–ด ์žˆ๋Š” ์กฐ๊ธˆ ๋” ๋ณต์žกํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ดํŽด๋ณด์ž. pc.hstack ์ปดํฌ๋„ŒํŠธ๋Š” ์ž์‹ ์˜ children์„ ์ˆ˜ํ‰์œผ๋กœ ์ •๋ ฌํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์ด๋‹ค.

<์ฝ”๋“œ ๊ฒฐ๊ณผ๋Š” pynecone ๊ณต์‹ ํ™ˆํŽ˜์ด์ง€์—์„œ ํ™•์ธ...!>

pc.hstack(
    pc.circular_progress(
        pc.circular_progress_label("50", color="green"),
        value=50,
    ),
    pc.circular_progress(
        pc.circular_progress_label(
            "โˆž", color="rgb(107,99,246)"
        ),
        is_indeterminate=True,
    ),
)

์–ด๋–ค props๋“ค์€ component์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง„๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด pc.circular_progress ์ปดํฌ๋„ŒํŠธ์˜ value prop์€ ํ”„๋กœ๊ทธ๋ ˆ์Šค ๋ฐ”์˜ ์ง„ํ–‰ ์ •๋„๋ฅผ ์กฐ์ ˆํ•œ๋‹ค.

color ๊ฐ™์€ ์Šคํƒ€์ผ๋ง prop๋“ค์€ ๋งŽ์€ ์ปดํฌ๋„ŒํŠธ๋“ค์—์„œ ์ด์šฉ๋œ๋‹ค.

์ปดํฌ๋„ŒํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํŽ˜์ด์ง€์—์„œ ๊ฐ ์ปดํฌ๋„ŒํŠธ๋“ค์˜ props๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

Pages

ํŒŒ์ธ์ฝ˜ ์•ฑ๋“ค์€ ํŽ˜์ด์ง€(page)๋“ค๋กœ ๊ตฌ์„ฑ๋œ๋‹ค. ํŽ˜์ด์ง€๋Š” ํŠน์ • URL ๊ฒฝ๋กœ๋ฅผ ์ปดํฌ๋„ŒํŠธ๋กœ ์—ฐ๊ฒฐํ•œ๋‹ค.

์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ˜ํ™˜(๋ฆฌํ„ด)ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ํ•จ์ˆ˜ ์ด๋ฆ„์ด ๊ฒฝ๋กœ๋กœ ์‚ฌ์šฉ๋˜์ง€๋งŒ, ๊ฒฝ๋กœ๋ฅผ ์ง์ ‘ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

def index():
    return pc.text("Root Page")


def about():
    return pc.text("About Page")


app = pc.App()
app.add_page(index, path="/")
app.add_page(about, path="/about")

์ด ์˜ˆ์‹œ์—์„œ ์šฐ๋ฆฌ๋Š” index ๋ผ๋Š” ํŽ˜์ด์ง€๋ฅผ ๋ฃจํŠธ ๊ฒฝ๋กœ์— ์ถ”๊ฐ€ํ–ˆ๋‹ค. ๋งŒ์•ฝ dev ๋ชจ๋“œ๋กœ ์•ฑ์„ ์‹คํ–‰ํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, http://localhost:8000์œผ๋กœ ์ ‘์†ํ•˜๋ฉด ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์œ ์‚ฌํ•˜๊ฒŒ about ํŽ˜์ด์ง€๋Š” http://localhost:8000/about ๊ฒฝ๋กœ๋กœ ์ ‘์†ํ•  ์ˆ˜ ์žˆ๋‹ค.

Props

Props(์ง์—ญ: ์†Œํ’ˆ)๋Š” ์ปดํฌ๋„ŒํŠธ์˜ ํŠน์„ฑ๊ณผ ๋™์ž‘์„ ๋ณ€๊ฒฝํ•œ๋‹ค. Prop๋“ค์€ ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ์ž ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ์ „๋‹ฌ๋œ๋‹ค.

Component Props

๊ฐ ์ปดํฌ๋„ŒํŠธ๋“ค์€ ๊ณ ์œ ํ•œ props๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด pc.avatar ์ปดํฌ๋„ŒํŠธ๋Š” ์•„๋ฐ”ํƒ€ ์ด๋ชจํ‹ฐ์ฝ˜์˜ ์ด๋ฆ„์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š” name prop์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

์ฝ”๋“œ ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€:

Avatar

pc.avatar(
    name="John Doe",
)

๊ณต์‹๋ฌธ์„œ๋ฅผ ํ†ตํ•ด ๊ฐ ์ปดํฌ๋„ŒํŠธ๋“ค์˜ props๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

ํŒŒ์ธ์ฝ˜์€ ๋”์šฑ ๋น ๋ฅธ ์‹œ์ž‘์„ ์œ„ํ•ด ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋นŒํŠธ์ธ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์ง€์›ํ•˜๊ณ  ์žˆ๋‹ค.

Style Props

ํŠน์ • ์ปดํฌ๋„ŒํŠธ๋ฅผ ์œ„ํ•œ porps ์™ธ์—๋„ ๋Œ€๋ถ€๋ถ„์˜ ๊ธฐ๋ณธ ์ œ๊ณต ์ปดํฌ๋„ŒํŠธ๋“ค์€ ๊ด‘๋ฒ”์œ„ํ•œ ์Šคํƒ€์ผ๋ง์„ ์œ„ํ•œ props๋ฅผ ์ง€์›ํ•œ๋‹ค.

<์ฝ”๋“œ ํ…Œ์ŠคํŠธ๋Š” ๊ณต์‹ ํ™ˆํŽ˜์ด์ง€์—์„œ>

์˜ˆ์‹œ ์Šคํฌ๋ฆฐ์ƒท:

Button

pc.button(
    "Fancy Button",
    border_radius="1em",
    box_shadow="rgba(151, 65, 252, 0.8) 0 15px 30px -10px",
    background_image="linear-gradient(144deg,#AF40FF,#5B42F3 50%,#00DDEB)",
    box_sizing="border-box",
    color="white",
    _hover={
        "opacity": 0.85,
    },
)

๋” ๋งŽ์€ ์•ฑ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•์„ ์œ„ํ•ด์„œ๋Š” styling docs๋ฅผ ์ฐธ๊ณ ํ•˜์ž.

Binding Props to State

About

Translation & test repo for pynecone! ๐ŸŒฒ

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages