[๊ฐ๋ ์ ๋ฆฌ] Streamlit๐ ์๊ฐ ๋ฐ ํ์ฉ ๊ฐ์ด๋
์๋ณธ ๊ฒ์๊ธ: https://velog.io/@euisuk-chung/Streamlit-์๊ฐ-๋ฐ-ํ์ฉ-๊ฐ์ด๋
1. Streamlit์ด๋?
Streamlit์ Python ๊ธฐ๋ฐ์ ์คํ์์ค ์น ์ ํ๋ฆฌ์ผ์ด์ ํ๋ ์์ํฌ๋ก, ๋ฐ์ดํฐ ์ฌ์ด์ธ์ค ๋ฐ ๋จธ์ ๋ฌ๋ ๋ชจ๋ธ์ ๋น ๋ฅด๊ฒ ๋ฐฐํฌํ๊ณ ๊ณต์ ํ ์ ์๋๋ก ์ค๊ณ๋ ๋๊ตฌ์ ๋๋ค.
- Flask, Django ๊ฐ์ ์ ํต์ ์ธ ์น ํ๋ ์์ํฌ๋ณด๋ค ํจ์ฌ ๊ฐ๊ฒฐํ ์ฝ๋๋ก ๋์๋ณด๋๋ฅผ ๊ตฌ์ถํ ์ ์์ต๋๋ค.
- ๋จธ์ ๋ฌ๋ ๋ชจ๋ธ์ ์ ๋ ฅ๊ณผ ์ถ๋ ฅ์ ์ฝ๊ฒ ์๊ฐํํ๊ณ , ์น ์ธํฐํ์ด์ค๋ฅผ ์์ฝ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค.
๐บ ๊ณต์ ์๊ฐ ์์: Streamlit Crash Course
2. Streamlit์ ์ฃผ์ ํน์ง
-
๊ฐํธํ ๊ตฌํ:
- ๋ช ์ค์ Python ์ฝ๋๋ง์ผ๋ก ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง๋ค ์ ์์.
-
๋ฐฑ์๋ ๊ฐ๋ฐ ๋ถํ์:
- ๋ณ๋์ API ์๋ฒ ๊ตฌ์ถ ์์ด Python ์ฝ๋๋ง์ผ๋ก ๋์๋ณด๋ ๊ตฌํ ๊ฐ๋ฅ.
-
์๋ ๋ฆฌ๋ ๋๋ง:
- UI ์์๊ฐ ๋ณ๊ฒฝ๋๋ฉด ์๋์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ ๋ฐ์ดํธ๋จ.
-
๋ฐฐํฌ ๊ธฐ๋ฅ ์ง์:
- Streamlit Cloud๋ฅผ ์ด์ฉํด ์ฝ๊ฒ ๋ฐฐํฌ ๊ฐ๋ฅ.
-
์ธํฐ๋ํฐ๋ธ UI ์ ๊ณต:
- ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ๋ฐ์ดํฐ๋ฅผ ์ฆ์ ๋ฐ์ํ ์ ์๋ ์์ ฏ(๋ฒํผ, ์ฌ๋ผ์ด๋, ์ฒดํฌ๋ฐ์ค ๋ฑ) ์ง์.
-
๋ค์ํ ์ฐจํธ ๋ฐ ์ง๋ ์ง์:
- ๋ฐ์ดํฐ๋ฅผ ์๊ฐ์ ์ผ๋ก ํํํ ์ ์๋ ๋ค์ํ ์ฐจํธ ๋ฐ ์ง๋ ์์ ฏ์ ๊ธฐ๋ณธ ์ ๊ณต.
-
์ปค๋ฎค๋ํฐ ๋ฐ ํ์ฅ ๊ธฐ๋ฅ ์ง์:
- ๋ค์ํ ํ๋ฌ๊ทธ์ธ๊ณผ ์ฌ์ฉ์ ์ ์ ์ปดํฌ๋ํธ๋ฅผ ํ์ฉํ์ฌ ๊ธฐ๋ฅ ํ์ฅ์ด ๊ฐ๋ฅ.
3. Streamlit ์ค์น ๋ฐ ๊ธฐ๋ณธ ์คํ
๐ 3.1 ์ค์น
1
pip install streamlit
- ์ค์น ์๋ฃ ํ ๊ธฐ๋ณธ ๋ฐ๋ชจ ์คํ:
1
streamlit hello
- ์ ๋ช ๋ น์ด๋ฅผ ์คํํ๋ฉด ๊ธฐ๋ณธ ๋ฐ๋ชจ๊ฐ ๋ธ๋ผ์ฐ์ (http://localhost:8501/) ์์ ์ด๋ฆฝ๋๋ค.
ํด๋น demo์๋ ์ํ ๋์๋ณด๋ ๋ฐ ๊ตฌํ ์ํ ์ฝ๋ snippet์ด ์กด์ฌํฉ๋๋ค.
-
DataFrame demo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@st.cache_data
def get_UN_data():
AWS_BUCKET_URL = "https://streamlit-demo-data.s3-us-west-2.amazonaws.com"
df = pd.read_csv(AWS_BUCKET_URL + "/agri.csv.gz")
return df.set_index("Region")
try:
df = get_UN_data()
countries = st.multiselect(
"Choose countries", list(df.index), ["China", "United States of America"]
)
if not countries:
st.error("Please select at least one country.")
else:
data = df.loc[countries]
data /= 1000000.0
st.subheader("Gross agricultural production ($B)")
st.dataframe(data.sort_index())
data = data.T.reset_index()
data = pd.melt(data, id_vars=["index"]).rename(
columns={"index": "year", "value": "Gross Agricultural Product ($B)"}
)
chart = (
alt.Chart(data)
.mark_area(opacity=0.3)
.encode(
x="year:T",
y=alt.Y("Gross Agricultural Product ($B):Q", stack=None),
color="Region:N",
)
)
st.altair_chart(chart, use_container_width=True)
except URLError as e:
st.error(f"This demo requires internet access. Connection error: {e.reason}")
-
Plotting demo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
progress_bar = st.sidebar.progress(0)
status_text = st.sidebar.empty()
last_rows = np.random.randn(1, 1)
chart = st.line_chart(last_rows)
for i in range(1, 101):
new_rows = last_rows[-1, :] + np.random.randn(5, 1).cumsum(axis=0)
status_text.text(f"{i}% complete")
chart.add_rows(new_rows)
progress_bar.progress(i)
last_rows = new_rows
time.sleep(0.05)
progress_bar.empty()
# Streamlit widgets automatically run the script from top to bottom. Since
# this button is not connected to any other logic, it just causes a plain
# rerun.
st.button("Rerun")
-
Mapping demo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
@st.cache_data
def from_data_file(filename):
url = (
"https://raw.githubusercontent.com/streamlit/"
"example-data/master/hello/v1/%s" % filename
)
return pd.read_json(url)
try:
ALL_LAYERS = {
"Bike rentals": pdk.Layer(
"HexagonLayer",
data=from_data_file("bike_rental_stats.json"),
get_position=["lon", "lat"],
radius=200,
elevation_scale=4,
elevation_range=[0, 1000],
extruded=True,
),
"Bart stop exits": pdk.Layer(
"ScatterplotLayer",
data=from_data_file("bart_stop_stats.json"),
get_position=["lon", "lat"],
get_color=[200, 30, 0, 160],
get_radius="[exits]",
radius_scale=0.05,
),
"Bart stop names": pdk.Layer(
"TextLayer",
data=from_data_file("bart_stop_stats.json"),
get_position=["lon", "lat"],
get_text="name",
get_color=[0, 0, 0, 200],
get_size=10,
get_alignment_baseline="'bottom'",
),
"Outbound flow": pdk.Layer(
"ArcLayer",
data=from_data_file("bart_path_stats.json"),
get_source_position=["lon", "lat"],
get_target_position=["lon2", "lat2"],
get_source_color=[200, 30, 0, 160],
get_target_color=[200, 30, 0, 160],
auto_highlight=True,
width_scale=0.0001,
get_width="outbound",
width_min_pixels=3,
width_max_pixels=30,
),
}
st.sidebar.subheader("Map layers")
selected_layers = [
layer
for layer_name, layer in ALL_LAYERS.items()
if st.sidebar.checkbox(layer_name, True)
]
if selected_layers:
st.pydeck_chart(
pdk.Deck(
map_style=None,
initial_view_state={
"latitude": 37.76,
"longitude": -122.4,
"zoom": 11,
"pitch": 50,
},
layers=selected_layers,
)
)
else:
st.error("Please choose at least one layer above.")
except URLError as e:
st.error(
"""
**This demo requires internet access.**
Connection error: %s
"""
% e.reason
)
-
Animation demo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# Interactive Streamlit elements, like these sliders, return their value.
# This gives you an extremely simple interaction model.
iterations = st.sidebar.slider("Level of detail", 2, 20, 10, 1)
separation = st.sidebar.slider("Separation", 0.7, 2.0, 0.7885)
# Non-interactive elements return a placeholder to their location
# in the app. Here we're storing progress_bar to update it later.
progress_bar = st.sidebar.progress(0)
# These two elements will be filled in later, so we create a placeholder
# for them using st.empty()
frame_text = st.sidebar.empty()
image = st.empty()
m, n, s = 960, 640, 400
x = np.linspace(-m / s, m / s, num=m).reshape((1, m))
y = np.linspace(-n / s, n / s, num=n).reshape((n, 1))
for frame_num, a in enumerate(np.linspace(0.0, 4 * np.pi, 100)):
# Here were setting value for these two elements.
progress_bar.progress(frame_num)
frame_text.text("Frame %i/100" % (frame_num + 1))
# Performing some fractal wizardry.
c = separation * np.exp(1j * a)
Z = np.tile(x, (n, 1)) + 1j * np.tile(y, (1, m))
C = np.full((n, m), c)
M: Any = np.full((n, m), True, dtype=bool)
N = np.zeros((n, m))
for i in range(iterations):
Z[M] = Z[M] * Z[M] + C[M]
M[np.abs(Z) > 2] = False
N[M] = i
# Update the image placeholder by calling the image() function on it.
image.image(1.0 - (N / N.max()), use_container_width=True)
# We clear elements by calling empty on them.
progress_bar.empty()
frame_text.empty()
# Streamlit widgets automatically run the script from top to bottom. Since
# this button is not connected to any other logic, it just causes a plain
# rerun.
st.button("Rerun")
๐ 3.2 ์ฒซ ๋ฒ์งธ Streamlit ์ฑ ์คํ
hello_streamlit.py
1
2
3
4
import streamlit as st
st.title("Hello Streamlit! ๐")
st.write("์ด๊ฒ์ Streamlit์ผ๋ก ๋ง๋ ๊ฐ๋จํ ์น ์ ํ๋ฆฌ์ผ์ด์
์
๋๋ค.")
- ์คํ ๋ช ๋ น์ด:
1
streamlit run hello_streamlit.py
streamlit run
์ผ๋ก ํ์ด์ฌ ํจ์๋ฅผ ์คํํ์ฌhttp://localhost:8501/
์์ Streamlit์ ์คํํ ์ ์์ต๋๋ค.
4. Streamlit ์ฃผ์ API ์๊ฐ
๐ API DEMO ์ถ๋ ฅ ๊ฒฐ๊ณผ ์ด๋ฏธ์ง๋ ์๋ DataCamp์ ์ถ๋ ฅ ๊ฒฐ๊ณผ ์ด๋ฏธ์ง๋ฅผ ํ์ฉํ์ต๋๋ค.
- Image Source: https://www.datacamp.com/tutorial/streamlit
๐ 4.1 ํ ์คํธ ์ถ๋ ฅ
- Streamlit์ ๋ค์ํ ๋ฐฉ์์ผ๋ก ํ ์คํธ๋ฅผ ํ์ํ ์ ์์ต๋๋ค.
Image Source: https://www.datacamp.com/tutorial/streamlit
st.write()
- ์ค๋ช : ๋ฌธ์์ด, ์ซ์, ๋ฐ์ดํฐํ๋ ์, ๋ฆฌ์คํธ, ๊ฐ์ฒด ๋ฑ์ ์ถ๋ ฅํ ์ ์๋ ๋ฒ์ฉ ์ถ๋ ฅ ํจ์์ ๋๋ค.
- ์ฌ์ฉ ์์:
1
2
st.write("์๋
ํ์ธ์, Streamlit์
๋๋ค!")
st.write(12345)
Image Source: https://www.datacamp.com/tutorial/streamlit
st.title()
- ์ค๋ช : ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๋ชฉ์ ์ค์ ํ๋ ํจ์์ ๋๋ค. ๊ฐ์ฅ ํฐ ๊ธ์จ ํฌ๊ธฐ๋ก ํ์๋ฉ๋๋ค.
-
์ฌ์ฉ ์์:
1
st.title("Streamlit ์น ์ ํ๋ฆฌ์ผ์ด์ ")
st.header()
- ์ค๋ช
: ํค๋(ํฐ ์ ๋ชฉ) ๋ฅผ ์ค์ ํ๋ ํจ์๋ก,
st.title()
๋ณด๋ค ํฌ๊ธฐ๊ฐ ์์ง๋ง, ์ฃผ์ ์น์ ์ ๋๋๋ ๋ฐ ์ ์ฉํฉ๋๋ค. - ์ฌ์ฉ ์์:
1
st.header("์ด๊ฒ์ ํค๋์
๋๋ค")
st.subheader()
- ์ค๋ช
: ์๋ธํค๋(์์ ๋ชฉ) ๋ฅผ ์ค์ ํ๋ ํจ์๋ก,
st.header()
๋ณด๋ค ์์ ํฌ๊ธฐ์ ์ ๋ชฉ์ ๋๋ค. - ์ฌ์ฉ ์์:
1
st.subheader("์ด๊ฒ์ ์๋ธํค๋์
๋๋ค")
st.markdown()
- ์ค๋ช : Markdown ๋ฌธ๋ฒ์ ์ฌ์ฉํ์ฌ ํ ์คํธ๋ฅผ ํฌ๋งทํ ์ ์์ต๋๋ค.
- ์ฌ์ฉ ์์:
1
2
st.markdown("# ํฐ ์ ๋ชฉ (Markdown)")
st.markdown("**๊ตต์ ๊ธ์จ**์ *์ดํค๋ฆญ์ฒด* ์ฌ์ฉ ๊ฐ๋ฅ")
st.caption()
- ์ค๋ช : ์ค๋ช ์ด๋ ์ฃผ์์ ๋ค๋ ์บก์ ์ ์ถ๊ฐํ๋ ํจ์๋ก, ์์ ๊ธ์จ๋ก ํ์๋ฉ๋๋ค.
- ์ฌ์ฉ ์์:
1
st.caption("์ด๊ฒ์ ์บก์
(์ค๋ช
)์
๋๋ค.")
st.code()
- ์ค๋ช : Python ์ฝ๋ ๋๋ ๋ค๋ฅธ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด ์ฝ๋๋ฅผ ํ์ด๋ผ์ดํ ๋ ์ฝ๋ ๋ธ๋ก์ผ๋ก ์ถ๋ ฅํฉ๋๋ค.
- ์ฌ์ฉ ์์:
1
2
3
4
st.code("""
def hello():
print("Hello, Streamlit!")
""", language="python")
st.latex()
- ์ค๋ช : LaTeX ๋ฌธ๋ฒ์ ์ฌ์ฉํ์ฌ ์์์ ๋ ๋๋งํ ์ ์์ต๋๋ค.
- ์ฌ์ฉ ์์:
1
st.latex(r"E = mc^2")
๐ 4.2 ์ฌ์ฉ์ ์ ๋ ฅ ๋ฐ๊ธฐ
- Streamlit์ ๋ค์ํ ์ ๋ ฅ ์์ ฏ์ ์ ๊ณตํ์ฌ ์ฌ์ฉ์๋ก๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ์ ๋ ฅ๋ฐ์ ์ ์์ต๋๋ค.
Image Source: https://www.datacamp.com/tutorial/streamlit
1. ํ
์คํธ ์
๋ ฅ (st.text_input()
)
- ์ค๋ช : ์ฌ์ฉ์๊ฐ ํ ์คํธ๋ฅผ ์ ๋ ฅํ ์ ์๋ ์ ๋ ฅ ์์๋ฅผ ์ ๊ณตํฉ๋๋ค.
- ์์ :
1
2
name = st.text_input("์ด๋ฆ์ ์
๋ ฅํ์ธ์")
st.write(f"์
๋ ฅ๋ ์ด๋ฆ: {name}")
2. ์ซ์ ์
๋ ฅ (st.number_input()
)
- ์ค๋ช : ์ฌ์ฉ์๊ฐ ์ซ์๋ฅผ ์ ๋ ฅํ ์ ์๋๋ก ํฉ๋๋ค.
- ์์ :
1
2
age = st.number_input("๋์ด๋ฅผ ์
๋ ฅํ์ธ์", min_value=0, max_value=100, step=1)
st.write(f"์
๋ ฅ๋ ๋์ด: {age}")
3. ๋ ์ง ์
๋ ฅ (st.date_input()
)
- ์ค๋ช : ์ฌ์ฉ์๊ฐ ๋ ์ง๋ฅผ ์ ํํ ์ ์๋๋ก ํฉ๋๋ค.
- ์์ :
1
2
selected_date = st.date_input("๋ ์ง ์ ํ")
st.write(f"์ ํํ ๋ ์ง: {selected_date}")
4. ์๊ฐ ์
๋ ฅ (st.time_input()
)
- ์ค๋ช : ์ฌ์ฉ์๊ฐ ์๊ฐ์ ์ ํํ ์ ์๋๋ก ํฉ๋๋ค.
- ์์ :
1
2
selected_time = st.time_input("์๊ฐ ์ ํ")
st.write(f"์ ํํ ์๊ฐ: {selected_time}")
5. ์ฌ๋ฌ ์ค ์
๋ ฅ (st.text_area()
)
- ์ค๋ช : ์ฌ๋ฌ ์ค์ ํ ์คํธ๋ฅผ ์ ๋ ฅํ ์ ์๋ ์ ๋ ฅ ํ๋๋ฅผ ์ ๊ณตํฉ๋๋ค.
- ์์ :
1
2
message = st.text_area("๋ฉ์์ง๋ฅผ ์
๋ ฅํ์ธ์")
st.write(f"์
๋ ฅ๋ ๋ฉ์์ง:\n{message}")
6. ํ์ผ ์
๋ก๋ (st.file_uploader()
)
- ์ค๋ช : ์ฌ์ฉ์๊ฐ ํ์ผ์ ์ ๋ก๋ํ ์ ์๋๋ก ํฉ๋๋ค.
- ์์ :
1
2
3
uploaded_file = st.file_uploader("ํ์ผ์ ์
๋ก๋ํ์ธ์")
if uploaded_file is not None:
st.write("์
๋ก๋๋ ํ์ผ:", uploaded_file.name)
7. ์์ ์ ํ (st.color_picker()
)
- ์ค๋ช : ์์์ ์ ํํ ์ ์๋๋ก ํฉ๋๋ค.
- ์์ :
1
2
color = st.color_picker("์์์ ์ ํํ์ธ์", <"#00f900")
st.write(f"์ ํํ ์์: {color}")
๐ 4.3 ๋ฒํผ ๋ฐ ์ ํํ ์ ๋ ฅ
- Streamlit์ ๋ค์ํ ๋ฒํผ ๋ฐ ์ ํํ ์ ๋ ฅ ์์ ฏ์ ์ ๊ณตํ์ฌ ์ธํฐ๋ํฐ๋ธํ UI๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
Image Source: https://www.datacamp.com/tutorial/streamlit
1. ๋ฒํผ (st.button()
)
- ์ค๋ช : ์ฌ์ฉ์๊ฐ ๋ฒํผ์ ํด๋ฆญํ๋ฉด ํน์ ๋์์ ์คํํ ์ ์๋๋ก ํฉ๋๋ค.
- ์์ :
1
2
if st.button("ํด๋ฆญํ์ธ์"):
st.write("๋ฒํผ์ด ํด๋ฆญ๋์์ต๋๋ค!")
2. ์ฒดํฌ๋ฐ์ค (st.checkbox()
)
- ์ค๋ช : ์ฒดํฌ๋ฐ์ค๋ฅผ ์ถ๊ฐํ์ฌ ์ฌ์ฉ์๊ฐ ์ ํํ ์ ์๋๋ก ํฉ๋๋ค.
- ์์ :
1
2
3
agree = st.checkbox("๋์ํฉ๋๋ค")
if agree:
st.write("๋์ํ์
จ์ต๋๋ค!")
3. ๋ผ๋์ค ๋ฒํผ (st.radio()
)
- ์ค๋ช : ์ฌ๋ฌ ์ต์ ์ค ํ๋๋ฅผ ์ ํํ ์ ์๋๋ก ํฉ๋๋ค.
- ์์ :
1
2
selected_option = st.radio("์ต์
์ ์ ํํ์ธ์", ("์ต์
1", "์ต์
2", "์ต์
3"))
st.write(f"์ ํ๋ ์ต์
: {selected_option}")
4. ๋๋กญ๋ค์ด ์ ํ (st.selectbox()
)
- ์ค๋ช : ๋๋กญ๋ค์ด ๋ฆฌ์คํธ์์ ํ๋์ ์ต์ ์ ์ ํํ ์ ์์ต๋๋ค.
- ์์ :
1
2
fruit = st.selectbox("๊ณผ์ผ์ ์ ํํ์ธ์", ["์ฌ๊ณผ", "๋ฐ๋๋", "์ค๋ ์ง"])
st.write(f"์ ํํ ๊ณผ์ผ: {fruit}")
5. ๋ค์ค ์ ํ (st.multiselect()
)
- ์ค๋ช : ์ฌ๋ฌ ๊ฐ์ ์ต์ ์ ๋์์ ์ ํํ ์ ์์ต๋๋ค.
- ์์ :
1
2
planets = st.multiselect("ํ์ฑ์ ์ ํํ์ธ์", ["๋ชฉ์ฑ", "ํ์ฑ", "ํด์์ฑ"])
st.write(f"์ ํํ ํ์ฑ: {planets}")
6. ์ฌ๋ผ์ด๋ (st.slider()
)
- ์ค๋ช : ์ฌ๋ผ์ด๋๋ฅผ ์ฌ์ฉํ์ฌ ์ซ์ ๊ฐ์ ์กฐ์ ํ ์ ์์ต๋๋ค.
- ์์ :
1
2
number = st.slider("์ซ์๋ฅผ ์ ํํ์ธ์", 0, 50)
st.write(f"์ ํ๋ ์ซ์: {number}")
7. ์ ํ ์ฌ๋ผ์ด๋ (st.select_slider()
)
- ์ค๋ช : ๋ฆฌ์คํธ์์ ์ ํด์ง ๊ฐ์ ์ ํํ๋ ์ฌ๋ผ์ด๋์ ๋๋ค.
- ์์ :
1
2
rating = st.select_slider("ํ๊ฐ๋ฅผ ์ ํํ์ธ์", ["๋์จ", "๋ณดํต", "์ข์", "์ต๊ณ "])
st.write(f"์ ํํ ํ๊ฐ: {rating}")
๐ 4.4 ๋ฐ์ดํฐ ์ถ๋ ฅ
- Streamlit์ ํ์ฉํ๋ฉด ์ด๋ฏธ์ง, ๋น๋์ค, ์ค๋์ค ํ์ผ๋ฟ๋ง ์๋๋ผ ๋ฐ์ดํฐํ๋ ์, JSON, ์ฃผ์ ์งํ(Metrics) ๋ฑ์ ์ฝ๊ฒ ์ถ๋ ฅํ ์ ์์ต๋๋ค.
1. ์ด๋ฏธ์ง, ๋น๋์ค ๋ฐ ์ค๋์ค ํ์ผ ์ถ๋ ฅ
- Streamlit์์๋ ๊ฐ๋จํ ํจ์ ํธ์ถ๋ง์ผ๋ก ๋ค์ํ ๋ฏธ๋์ด ํ์ผ์ ํ์ํ ์ ์์ต๋๋ค.
(1) ์ด๋ฏธ์ง ์ถ๋ ฅ (st.image()
)
- ์ค๋ช
: ์ด๋ฏธ์ง๋ฅผ ์ถ๋ ฅํ๋ ํจ์์
๋๋ค.
PIL.Image
๊ฐ์ฒด ๋๋ ์ด๋ฏธ์ง URL, ๋ก์ปฌ ํ์ผ ๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. - ์์ :
1
2
3
4
5
import streamlit as st
from PIL import Image
image = Image.open("example.jpg") - ๋ก์ปฌ ์ด๋ฏธ์ง ํ์ผ
st.image(image, caption="์์ ์ด๋ฏธ์ง", use_column_width=True)
(2) ์ค๋์ค ์ถ๋ ฅ (st.audio()
)
- ์ค๋ช : ์ค๋์ค ํ์ผ์ ์น์์ ์ฌ์ํ ์ ์๋๋ก ํฉ๋๋ค.
- ์์ :
1
st.audio("example.mp3")
(3) ๋น๋์ค ์ถ๋ ฅ (st.video()
)
- ์ค๋ช : ๋น๋์ค ํ์ผ์ ์น์์ ์ฌ์ํ ์ ์๋๋ก ํฉ๋๋ค.
- ์์ :
1
st.video("example.mp4")
2. ๋ฐ์ดํฐํ๋ ์ ์ถ๋ ฅ
- Streamlit์
pandas
๋ฐ์ดํฐํ๋ ์์ ์ฌ๋ฌ ๋ฐฉ์์ผ๋ก ํ์ํ ์ ์์ต๋๋ค.
(1) ๊ธฐ๋ณธ ๋ฐ์ดํฐ ์ถ๋ ฅ (st.write()
)
- ์ค๋ช
:
st.write()
๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฐ์ดํฐํ๋ ์์ ๊ธฐ๋ณธ์ ์ธ ํํ๋ก ์ถ๋ ฅํ ์ ์์ต๋๋ค. - ์์ :
1
st.write(df)
(2) ์ธํฐ๋ํฐ๋ธ ๋ฐ์ดํฐํ๋ ์ (st.dataframe()
)
- ์ค๋ช
:
st.dataframe()
์ ์ฌ์ฉํ๋ฉด ์คํฌ๋กค ๋ฐ ์ ๋ ฌ ๊ธฐ๋ฅ์ด ํฌํจ๋ ์ธํฐ๋ํฐ๋ธํ ๋ฐ์ดํฐํ๋ ์์ ์ถ๋ ฅํ ์ ์์ต๋๋ค. - ์์ :
1
st.dataframe(df)
(3) ์ ์ ํ
์ด๋ธ (st.table()
)
- ์ค๋ช
:
st.table()
์ ์ ์ ์ธ ํ ์ด๋ธ ํํ๋ก ๋ฐ์ดํฐ๋ฅผ ์ถ๋ ฅํ๋ฉฐ, ๋ฐ์ดํฐ ๋ณ๊ฒฝ์ด ํ์ ์์ ๋ ์ ์ฉํฉ๋๋ค. - ์์ :
1
st.table(df)
3. JSON ๋ฐ์ดํฐ ์ถ๋ ฅ (st.json()
)
- ์ค๋ช : JSON ํํ์ ๋ฐ์ดํฐ๋ฅผ ๊ณ์ธต์ ์ผ๋ก ์ ๋ฆฌ๋ ํํ๋ก ์ถ๋ ฅํ ์ ์์ต๋๋ค.
- ์์ :
1
2
3
4
5
st.json({
'์ด๋ฆ': '์ด์ํ',
'๋์ด': 24,
'๊ฑฐ์ฃผ์ง': '๊ด์ฃผ'
})
4. ์ฃผ์ ์งํ ๋ฐ ํต๊ณ ์ถ๋ ฅ (st.metric()
)
- ์ค๋ช
: ํน์ ์งํ(metric) ๋ฅผ ๊ฐ์กฐํด์ ๋ณด์ฌ์ค ๋ ์ฌ์ฉ๋ฉ๋๋ค.
delta
๊ฐ์ ์ค์ ํ๋ฉด ๋ณํ๋์ ํจ๊ป ํ์ํ ์ ์์ต๋๋ค.
์์ (์งํ ์ถ๋ ฅ)
1
2
st.metric(label="LG์ ์", value="78,000์", delta="2.12%")
st.metric(label="ํ๋์ฐจ", value="150,000์", delta="-1.25%")
๐ 4.5 ์ฐจํธ ๋ฐ ์ง๋ ์ถ๋ ฅ
- ๋ฐ์ดํฐ ์๊ฐํ๋ ๋ฐ์ดํฐ๋ฅผ ๋์ฑ ์ง๊ด์ ์ผ๋ก ์ดํดํ๊ณ ์ธ์ฌ์ดํธ๋ฅผ ์ป๋ ๋ฐ ์ค์ํ ์ญํ ์ ํฉ๋๋ค. Streamlit์ ํ์ฉํ๋ฉด ๊ฐ๋จํ ์ฝ๋๋ก ๋ค์ํ ์ฐจํธ์ ์ง๋ ๋ฐ์ดํฐ๋ฅผ ์๊ฐํํ ์ ์์ต๋๋ค.
1. ์ฐจํธ ์ถ๋ ฅ
- Streamlit์ ๋ค์ํ ์ฐจํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ง์ํ๋ฉฐ,
matplotlib
,pandas
,Altair
,Graphviz
๋ฑ์ ๊ทธ๋ํ๋ฅผ ์ฝ๊ฒ ์์ฑํ ์ ์์ต๋๋ค.
(1) Matplotlib ๊ทธ๋ํ (st.pyplot()
)
-
์ค๋ช :
matplotlib.pyplot
์ ์ฌ์ฉํ์ฌ ์์ฑํ ๊ทธ๋ํ๋ฅผ Streamlit ์ฑ์ ํ์ํ ์ ์์ต๋๋ค.Matplotlib
์ Python์์ ๊ฐ์ฅ ๋๋ฆฌ ์ฌ์ฉ๋๋ ์๊ฐํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก, ์ธ๋ฐํ ์ปค์คํฐ๋ง์ด์ง์ด ํ์ํ ๊ฒฝ์ฐ ์ ์ฉํฉ๋๋ค.- ํ์คํ ๊ทธ๋จ, ์ฐ์ ๋, ์ ๊ทธ๋ํ, ๋ง๋ ๊ทธ๋ํ ๋ฑ ๋ค์ํ ๊ทธ๋ํ๋ฅผ ์ง์ ์ ์ดํ ์ ์์ต๋๋ค.
-
์์ :
1
2
3
4
5
6
7
8
import streamlit as st
import matplotlib.pyplot as plt
import numpy as np
rand = np.random.normal(1, 2, size=20) # ์ ๊ท๋ถํฌ ๋์ ์์ฑ
fig, ax = plt.subplots()
ax.hist(rand, bins=15) # ํ์คํ ๊ทธ๋จ ๊ทธ๋ฆฌ๊ธฐ
st.pyplot(fig)
Image Source: https://www.datacamp.com/tutorial/streamlit
(2) ์ ํ ์ฐจํธ (st.line_chart()
)
-
์ค๋ช : Pandas ๋ฐ์ดํฐํ๋ ์์ ์ด์ฉํ์ฌ ์ ํ ์ฐจํธ๋ฅผ ๊ทธ๋ฆฝ๋๋ค.
- ์๊ฐ์ ๋ฐ๋ฅธ ๋ณํ๋ฅผ ์๊ฐํํ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
- ์๊ณ์ด ๋ฐ์ดํฐ, ์ฃผ๊ฐ ๋ณ๋, ํธ๋ ๋ ๋ถ์ ๋ฑ์์ ์ ์ฉํฉ๋๋ค.
-
์์ :
1
2
3
4
5
6
import streamlit as st
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(10, 2), columns=['x', 'y'])
st.line_chart(df)
Image Source: https://www.datacamp.com/tutorial/streamlit
(3) ๋ง๋ ์ฐจํธ (st.bar_chart()
)
-
์ค๋ช : Pandas ๋ฐ์ดํฐํ๋ ์์ ์ด์ฉํ์ฌ ๋ง๋ ์ฐจํธ๋ฅผ ์์ฑํฉ๋๋ค.
- ์นดํ ๊ณ ๋ฆฌ๋ณ ๋น๊ต๋ฅผ ํ ๋ ์ ์ ํ ์ฐจํธ์ ๋๋ค.
- ๊ฐ ๋ฒ์ฃผ์ ํฌ๊ธฐ ์ฐจ์ด๋ฅผ ๊ฐ์กฐํ๋ ๋ฐ ์ ์ฉํฉ๋๋ค.
-
์์ :
1
2
3
4
5
6
import streamlit as st
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(10, 2), columns=['x', 'y'])
st.bar_chart(df)
Image Source: https://www.datacamp.com/tutorial/streamlit
(4) ์์ญ ์ฐจํธ (st.area_chart()
)
-
์ค๋ช : Pandas ๋ฐ์ดํฐํ๋ ์์ ์ด์ฉํ์ฌ ์์ญ ์ฐจํธ๋ฅผ ์์ฑํฉ๋๋ค.
- ์ ํ ์ฐจํธ์ ์ ์ฌํ์ง๋ง, ๋์ ๋ ๊ฐ์ ๋ณํ๋ฅผ ๊ฐ์กฐํ ๋ ์ ์ฉํฉ๋๋ค.
- ์ ์ฒด์ ์ธ ๋ณํ ํ๋ฆ๊ณผ ์ฐจ์ด๋ฅผ ๊ฐ์กฐํ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
-
์์ :
1
2
3
4
5
6
import streamlit as st
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(10, 2), columns=['x', 'y'])
st.area_chart(df)
Image Source: https://www.datacamp.com/tutorial/streamlit
(5) Altair ์ฐจํธ (st.altair_chart()
)
-
์ค๋ช :
Altair
๋ฅผ ์ฌ์ฉํ์ฌ ์ธํฐ๋ํฐ๋ธํ ์ฐจํธ๋ฅผ ์์ฑํฉ๋๋ค.- ๋๊ท๋ชจ ๋ฐ์ดํฐ ๋ถ์ ๋ฐ ์ํธ์์ฉ์ด ํ์ํ ๊ฒฝ์ฐ ์ ํฉํฉ๋๋ค.
- ์ฐ์ ๋, ๋ฒ๋ธ ์ฐจํธ ๋ฑ ๋ค์ฐจ์ ๋ฐ์ดํฐ๋ฅผ ์๊ฐํํ๋ ๋ฐ ์ ์ฉํฉ๋๋ค.
-
์์ :
1
2
3
4
5
6
7
8
9
10
import streamlit as st
import pandas as pd
import numpy as np
import altair as alt
df = pd.DataFrame(np.random.randn(500, 3), columns=['x', 'y', 'z'])
chart = alt.Chart(df).mark_circle().encode(
x='x', y='y', size='z', color='z', tooltip=['x', 'y', 'z']
)
st.altair_chart(chart, use_container_width=True)
Image Source: https://www.datacamp.com/tutorial/streamlit
(6) ๊ทธ๋ํ ๊ตฌ์กฐ ์๊ฐํ (st.graphviz_chart()
)
-
์ค๋ช :
graphviz
๋ฅผ ์ด์ฉํด ๋ ธ๋ ๋ฐ ์ฃ์ง ๊ธฐ๋ฐ ๊ทธ๋ํ๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.- ๋ ธ๋์ ์ฃ์ง ๊ธฐ๋ฐ ๋คํธ์ํฌ๋ฅผ ํํํ๋ ๋ฐ ์ ์ฉํฉ๋๋ค.
- ๊ณ์ธต ๊ตฌ์กฐ, ํ๋ก์ธ์ค ํ๋ฆ๋, ๊ด๊ณ ๋ชจ๋ธ๋ง ๋ฑ์ ์ฌ์ฉ๋ฉ๋๋ค.
-
์์ :
1
2
3
4
5
6
7
8
9
10
11
import streamlit as st
import graphviz
st.graphviz_chart('''
digraph {
Big_shark -> Tuna
Tuna -> Mackerel
Mackerel -> Small_fishes
Small_fishes -> Shrimp
}
''')
Image Source: https://www.datacamp.com/tutorial/streamlit
2. ์ง๋ ์ถ๋ ฅ
- Streamlit์ ๊ฐ๋จํ
st.map()
ํจ์๋ฅผ ์ด์ฉํ์ฌ ์ง๋๋ฅผ ํ์ํ ์ ์์ผ๋ฉฐ,latitude
(์๋) ๋ฐlongitude
(๊ฒฝ๋) ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์๊ฐํํ ์ ์์ต๋๋ค.
์ง๋ ์ถ๋ ฅ (st.map()
)
-
์ค๋ช : Pandas ๋ฐ์ดํฐํ๋ ์์ ์๋(lat)์ ๊ฒฝ๋(lon) ๊ฐ์ ํฌํจํ์ฌ ์ง๋๋ฅผ ์ถ๋ ฅํ ์ ์์ต๋๋ค.
- ์ง๋ฆฌ์ ๋ฐ์ดํฐ ์๊ฐํ๋ฅผ ์ํ ๊ธฐ๋ณธ์ ์ธ ์ง๋ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
- ์๋(
lat
)์ ๊ฒฝ๋(lon
) ๊ฐ์ด ํฌํจ๋ ๋ฐ์ดํฐ๊ฐ ํ์ํฉ๋๋ค.
-
์์ :
1
2
3
4
5
6
7
8
9
import pandas as pd
import numpy as np
import streamlit as st
df = pd.DataFrame(
np.random.randn(500, 2) / [50, 50] + [37.76, -122.4], # ์ํ๋์์ค์ฝ ์ฃผ๋ณ ๋๋ค ์ขํ ์์ฑ
columns=['lat', 'lon']
)
st.map(df)
Image Source: https://www.datacamp.com/tutorial/streamlit
๐ 4.6. ์ํ ๋ฉ์์ง ๋ฐ ์งํ๋ฅ ํ์
- Streamlit์ ์ ํ๋ฆฌ์ผ์ด์ ์ ํ์ฌ ์ํ๋ฅผ ์๊ฐ์ ์ผ๋ก ํํํ ์ ์๋ ๋ค์ํ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. ์งํ๋ฅ ๋ฐ, ์คํผ๋(๋ก๋ฉ ํ์), ์๋ฆผ ๋ฉ์์ง ๋ฑ์ ํ์ฉํ์ฌ ์ฌ์ฉ์ ๊ฒฝํ์ ํฅ์์ํฌ ์ ์์ต๋๋ค.
1. ์งํ๋ฅ ๋ฐ ๋ก๋ฉ ์ํ ํ์
Image Source: https://www.datacamp.com/tutorial/streamlit
(1) ์งํ๋ฅ ๋ฐ (st.progress()
)
- ์ค๋ช : ํ๋ก์ธ์ค ์งํ ์ํฉ์ ๋ํ๋ด๋ ์งํ๋ฅ ๋ฐ(progress bar) ๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
- ์์ :
1
2
3
4
5
6
7
8
import streamlit as st
import time
progress_bar = st.progress(0) # ์ด๊ธฐ๊ฐ 0
for percent in range(0, 101, 10):
time.sleep(0.1) # ํ๋ก์ธ์ค ์งํ ์๋ฎฌ๋ ์ด์
progress_bar.progress(percent) # ์งํ๋ฅ ์
๋ฐ์ดํธ
(2) ์คํผ๋ (st.spinner()
)
- ์ค๋ช : ์๊ฐ์ด ๊ฑธ๋ฆฌ๋ ์์ ์ค ๋ก๋ฉ ๋ฉ์์ง๋ฅผ ํ์ํ๋ ๊ธฐ๋ฅ์ ๋๋ค.
- ์์ :
1
2
3
4
5
6
import streamlit as st
import time
with st.spinner("์ ์๋ง ๊ธฐ๋ค๋ ค ์ฃผ์ธ์..."):
time.sleep(5) # ๋๊ธฐ ์๊ฐ ์๋ฎฌ๋ ์ด์
st.success("์์
์๋ฃ!")
(3) ์ถํ ์ ๋๋ฉ์ด์
(st.balloons()
)
- ์ค๋ช : ์ฌ์ฉ์๊ฐ ์์ ์ ์๋ฃํ์ ๋ ํ์ ์ ๋๋ฉ์ด์ ์ ํ์ํ์ฌ ์ถํํ ์ ์์ต๋๋ค.
- ์์ :
1
2
3
4
import streamlit as st
st.success("์์
์ด ์ฑ๊ณต์ ์ผ๋ก ์๋ฃ๋์์ต๋๋ค!")
st.balloons() # ์ถํ ์ ๋๋ฉ์ด์
2. ์ํ ๋ฉ์์ง ์ถ๋ ฅ
- Streamlit์ ์ฑ๊ณต, ์ค๋ฅ, ๊ฒฝ๊ณ , ์ ๋ณด ๋ฉ์์ง๋ฅผ ์ฝ๊ฒ ์ถ๋ ฅํ ์ ์์ต๋๋ค.
Image Source: https://www.datacamp.com/tutorial/streamlit
(1) ์ฑ๊ณต ๋ฉ์์ง (st.success()
)
- ์ค๋ช : ์ฑ๊ณต์ ์ธ ์์ ์๋ฃ๋ฅผ ์๋ฆฌ๋ ๋ น์ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
- ์์ :
1
st.success("์ถํํฉ๋๋ค! ๋ชจ๋ ์์
์ด ์ฑ๊ณต์ ์ผ๋ก ์๋ฃ๋์์ต๋๋ค.")
(2) ์ค๋ฅ ๋ฉ์์ง (st.error()
)
- ์ค๋ช : ์๋ฌ ๋๋ ์คํจํ ์์ ์ ๊ฐ์กฐํ ๋ ์ฌ์ฉํฉ๋๋ค.
- ์์ :
1
st.error("์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค. ๋ค์ ์๋ํด์ฃผ์ธ์.")
(3) ๊ฒฝ๊ณ ๋ฉ์์ง (st.warning()
)
- ์ค๋ช : ์ฃผ์๊ฐ ํ์ํ ์์ ์ ๊ฐ์กฐํ๋ ๊ฒฝ๊ณ ๋ฉ์์ง์ ๋๋ค.
- ์์ :
1
st.warning("์ด ์์
์ ์ฃผ์๊ฐ ํ์ํฉ๋๋ค.")
(4) ์ ๋ณด ๋ฉ์์ง (st.info()
)
- ์ค๋ช : ์ผ๋ฐ์ ์ธ ์ ๋ณด๋ ๊ฐ์ด๋๋ผ์ธ์ ์ ๋ฌํ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
- ์์ :
1
st.info("Streamlit์ ์ฌ์ฉํ๋ฉด ์ฝ๊ฒ ์น ์ฑ์ ๋ง๋ค ์ ์์ต๋๋ค.")
(5) ์์ธ ๋ฉ์์ง (st.exception()
)
- ์ค๋ช : Python์ ์์ธ(Exception) ๋ฅผ ์ถ๋ ฅํ ๋ ์ฌ์ฉํฉ๋๋ค.
- ์์ :
1
st.exception(RuntimeError("RuntimeError ์์ธ ๋ฐ์"))
-
Streamlit Component
Streamlit์ ๋ค์ํ UI ์์๋ฅผ ์ ๊ณตํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ณด๋ค ๊ตฌ์กฐ์ ์ผ๋ก ์ ๋ฆฌํ๊ณ ์ฌ์ฉ์ ๊ฒฝํ์ ํฅ์์ํฌ ์ ์์ต๋๋ค. ์ด ์ฅ์์๋ ์ฌ์ด๋๋ฐ, ์ปจํ ์ด๋, ์ปฌ๋ผ, ํญ, ์ต์คํฌ๋(expander) ๋ฑ์ ๊ธฐ๋ฅ์ ์ ๋ฆฌํ๊ฒ ์ต๋๋ค.
๐ 5.1. Sidebar ์ฌ์ฉํ๊ธฐ
Streamlit์ st.sidebar()
๋ฅผ ์ฌ์ฉํ๋ฉด ํ๋ฉด์ ์ผ์ชฝ์ ๊ณ ์ ๋ ์ฌ์ด๋๋ฐ(Sidebar) ๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
(1) ์ฌ์ด๋๋ฐ ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
- ์ค๋ช
:
st.sidebar
๋ฅผ ์ฌ์ฉํ๋ฉด ์ฑ์ ์ฃผ์ ์ฝํ ์ธ ๋ฅผ ๋ฐฉํดํ์ง ์๊ณ ์ต์ , ์ ๋ ฅ ํ๋, ๋ฒํผ ๋ฑ์ ๋ฐฐ์นํ ์ ์์ต๋๋ค. - ์์ :
1
2
3
4
5
6
7
8
import streamlit as st
st.sidebar.title("์ฌ์ด๋๋ฐ ๋ฉ๋ด")
st.sidebar.markdown("์ฌ๊ธฐ์ ์ค์ ์ ์ถ๊ฐํ ์ ์์ต๋๋ค.")
# ์ฌ์ด๋๋ฐ ์์ ์ถ๊ฐ
option = st.sidebar.radio("์ต์
์ ํ", ["์ต์
A", "์ต์
B", "์ต์
C"])
st.sidebar.button("์ฌ์ด๋๋ฐ ๋ฒํผ")
๐ ์ฃผ์ ํน์ง
st.sidebar.title()
,st.sidebar.markdown()
,st.sidebar.radio()
๋ฑ์ ์ฌ์ฉํ์ฌ ์ฌ์ด๋๋ฐ ๋ด UI ๊ตฌ์ฑ ๊ฐ๋ฅ- ์ฃผ์ ์ฝํ ์ธ ๋ฅผ ํ๋ฉด ์ค์์ ๋ฐฐ์นํ๋ฉด์ ์ค์ ์ ์ฌ์ด๋๋ฐ์ ๋ฃ์ด ์ฌ์ฉ์ ๊ฒฝํ์ ํฅ์
๐ 5.2. ์ฌ๋ฌ ๊ฐ์ ์ปฌ๋ผ ํ์ฉ
Streamlit์์๋ st.columns()
์ ์ฌ์ฉํ์ฌ ์ฌ๋ฌ ๊ฐ์ ์ปฌ๋ผ์ ์์ฑํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํ์ฉํ๋ฉด ๋ ์ด์์์ ๋ ์ ๋ํ ์ ์์ต๋๋ค.
(1) ๋์ผํ ๋๋น์ ์ปฌ๋ผ ์์ฑ
- ์ค๋ช
:
st.columns(n)
์ ์ฌ์ฉํ๋ฉดn
๊ฐ์ ๋์ผํ ํฌ๊ธฐ์ ์ปฌ๋ผ์ด ์์ฑ๋ฉ๋๋ค. - ์์ :
1
2
3
4
col1, col2 = st.columns(2)
col1.write("์ฒซ ๋ฒ์งธ ์ปฌ๋ผ")
col2.write("๋ ๋ฒ์งธ ์ปฌ๋ผ")
(2) ๋ค์ํ ๋๋น์ ์ปฌ๋ผ ์์ฑ
- ์ค๋ช
:
st.columns([๋น์จ1, ๋น์จ2, ...])
์ ์ฌ์ฉํ๋ฉด ๋น์จ์ ์ง์ ํ์ฌ ๊ฐ๋ณ์ ์ธ ๋๋น์ ์ปฌ๋ผ์ ์์ฑํ ์ ์์ต๋๋ค. - ์์ :
1
2
3
4
5
6
7
8
9
10
11
12
13
col1, col2, col3 = st.columns([2, 6, 2])
with col1:
st.header('Col1')
st.image('https://static.streamlit.io/examples/cat.jpg')
with col2:
st.header('Col2')
st.image('https://static.streamlit.io/examples/dog.jpg')
with col3:
st.header('Col3')
st.image('https://static.streamlit.io/examples/owl.jpg')
๐ ์ฃผ์ ํน์ง
- ์ฌ๋ฌ ๊ฐ์ UI ์์๋ฅผ ๋ณ๋ ฌ ๋ฐฐ์น ๊ฐ๋ฅ
- ๋ฐ์ดํฐ ์๊ฐํ ๋ฐ ๋น๊ต ๋ถ์ ํ๋ฉด ๊ตฌ์ฑ์ ์ ์ฉ
๐ 5.3. ์ปจํ ์ด๋ ์ฌ์ฉํ๊ธฐ
Streamlit์์๋ st.container()
๋ฅผ ์ฌ์ฉํ์ฌ ๋ด์ฉ์ ๊ทธ๋ฃนํํ ์ ์์ต๋๋ค.
(1) ์ปจํ ์ด๋ ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
- ์ค๋ช
:
st.container()
์์ ์์๋ฅผ ๋ฐฐ์นํ๋ฉด ๋ ผ๋ฆฌ์ ์ธ ๊ทธ๋ฃน์ ๋ง๋ค ์ ์์ต๋๋ค. - ์์ :
1
2
with st.container():
st.write("์ด๊ฒ์ ์ปจํ
์ด๋ ๋ด๋ถ์
๋๋ค.")
๐ ์ฃผ์ ํน์ง
- ํน์ ์ฝํ ์ธ ๋ฅผ ๋ ผ๋ฆฌ์ ์ผ๋ก ๊ทธ๋ฃนํํ์ฌ UI๋ฅผ ์ ๋
- ๋ฐ๋ณต์ ์ธ UI ์์๋ฅผ ๋์ ์ผ๋ก ์์ฑํ ๋ ์ ์ฉ
๐ 5.4. Tab(ํญ) ํ์ฉํ๊ธฐ
Streamlit์ st.tabs()
๋ฅผ ์ฌ์ฉํ๋ฉด ํ ํ๋ฉด์์ ์ฌ๋ฌ ๊ฐ์ ํญ์ ํ์ฉํ ์ ์์ต๋๋ค.
(1) ๊ธฐ๋ณธ์ ์ธ ํญ ์์ฑ
- ์ค๋ช
:
st.tabs(["ํญ ์ด๋ฆ1", "ํญ ์ด๋ฆ2", ...])
์ ์ฌ์ฉํ์ฌ ํญ์ ์์ฑํ๊ณ , ๊ฐ ํญ์ ์ฝํ ์ธ ๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค. - ์์ :
1
2
3
4
5
6
7
8
9
10
11
12
13
tab1, tab2, tab3 = st.tabs(['Cat', 'Dog', 'Owl'])
with tab1:
st.header('๊ณ ์์ด')
st.image('https://static.streamlit.io/examples/cat.jpg')
with tab2:
st.header('๊ฐ์์ง')
st.image('https://static.streamlit.io/examples/dog.jpg')
with tab3:
st.header('์ฌ๋นผ๋ฏธ')
st.image('https://static.streamlit.io/examples/owl.jpg')
๐ ์ฃผ์ ํน์ง
- ์ฌ๋ฌ ๊ฐ์ ์ ๋ณด๋ฅผ ํ ํ๋ฉด์์ ๊ด๋ฆฌํ๋ฉด์๋ ์ฌ์ฉ์๊ฐ ์ ํ์ ์ผ๋ก ๋ณผ ์ ์๋๋ก ๊ตฌ์ฑ
- ๋ฉํฐ ํ์ด์ง ๊ตฌ์กฐ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๊ตฌํ ๊ฐ๋ฅ
๐ 5.5. Expander(ํผ์น๊ธฐ) ์ฌ์ฉํ๊ธฐ
Streamlit์์๋ st.expander()
๋ฅผ ์ฌ์ฉํ์ฌ ์ ๋ณด๋ฅผ ์ ๊ณ ํผ์น๋ UI๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค.
(1) ๊ธฐ๋ณธ์ ์ธ Expander ์ฌ์ฉ๋ฒ
- ์ค๋ช
:
st.expander("์ ๋ชฉ")
์ ์ฌ์ฉํ์ฌ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ํ ์๋ ๋ธ๋ก์ ๋ง๋ค๊ณ , ํด๋ฆญ ์ ๋ด์ฉ์ ํผ์น ์ ์์ต๋๋ค. - ์์ :
1
2
with st.expander("๋ ๋ณด๊ธฐ"):
st.write("์ด๊ณณ์ ์ถ๊ฐ ์ ๋ณด๋ฅผ ์
๋ ฅํ ์ ์์ต๋๋ค.")
(2) Expander ๋ด๋ถ์ ์ด๋ฏธ์ง ๋ฐ ํ ์คํธ ์ถ๊ฐ
- ์ค๋ช
:
st.expander()
๋ด๋ถ์ ์ฌ๋ฌ ๊ฐ์ง ์์๋ฅผ ๋ฃ์ ์ ์์ต๋๋ค. - ์์ :
1
2
3
with st.expander("๊ณ ์์ด ์ ๋ณด ๋ณด๊ธฐ"):
st.write("์ฌ๊ธฐ์๋ ๊ณ ์์ด์ ๋ํ ์ ๋ณด๊ฐ ๋ค์ด๊ฐ๋๋ค.")
st.image('https://static.streamlit.io/examples/cat.jpg', width=200)
๐ ์ฃผ์ ํน์ง
- ๊ธด ๋ด์ฉ์ ํ ๋ฒ์ ํ์ํ์ง ์๊ณ , ํ์ํ ๋๋ง ๋ด์ฉ์ ๋ณผ ์ ์๋๋ก ๊ตฌ์ฑ ๊ฐ๋ฅ
- ์ค๋ช ์, ์ถ๊ฐ ์ ๋ณด ์ ๊ณต ์ ์ ์ฉ
6. Streamlit ๋ก์ปฌ ์๋ฒ ์คํ ๋ฐ ์ธ๋ถ ์ ์ ์ค์
(์ฐธ๊ณ ) ๊ธฐ๋ณธ์ ์ผ๋ก ์คํํ๋ฉด?
1 streamlit run app.py
- ๊ธฐ๋ณธ์ ์ผ๋ก localhost:8501 ์์ ์คํ๋จ.
- localhost๋ 127.0.0.1๋ก ๋งคํ๋๋ฉฐ, ์ธ๋ถ์์๋ ์ ๊ทผํ ์ ์์.
- ์ฆ, ๊ฐ์ PC์์๋ง ์ ๊ทผ ๊ฐ๋ฅํ๊ณ , ๋ค๋ฅธ ๋คํธ์ํฌ ๊ธฐ๊ธฐ(์: ์ค๋งํธํฐ, ๋ค๋ฅธ ์ปดํจํฐ)์์๋ ์ ์ํ ์ ์์.
๐ 6.1 ํน์ ํฌํธ์์ ์คํ
- ๊ธฐ๋ณธ ํฌํธ(8501) ๋์
8080
ํฌํธ์์ ์คํ๋จ.
1
streamlit run app.py --server.port 8080
โ ์ ํน์ ํฌํธ๋ฅผ ๋ณ๊ฒฝํ ๊น?
- ํฌํธ ์ถฉ๋ ๋ฐฉ์ง: ์ด๋ฏธ 8501 ํฌํธ๋ฅผ ๋ค๋ฅธ ์๋น์ค๊ฐ ์ฌ์ฉ ์ค์ผ ์๋ ์์.
- ๊ธฐ๋ณธ ๋ฐฉํ๋ฒฝ ์ ์ฑ ์ฐํ: ์ผ๋ถ ๋คํธ์ํฌ ํ๊ฒฝ์์๋ ํน์ ํฌํธ(์: 8501)๊ฐ ์ฐจ๋จ๋ ์ ์์.
- ๊ณต์ ๋ ์๋ฒ์์ ๋ค๋ฅธ ์๋น์ค์ ๊ตฌ๋ถ: ๋์ผํ ์๋ฒ์์ ์ฌ๋ฌ Streamlit ์ฑ์ ์คํํ ๋ ํฌํธ๋ฅผ ๋ค๋ฅด๊ฒ ์ค์ ํด์ผ ํจ.
๐ 6.2 ์ธ๋ถ ๋คํธ์ํฌ์์ ์ ์ ๊ฐ๋ฅํ๊ฒ ํ๊ธฐ
- ๊ฐ์ ๋คํธ์ํฌ ๋ด ๋ค๋ฅธ ๊ธฐ๊ธฐ์์๋
http://<์๋ฒ IP>:8080
์ผ๋ก ์ ์ ๊ฐ๋ฅ
1
streamlit run app.py --server.address 0.0.0.0 --server.port 8080
โ ์ฌ๊ธฐ์ 0.0.0.0์ด ๋ฌด์์ธ๊ฐ?
- ๊ธฐ๋ณธ์ ์ผ๋ก Streamlit์
localhost(127.0.0.1)
์์๋ง ์คํ๋๋ฏ๋ก, ์ธ๋ถ์์๋ ์ ๊ทผํ ์ ์์.0.0.0.0
์ผ๋ก ์ค์ ํ๋ฉด ํด๋น ์ปดํจํฐ์ ๋ชจ๋ ๋คํธ์ํฌ ์ธํฐํ์ด์ค์์ ์ ๊ทผ ๊ฐ๋ฅ.- ์ฆ, ๊ฐ์ ๋คํธ์ํฌ์ ๋ค๋ฅธ ๊ธฐ๊ธฐ์์๋
http://<์๋ฒ์ IP>:8080
์ ํตํด ์ ๊ทผ ๊ฐ๋ฅ.
7. Streamlit ๋ฐฐํฌํ๊ธฐ
๐ 7.1 Streamlit Community Cloud ๋ฐฐํฌ
- GitHub์ ํ๋ก์ ํธ ์ ๋ก๋
- Streamlit Cloud ์ ์
- New app ๋ฒํผ ํด๋ฆญ ํ GitHub ์ ์ฅ์ ์ ํ
- ์๋์ผ๋ก ๋ฐฐํฌ๋จ (๋ฌด๋ฃ ๋ฐฐํฌ ๊ฐ๋ฅ)
๐ 7.2 Docker๋ฅผ ํ์ฉํ ๋ฐฐํฌ
1) Dockerfile ์์ฑ
1
2
3
4
5
6
7
8
FROM python:3.9
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["streamlit", "run", "app.py", "--server.address=0.0.0.0", "--server.port=8501"]
2) Docker ์ปจํ ์ด๋ ์คํ
1
2
docker build -t my-streamlit-app .
docker run -p 8501:8501 my-streamlit-app
๐ ์ด์ http://<์๋ฒ IP>:8501
์์ ์ ๊ทผ ๊ฐ๋ฅ!
โน๏ธ Streamlit ์ปค๋ฎค๋ํฐ ๋ฐ ํ์ต ์๋ฃ
- Streamlit ๊ณต์ ๋ฌธ์: https://docs.streamlit.io/
- 30์ผ ์ฑ๋ฆฐ์ง: https://30days.streamlit.app
- Streamlit ๊ฐค๋ฌ๋ฆฌ (์์ ์ฑ ๋ชจ์): https://streamlit.io/gallery
- Streamlit ํฌ๋ผ (์ง๋ฌธ & ํ ๋ก ): https://discuss.streamlit.io
๐ฏ ์ ๋ฆฌ
Streamlit
์ ๊ฐ๋จํ ํ์ด์ฌ ์ฝ๋๋ง์ผ๋ก ์น/์ฑ ๋์๋ณด๋๋ฅผ ๋ง๋ค ์ ์๋ ์ต๊ณ ์ ๋๊ตฌ- ๋ฐฐํฌ๋ ์ฝ๊ณ , ๋ก์ปฌ ์๋ฒ์์๋ ์์ฝ๊ฒ ์คํ ๊ฐ๋ฅ
- ๋ฐ์ดํฐ ๋ถ์, ๋จธ์ ๋ฌ๋ ๋ชจ๋ธ ๋ฐฐํฌ, ์ค์๊ฐ ๋์๋ณด๋ ๊ตฌ์ถ ๋ฑ ๋ค์ํ ๋ถ์ผ์์ ํ์ฉ ๊ฐ๋ฅ
์ฝ์ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค ๐