Streamlit 주요 기능 완벽 정리 - 데이터 애플리케이션 개발 가이드
Streamlit 주요 기능 완벽 정리
📌 소개
Streamlit은 Python으로 데이터 분석 및 머신러닝 웹 애플리케이션을 빠르게 구축할 수 있는 오픈소스 프레임워크임. 이 글에서는 실제 프로젝트에서 사용한 Streamlit의 주요 기능들을 정리함.
🚀 Streamlit 설치 및 실행
설치 방법
# pip를 이용한 설치
pip install streamlit
# 특정 버전 설치
pip install streamlit==1.30.0
# 필요한 라이브러리와 함께 설치
pip install streamlit pandas plotly
Streamlit 앱 실행 방법
Streamlit은 일반적인 Python 스크립트와 달리 python 명령어가 아닌 streamlit run 명령어로 실행함.
# 기본 실행 방법
streamlit run app.py
# 특정 포트로 실행
streamlit run app.py --server.port 8080
# 브라우저 자동 실행 비활성화
streamlit run app.py --server.headless true
❌ 잘못된 실행 방법:
python app.py # 이렇게 실행하면 안 됨!
✅ 올바른 실행 방법:
streamlit run app.py # 이렇게 실행해야 함!
간단한 예제로 실행해보기
hello.py 파일 생성:
import streamlit as st
st.title('Hello Streamlit! 🎉')
st.write('첫 번째 Streamlit 앱입니다.')
name = st.text_input('이름을 입력하세요')
if name:
st.write(f'안녕하세요, {name}님!')
실행:
streamlit run hello.py
실행하면 자동으로 브라우저가 열리고 http://localhost:8501에서 앱을 확인할 수 있음.
주요 실행 옵션
# 포트 변경
streamlit run app.py --server.port 8080
# 외부 접속 허용
streamlit run app.py --server.address 0.0.0.0
# 파일 변경 감지 비활성화
streamlit run app.py --server.fileWatcherType none
# 테마 설정
streamlit run app.py --theme.base dark
개발 시 유용한 팁
1. 자동 새로고침:
- 코드를 수정하고 저장하면 Streamlit이 자동으로 변경사항을 감지함
- 브라우저 우측 상단에 “Rerun” 버튼이 나타남
- “Always rerun” 옵션을 선택하면 자동으로 재실행됨
2. 캐시 초기화:
# 캐시 삭제
streamlit cache clear
3. 설정 파일:
프로젝트 폴더에 .streamlit/config.toml 파일을 만들어 기본 설정 가능함
[server]
port = 8501
headless = false
[theme]
primaryColor = "#F63366"
backgroundColor = "#FFFFFF"
secondaryBackgroundColor = "#F0F2F6"
textColor = "#262730"
font = "sans serif"
디버깅 방법
Streamlit에서는 print() 대신 다음 방법들을 사용함:
import streamlit as st
# 1. st.write() - 가장 범용적
st.write('디버깅 메시지:', variable)
# 2. st.text() - 단순 텍스트
st.text(f'값: {variable}')
# 3. st.code() - 코드 형식으로 표시
st.code(f'variable = {variable}')
# 4. st.json() - JSON 형식으로 표시
st.json({'key': 'value', 'number': 123})
# 5. st.dataframe() - 데이터프레임 표시
st.dataframe(df)
# 6. st.expander() - 접을 수 있는 디버그 정보
with st.expander('디버그 정보'):
st.write('변수 값:', variable)
st.write('데이터프레임:', df)
터미널에서 확인하고 싶을 때:
import streamlit as st
# 터미널에 출력 (개발 중 디버깅용)
print('터미널에 출력됨') # streamlit run 실행한 터미널에 표시됨
# 브라우저에 출력 (사용자에게 보여줄 때)
st.write('브라우저에 출력됨') # 웹 페이지에 표시됨
프로젝트 구조 예시
my-streamlit-app/
│
├── app.py # 메인 앱 파일
├── requirements.txt # 필요한 패키지 목록
├── .streamlit/
│ └── config.toml # Streamlit 설정
├── data/ # 데이터 파일
│ └── sample.csv
├── utils/ # 유틸리티 함수
│ └── helpers.py
└── README.md
requirements.txt 예시:
streamlit==1.30.0
pandas==2.0.0
plotly==5.18.0
numpy==1.24.0
설치:
pip install -r requirements.txt
1️⃣ 텍스트 및 마크다운 표시 기능
1.1 제목 및 헤더
Streamlit은 다양한 레벨의 제목을 지원함.
import streamlit as st
# 타이틀 (가장 큰 제목)
st.title('이것은 타이틀 입니다')
# 이모티콘 삽입 가능
st.title('스마일 :sunglasses:')
# 헤더
st.header('헤더를 입력할 수 있어요! :sparkles:')
# 서브헤더
st.subheader('이것은 subheader 입니다')
# 캡션 (작은 텍스트)
st.caption('캡션을 한 번 넣어 봤습니다')
특징:
- 이모티콘 shortcode를 사용하여 다양한 이모티콘 삽입 가능함
- 이모티콘 참고: https://streamlit-emoji-shortcodes-streamlit-app-gwckff.streamlit.app/
1.2 코드 표시
# 코드 블록 표시
sample_code = '''
def function():
print('hello, world')
'''
st.code(sample_code, language="python")
코드를 syntax highlighting과 함께 깔끔하게 표시할 수 있음.
1.3 일반 텍스트 및 마크다운
# 일반 텍스트
st.text('일반적인 텍스트를 입력해 보았습니다.')
# 마크다운 문법 지원
st.markdown('streamlit은 **마크다운 문법을 지원**합니다.')
# 컬러 텍스트 (blue, green, orange, red, violet)
st.markdown("텍스트의 색상을 :green[초록색]으로, 그리고 **:blue[파란색]** 볼트체로 설정할 수 있습니다.")
# LaTeX 수식 표현
st.markdown(":green[$\\sqrt{x^2+y^2}=1$] 와 같이 latex 문법의 수식 표현도 가능합니다 :pencil:")
1.4 LaTeX 수식
# LaTeX 수식 전용 표시
st.latex(r'\sqrt{x^2+y^2}=1')
수학 공식을 아름답게 표현할 수 있음.
2️⃣ 데이터 표시 기능
2.1 DataFrame 표시
import pandas as pd
# DataFrame 생성
dataframe = pd.DataFrame({
'first column': [1, 2, 3, 4],
'second column': [10, 20, 30, 40],
})
# Interactive DataFrame (정렬, 필터링 가능)
st.dataframe(dataframe, use_container_width=False)
특징:
use_container_width: 데이터프레임을 컨테이너 크기에 맞춰 확장할지 여부 설정함 (True/False)- 사용자가 직접 정렬하고 탐색할 수 있는 인터랙티브 UI 제공함
2.2 정적 테이블
# 정적 테이블 (인터랙션 없음)
st.table(dataframe)
DataFrame과 달리 인터랙티브 UI를 제공하지 않는 정적 테이블임.
2.3 메트릭 표시
# 단일 메트릭
st.metric(label="온도", value="10°C", delta="1.2°C")
st.metric(label="삼성전자", value="61,000 원", delta="-1,200 원")
# 컬럼으로 나누어 표시
col1, col2, col3 = st.columns(3)
col1.metric(label="달러USD", value="1,228 원", delta="-12.00 원")
col2.metric(label="일본JPY(100엔)", value="958.63 원", delta="-7.44 원")
col3.metric(label="유럽연합EUR", value="1,335.82 원", delta="11.44 원")
특징:
delta값이 양수면 녹색 화살표, 음수면 빨간색 화살표로 표시됨- 대시보드의 KPI 표시에 매우 유용함
3️⃣ 사용자 입력 위젯
3.1 버튼
# 일반 버튼
button = st.button('버튼을 눌러보세요')
if button:
st.write(':blue[버튼]이 눌렸습니다 :sparkles:')
3.2 다운로드 버튼
# 파일 다운로드 버튼
dataframe = pd.DataFrame({
'first column': [1, 2, 3, 4],
'second column': [10, 20, 30, 40],
})
st.download_button(
label='CSV로 다운로드',
data=dataframe.to_csv(),
file_name='sample.csv',
mime='text/csv'
)
사용자가 데이터를 CSV 파일로 다운로드할 수 있게 함.
3.3 체크박스
# 체크박스
agree = st.checkbox('동의 하십니까?')
if agree:
st.write('동의 해주셔서 감사합니다 :100:')
3.4 라디오 버튼
# 라디오 선택 버튼 (단일 선택)
mbti = st.radio(
'당신의 MBTI는 무엇입니까?',
('ISTJ', 'ENFP', '선택지 없음'))
if mbti == 'ISTJ':
st.write('당신은 :blue[현실주의자] 이시네요')
elif mbti == 'ENFP':
st.write('당신은 :green[활동가] 이시네요')
else:
st.write("당신에 대해 :red[알고 싶어요]:grey_exclamation:")
3.5 선택박스 (Selectbox)
# 드롭다운 선택박스
mbti = st.selectbox(
'당신의 MBTI는 무엇입니까?',
('ISTJ', 'ENFP', '선택지 없음'),
index=2 # 기본 선택 인덱스
)
특징:
index파라미터로 기본 선택값 지정 가능함
3.6 다중 선택박스 (Multiselect)
# 다중 선택박스
options = st.multiselect(
'당신이 좋아하는 과일은 뭔가요?',
['망고', '오렌지', '사과', '바나나'],
['망고', '오렌지'] # 기본 선택값
)
st.write(f'당신의 선택은: :red[{options}] 입니다.')
여러 개의 옵션을 동시에 선택할 수 있음.
3.7 슬라이더
from datetime import datetime as dt
import datetime
# 범위 슬라이더
values = st.slider(
'범위의 값을 다음과 같이 지정할 수 있어요:sparkles:',
0.0, 100.0, (25.0, 75.0))
st.write('선택 범위:', values)
# 날짜/시간 슬라이더
start_time = st.slider(
"언제 약속을 잡는 것이 좋을까요?",
min_value=dt(2020, 1, 1, 0, 0),
max_value=dt(2020, 1, 7, 23, 0),
value=dt(2020, 1, 3, 12, 0),
step=datetime.timedelta(hours=1),
format="MM/DD/YY - HH:mm")
st.write("선택한 약속 시간:", start_time)
특징:
- 숫자 범위뿐만 아니라 날짜/시간 선택도 가능함
step파라미터로 증감 단위 조절 가능함
3.8 텍스트 입력
# 텍스트 입력
title = st.text_input(
label='가고 싶은 여행지가 있나요?',
placeholder='여행지를 입력해 주세요'
)
st.write(f'당신이 선택한 여행지: :violet[{title}]')
# 텍스트 영역 (여러 줄)
question = st.text_area(
'질문',
placeholder='질문을 입력해 주세요'
)
3.9 숫자 입력
# 숫자 입력
number = st.number_input(
label='나이를 입력해 주세요.',
min_value=10,
max_value=100,
value=30, # 기본값
step=5 # 증감 단위
)
st.write('당신이 입력하신 나이는: ', number)
3.10 날짜 입력
import datetime
# 날짜 선택
date = st.date_input(
"조회 시작일을 선택해 주세요",
datetime.datetime(2022, 1, 1)
)
4️⃣ 파일 업로드 기능
import time
# 파일 업로드
file = st.file_uploader("파일 선택(csv or excel)", type=['csv', 'xls', 'xlsx'])
# 파일 확장자에 따라 다르게 처리
if file is not None:
ext = file.name.split('.')[-1]
if ext == 'csv':
df = pd.read_csv(file)
st.dataframe(df)
elif 'xls' in ext:
df = pd.read_excel(file, engine='openpyxl')
st.dataframe(df)
특징:
type파라미터로 허용할 파일 형식 지정 가능함- 업로드된 파일은 즉시 처리 가능함
5️⃣ 차트 및 시각화
5.1 Matplotlib/Seaborn 차트
import matplotlib.pyplot as plt
import seaborn as sns
# 한글 폰트 설정
plt.rcParams['font.family'] = "AppleGothic" # Mac
# plt.rcParams['font.family'] = "NanumGothic" # Windows, Linux
plt.rcParams['axes.unicode_minus'] = False
# DataFrame 생성
data = pd.DataFrame({
'이름': ['영식', '철수', '영희'],
'나이': [22, 31, 25],
'몸무게': [75.5, 80.2, 55.1]
})
# Matplotlib 차트
fig, ax = plt.subplots()
ax.bar(data['이름'], data['나이'])
st.pyplot(fig)
# Seaborn 차트
barplot = sns.barplot(x='이름', y='나이', data=data, ax=ax, palette='Set2')
fig = barplot.get_figure()
st.pyplot(fig)
5.2 Streamlit 내장 차트
import FinanceDataReader as fdr
# 주식 데이터 가져오기
df = fdr.DataReader('005930', '2022-01-01') # 삼성전자
data = df.sort_index(ascending=True).loc[:, 'Close']
# 라인 차트
st.line_chart(data)
특징:
st.line_chart(),st.bar_chart(),st.area_chart()등 간단한 차트 제공함- 별도의 figure 생성 없이 바로 데이터를 시각화할 수 있음
5.3 Plotly 인터랙티브 차트
Plotly는 강력한 인터랙티브 차트 라이브러리로, Streamlit과 완벽하게 통합됨. 사용자가 차트를 확대/축소하고, 데이터 포인트를 탐색할 수 있는 동적 시각화를 제공함.
5.3.1 기본 Plotly 차트
import plotly.express as px
import plotly.graph_objects as go
# 샘플 데이터
df = pd.DataFrame({
'과일': ['사과', '바나나', '오렌지', '포도', '딸기'],
'판매량': [100, 150, 80, 120, 90]
})
# Plotly Express로 간단한 막대 차트
fig = px.bar(df, x='과일', y='판매량',
title='과일별 판매량',
color='판매량',
color_continuous_scale='Blues')
# Streamlit에 표시
st.plotly_chart(fig, use_container_width=True)
특징:
st.plotly_chart()함수로 Plotly 차트를 표시함use_container_width=True로 컨테이너 너비에 맞춰 차트 크기 조절 가능함- 자동으로 줌, 팬, 호버 등의 인터랙티브 기능 제공함
5.3.2 주식 캔들스틱 차트
import plotly.graph_objects as go
import FinanceDataReader as fdr
# 주식 데이터 가져오기
df = fdr.DataReader('005930', '2025-01-01', '2025-12-31') # 삼성전자
# 캔들스틱 차트 생성
fig = go.Figure(data=[go.Candlestick(
x=df.index,
open=df['Open'],
high=df['High'],
low=df['Low'],
close=df['Close'],
name='주가'
)])
# 레이아웃 설정
fig.update_layout(
title='삼성전자 주가 차트',
yaxis_title='주가 (원)',
xaxis_title='날짜',
template='plotly_dark', # 다크 테마
height=600
)
st.plotly_chart(fig, use_container_width=True)
특징:
- 캔들스틱 차트로 주식의 시가, 고가, 저가, 종가를 한눈에 볼 수 있음
template파라미터로 다양한 테마 적용 가능함 (plotly, plotly_white, plotly_dark 등)
5.3.3 이동평균선 추가
# 이동평균 계산
df['MA5'] = df['Close'].rolling(window=5).mean()
df['MA20'] = df['Close'].rolling(window=20).mean()
df['MA60'] = df['Close'].rolling(window=60).mean()
# 캔들스틱 차트 생성
fig = go.Figure()
# 캔들스틱 추가
fig.add_trace(go.Candlestick(
x=df.index,
open=df['Open'],
high=df['High'],
low=df['Low'],
close=df['Close'],
name='주가'
))
# 이동평균선 추가
fig.add_trace(go.Scatter(x=df.index, y=df['MA5'],
mode='lines', name='MA5',
line=dict(color='orange', width=1)))
fig.add_trace(go.Scatter(x=df.index, y=df['MA20'],
mode='lines', name='MA20',
line=dict(color='blue', width=1)))
fig.add_trace(go.Scatter(x=df.index, y=df['MA60'],
mode='lines', name='MA60',
line=dict(color='purple', width=1)))
# 레이아웃 설정
fig.update_layout(
title='주가 차트 with 이동평균선',
yaxis_title='주가 (원)',
xaxis_title='날짜',
template='plotly_white',
height=600,
xaxis_rangeslider_visible=False # 하단 범위 슬라이더 숨김
)
st.plotly_chart(fig, use_container_width=True)
5.3.4 서브플롯 (가격 + 거래량)
from plotly.subplots import make_subplots
# 서브플롯 생성 (2행 1열)
fig = make_subplots(
rows=2, cols=1,
shared_xaxes=True,
vertical_spacing=0.03,
row_heights=[0.7, 0.3],
subplot_titles=('주가', '거래량')
)
# 첫 번째 서브플롯: 캔들스틱
fig.add_trace(
go.Candlestick(
x=df.index,
open=df['Open'],
high=df['High'],
low=df['Low'],
close=df['Close'],
name='주가'
),
row=1, col=1
)
# 이동평균선 추가
fig.add_trace(
go.Scatter(x=df.index, y=df['MA20'],
mode='lines', name='MA20',
line=dict(color='blue', width=1)),
row=1, col=1
)
# 두 번째 서브플롯: 거래량
fig.add_trace(
go.Bar(x=df.index, y=df['Volume'], name='거래량',
marker_color='lightblue'),
row=2, col=1
)
# 레이아웃 설정
fig.update_layout(
title='주가 및 거래량 차트',
height=800,
template='plotly_white',
showlegend=True,
xaxis_rangeslider_visible=False
)
fig.update_xaxes(title_text="날짜", row=2, col=1)
fig.update_yaxes(title_text="주가 (원)", row=1, col=1)
fig.update_yaxes(title_text="거래량", row=2, col=1)
st.plotly_chart(fig, use_container_width=True)
특징:
make_subplots()로 여러 차트를 하나의 figure에 배치할 수 있음shared_xaxes=True로 x축을 공유하여 동기화된 줌/팬 가능함row_heights로 각 서브플롯의 높이 비율 조절 가능함
5.3.5 인터랙티브 드롭다운 메뉴
# 여러 종목 데이터 준비
stocks = {
'삼성전자': '005930',
'SK하이닉스': '000660',
'NAVER': '035420'
}
# 첫 번째 종목으로 초기 차트 생성
first_stock = list(stocks.keys())[0]
df = fdr.DataReader(stocks[first_stock], '2025-01-01', '2025-12-31')
# 모든 종목에 대한 trace 생성
fig = go.Figure()
for stock_name, stock_code in stocks.items():
df_temp = fdr.DataReader(stock_code, '2025-01-01', '2025-12-31')
fig.add_trace(go.Scatter(
x=df_temp.index,
y=df_temp['Close'],
name=stock_name,
visible=(stock_name == first_stock) # 첫 번째만 보이게
))
# 드롭다운 버튼 생성
buttons = []
for i, stock_name in enumerate(stocks.keys()):
# 각 버튼마다 어떤 trace를 보일지 설정
visible = [False] * len(stocks)
visible[i] = True
buttons.append(
dict(
label=stock_name,
method="update",
args=[{"visible": visible},
{"title": f"{stock_name} 주가 차트"}]
)
)
# 레이아웃에 드롭다운 추가
fig.update_layout(
updatemenus=[
dict(
active=0,
buttons=buttons,
direction="down",
pad={"r": 10, "t": 10},
showactive=True,
x=0.1,
xanchor="left",
y=1.15,
yanchor="top"
)
],
title=f"{first_stock} 주가 차트",
xaxis_title="날짜",
yaxis_title="주가 (원)",
template='plotly_white',
height=600
)
st.plotly_chart(fig, use_container_width=True)
특징:
updatemenus로 드롭다운, 버튼 등의 인터랙티브 컨트롤 추가 가능함method="update"로 차트 데이터와 레이아웃을 동적으로 변경할 수 있음- 사용자가 직접 차트를 조작하여 다양한 데이터를 탐색할 수 있음
5.3.6 Plotly Express로 빠른 시각화
import plotly.express as px
# 라인 차트
fig = px.line(df, x=df.index, y='Close',
title='종가 추이',
labels={'Close': '종가 (원)', 'index': '날짜'})
st.plotly_chart(fig, use_container_width=True)
# 영역 차트
fig = px.area(df, x=df.index, y='Volume',
title='거래량 추이',
labels={'Volume': '거래량', 'index': '날짜'})
st.plotly_chart(fig, use_container_width=True)
# 산점도
fig = px.scatter(df, x='Volume', y='Close',
title='거래량 vs 종가',
labels={'Volume': '거래량', 'Close': '종가 (원)'},
trendline="ols") # 추세선 추가
st.plotly_chart(fig, use_container_width=True)
# 히스토그램
fig = px.histogram(df, x='Close', nbins=50,
title='종가 분포',
labels={'Close': '종가 (원)'})
st.plotly_chart(fig, use_container_width=True)
Plotly Express vs Graph Objects:
- Plotly Express (px): 간단하고 빠른 차트 생성, 한 줄로 복잡한 차트 생성 가능함
- Graph Objects (go): 세밀한 커스터마이징 가능, 복잡한 차트 구성에 적합함
5.3.7 Streamlit과 Plotly 연동 팁
# 1. Streamlit 위젯으로 Plotly 차트 제어
chart_type = st.selectbox(
'차트 유형 선택',
['라인 차트', '영역 차트', '막대 차트']
)
if chart_type == '라인 차트':
fig = px.line(df, x=df.index, y='Close')
elif chart_type == '영역 차트':
fig = px.area(df, x=df.index, y='Close')
else:
fig = px.bar(df, x=df.index, y='Close')
st.plotly_chart(fig, use_container_width=True)
# 2. 컬러 스케일 선택
color_scale = st.selectbox(
'컬러 스케일',
['Blues', 'Reds', 'Greens', 'Viridis', 'Plasma']
)
fig = px.bar(df.head(10), x=df.head(10).index, y='Close',
color='Close',
color_continuous_scale=color_scale)
st.plotly_chart(fig, use_container_width=True)
# 3. 날짜 범위 필터링
col1, col2 = st.columns(2)
with col1:
start_date = st.date_input('시작일', df.index.min())
with col2:
end_date = st.date_input('종료일', df.index.max())
# 필터링된 데이터로 차트 생성
filtered_df = df.loc[start_date:end_date]
fig = px.line(filtered_df, x=filtered_df.index, y='Close',
title=f'{start_date} ~ {end_date} 주가 추이')
st.plotly_chart(fig, use_container_width=True)
Plotly 주요 장점:
- ✅ 완전한 인터랙티브 차트 (줌, 팬, 호버, 선택 등)
- ✅ 전문적인 금융 차트 (캔들스틱, OHLC 등) 지원함
- ✅ 다양한 차트 타입과 커스터마이징 옵션 제공함
- ✅ 서브플롯으로 복잡한 대시보드 구성 가능함
- ✅ 드롭다운, 슬라이더 등 내장 인터랙티브 컨트롤 제공함
- ✅ 반응형 디자인으로 모바일에서도 잘 작동함
6️⃣ 레이아웃 기능
6.1 컬럼 (Columns)
# 3개의 컬럼으로 나누기
col1, col2, col3 = st.columns(3)
col1.metric(label="달러USD", value="1,228 원", delta="-12.00 원")
col2.metric(label="일본JPY(100엔)", value="958.63 원", delta="-7.44 원")
col3.metric(label="유럽연합EUR", value="1,335.82 원", delta="11.44 원")
화면을 여러 컬럼으로 나누어 콘텐츠를 배치할 수 있음.
6.2 사이드바 (Sidebar)
# 사이드바에 위젯 배치
with st.sidebar:
date = st.date_input(
"조회 시작일을 선택해 주세요",
datetime.datetime(2022, 1, 1)
)
code = st.text_input(
'종목코드',
value='',
placeholder='종목코드를 입력해 주세요'
)
사이드바를 활용하여 입력 위젯을 깔끔하게 정리할 수 있음.
6.3 탭 (Tabs)
# 탭 생성
tab1, tab2 = st.tabs(['차트', '데이터'])
with tab1:
st.line_chart(data)
with tab2:
st.dataframe(df.sort_index(ascending=False))
콘텐츠를 탭으로 구분하여 표시할 수 있음.
6.4 확장 가능한 영역 (Expander)
# 접었다 펼 수 있는 영역
with st.expander('컬럼 설명'):
st.markdown('''
- Open: 시가
- High: 고가
- Low: 저가
- Close: 종가
- Adj Close: 수정 종가
- Volume: 거래량
''')
추가 정보를 접어두고 필요할 때만 펼쳐볼 수 있음.
7️⃣ 캐싱 기능
@st.cache
def read_pensiondata():
data = PensionData('https://www.dropbox.com/s/nxeo1tziv05ejz7/national-pension.csv?dl=1')
return data
# 함수 호출 시 캐싱됨
data = read_pensiondata()
특징:
@st.cache데코레이터를 사용하면 함수 결과를 캐싱함- 동일한 입력에 대해 함수를 다시 실행하지 않아 성능이 크게 향상됨
- 데이터 로딩, API 호출 등 시간이 오래 걸리는 작업에 필수적임
8️⃣ 외부 API 연동 예제
8.1 Naver Clova API 연동
import json
import configparser
import http.client
class CompletionExecutor:
def __init__(self, host, api_key, api_key_primary_val, request_id):
self._host = host
self._api_key = api_key
self._api_key_primary_val = api_key_primary_val
self._request_id = request_id
def _send_request(self, completion_request):
headers = {
'Content-Type': 'application/json; charset=utf-8',
'X-NCP-CLOVASTUDIO-API-KEY': self._api_key,
'X-NCP-APIGW-API-KEY': self._api_key_primary_val,
'X-NCP-CLOVASTUDIO-REQUEST-ID': self._request_id
}
conn = http.client.HTTPSConnection(self._host)
conn.request('POST', '/testapp/v1/completions/LK-D',
json.dumps(completion_request), headers)
response = conn.getresponse()
result = json.loads(response.read().decode(encoding='utf-8'))
conn.close()
return result
def execute(self, completion_request):
res = self._send_request(completion_request)
if res['status']['code'] == '20000':
return res['result']['text']
else:
return 'Error'
# API 키 설정
config = configparser.ConfigParser()
config.read('./your_apikey.ini')
completion_executor = CompletionExecutor(
host=config['CLOVA']['host'],
api_key=config['CLOVA']['api_key'],
api_key_primary_val=config['CLOVA']['api_key_primary_val'],
request_id=config['CLOVA']['request_id']
)
# Streamlit UI
st.title('나만의 챗봇')
preset_input = st.selectbox(
'사전 문장',
('MBTI에 대한 지식을 기반으로, 아래의 질문에 답해보세요.',
'키워드를 포함하여 설날 인사말을 생성합니다.',
'30대 남성으로 질문에 군인말투로 끝을 다,나,까로 대답한다.'),
index=1
)
question = st.text_area('질문', placeholder='질문을 입력해 주세요')
if preset_input and question:
preset_text = f'{preset_input}\n\n질문:{question}'
request_data = {
'text': preset_text,
'maxTokens': 100,
'temperature': 0.5,
'topK': 0,
'topP': 0.8,
'repeatPenalty': 5.0,
'start': '\n###답:',
'stopBefore': ['###', '질문:', '답:', '###\n'],
'includeTokens': True,
'includeAiFilters': True,
'includeProbs': True
}
response_text = completion_executor.execute(request_data)
st.markdown(response_text.split('###')[1])
8.2 Bitly URL 단축 API
import bitlyshortener
import configparser
# API 키 설정
config = configparser.ConfigParser()
config.read('./your_apikey.ini')
access_tokens = [config['bitly']['access_token']]
shortener = bitlyshortener.Shortener(tokens=access_tokens)
# Streamlit UI
url = st.text_input('URL을 입력해 주세요')
if url:
shortened = shortener.shorten_urls([url])
st.markdown(f'''
### URL이 생성되었습니다:sparkles:
**긴 주소**
''')
st.code(f'{url}')
st.markdown(f'**짧은 주소**')
st.code(f'{shortened[0]}')
9️⃣ 실전 프로젝트 예제
9.1 로또 번호 생성기
import random
import datetime
st.title(':sparkles:로또 생성기:sparkles:')
def generate_lotto():
lotto = set()
while len(lotto) < 6:
number = random.randint(1, 46)
lotto.add(number)
lotto = list(lotto)
lotto.sort()
return lotto
button = st.button('로또를 생성해 주세요!')
if button:
for i in range(1, 6):
st.subheader(f'{i}. 행운의 번호: :green[{generate_lotto()}]')
st.write(f"생성된 시각: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M')}")
9.2 주식 차트 검색 앱
import FinanceDataReader as fdr
import datetime
st.title('종목 차트 검색')
with st.sidebar:
date = st.date_input(
"조회 시작일을 선택해 주세요",
datetime.datetime(2022, 1, 1)
)
code = st.text_input(
'종목코드',
value='',
placeholder='종목코드를 입력해 주세요'
)
if code and date:
df = fdr.DataReader(code, date)
data = df.sort_index(ascending=True).loc[:, 'Close']
tab1, tab2 = st.tabs(['차트', '데이터'])
with tab1:
st.line_chart(data)
with tab2:
st.dataframe(df.sort_index(ascending=False))
with st.expander('컬럼 설명'):
st.markdown('''
- Open: 시가
- High: 고가
- Low: 저가
- Close: 종가
- Adj Close: 수정 종가
- Volume: 거래량
''')
9.3 국민연금 급여 조회 앱
이 앱은 국민연금 데이터를 기반으로 회사별 급여를 추정하는 복잡한 예제임.
주요 기능:
- 회사명으로 검색
- 해당 회사의 월급여 및 연봉 추정
- 동종 업계 평균과 비교
- 시각화를 통한 비교 분석
# 회사 검색
company_name = st.text_input('회사명을 입력해 주세요', placeholder='검색할 회사명 입력')
if data and company_name:
output = data.find_company(company_name=company_name)
if len(output) > 0:
st.subheader(output.iloc[0]['사업장명'])
info = data.company_info(company_name=company_name)
# 회사 정보 표시
st.markdown(f"""
- `{info['주소']}`
- 업종코드명 `{info['업종코드명']}`
- 총 근무자 `{int(info['가입자수']):,}` 명
- 신규 입사자 `{info['신규']:,}` 명
- 퇴사자 `{info['상실']:,}` 명
""")
# 메트릭 표시
col1, col2, col3 = st.columns(3)
col1.text('월급여 추정')
col1.markdown(f"`{int(output.iloc[0]['월급여추정']):,}` 원")
col2.text('연봉 추정')
col2.markdown(f"`{int(output.iloc[0]['연간급여추정']):,}` 원")
col3.text('가입자수 추정')
col3.markdown(f"`{int(output.iloc[0]['가입자수']):,}` 명")
🔟 유용한 팁
1. 한글 폰트 설정
# Matplotlib 한글 폰트 설정
plt.rcParams['font.family'] = "AppleGothic" # Mac
# plt.rcParams['font.family'] = "NanumGothic" # Windows, Linux
plt.rcParams['axes.unicode_minus'] = False # 마이너스 기호 깨짐 방지
2. API 키 관리
# .ini 파일로 API 키 관리
import configparser
config = configparser.ConfigParser()
config.read('./your_apikey.ini')
api_key = config['SECTION']['key_name']
your_apikey.ini 예시:
[CLOVA]
host = clovastudio.apigw.ntruss.com
api_key = your_api_key_here
api_key_primary_val = your_primary_key_here
request_id = your_request_id_here
[bitly]
access_token = your_bitly_token_here
3. 데이터 포맷팅
# 숫자 천 단위 콤마
st.write(f"{1234567:,}") # 1,234,567
# 소수점 자리수 제한
st.write(f"{3.141592:.2f}") # 3.14
4. 조건부 렌더링
# 입력값이 있을 때만 처리
if code and date:
# 데이터 처리 및 표시
pass
📚 결론
Streamlit은 Python 개발자가 빠르게 데이터 애플리케이션을 만들 수 있는 강력한 도구임.
주요 장점:
- ✅ 간단한 문법으로 빠른 개발 가능함
- ✅ 다양한 위젯과 차트 지원함
- ✅ Plotly를 통한 강력한 인터랙티브 시각화 가능함
- ✅ 외부 API 연동이 쉬움
- ✅ 캐싱 기능으로 성능 최적화 가능함
- ✅ 레이아웃 기능으로 깔끔한 UI 구성 가능함
활용 분야:
- 📊 데이터 대시보드
- 🤖 머신러닝 모델 데모
- 📈 주식/금융 분석 도구 (Plotly 캔들스틱 차트 활용)
- 🔍 데이터 탐색 도구
- 💬 챗봇 인터페이스
- 📉 인터랙티브 비즈니스 리포트
Streamlit을 활용하면 복잡한 웹 개발 지식 없이도 전문적인 데이터 애플리케이션을 만들 수 있음!
🔗 참고 자료
- Streamlit 공식 문서: https://docs.streamlit.io/
- Streamlit 이모티콘: https://streamlit-emoji-shortcodes-streamlit-app-gwckff.streamlit.app/
- FinanceDataReader: https://github.com/financedata-org/FinanceDataReader
- Plotly 공식 문서: https://plotly.com/python/
- Plotly Graph Objects: https://plotly.com/python/graph-objects/
- Plotly Express: https://plotly.com/python/plotly-express/
Comments