나는 처음으로 Streamlit을 시도하고 MLB 배트 트래킹 대시보드를 만들었다
Source: Dev.to
위에 제공된 소스 링크 외에 번역하고 싶은 텍스트를 알려주시면, 해당 내용을 한국어로 번역해 드리겠습니다.
What I Built
I built a web dashboard to visualize MLB bat tracking data from Baseball Savant.

The dashboard has five tabs:
| Tab | What it shows |
|---|---|
| Leaderboard | Rankings by Bat Speed, Attack Angle, and more |
| Player Comparison | Radar & bar charts comparing up to 6 players |
| WBC Country Strength | Batting & pitching scores for all 20 WBC 2026 nations |
| Team Lineup Builder | Bat‑tracking metrics for each MLB team’s 9‑man lineup |
| Monthly Trend | Month‑by‑month bat speed trend for any player |
It also supports English/Japanese language switching.
데이터 소스
저는 자체 오픈‑소스 라이브러리 savant‑extras를 사용하여 데이터를 가져왔습니다.
pip install savant-extras
from savant_extras import bat_tracking, bat_tracking_monthly
# Batter bat tracking data for 2025 season
df = bat_tracking(year=2025, player_type="batter")
# Monthly breakdown
df_monthly = bat_tracking_monthly(year=2025)
- GitHub:
- PyPI:
왜 나는 Streamlit을 선택했는가
데이터 분석을 시각적이고 접근하기 쉬운 형태로 공유하고 싶었습니다. Streamlit은 세 가지 이유로 매력적이었습니다:
- Pure Python – HTML, CSS, JavaScript가 필요 없습니다.
- 무료 호스팅 Streamlit Community Cloud에서 (GitHub 저장소만 연결하면 됩니다).
- 한 줄 UI 컴포넌트 – 예:
st.selectbox(),st.slider().
예시: 사이드바에 드롭다운 추가하기.
import streamlit as st
year = st.sidebar.selectbox("Season", [2024, 2025], index=1)
player_type = st.sidebar.selectbox("Player type", ["batter", "pitcher"])
핵심 구현 포인트
API 호출 캐싱
매 인터랙션마다 데이터를 가져오면 너무 느립니다. @st.cache_data는 결과를 캐시하여 동일한 인수로 반복 호출 시 즉시 반환합니다.
@st.cache_data(ttl=3600)
def load_bat_data(year: int, player_type: str):
return bat_tracking(year=year, player_type=player_type)
탭 간 데이터 공유
Streamlit은 각 인터랙션마다 스크립트를 다시 실행합니다. 버튼을 눌러 데이터를 로드한 뒤에는 st.session_state를 사용해 데이터를 유지합니다.
if load_btn:
st.session_state["df_raw"] = load_bat_data(year, player_type)
if "df_raw" in st.session_state:
df = st.session_state["df_raw"]
일본어 폰트 지원
Matplotlib 차트에 일본어 라벨을 표시하기 위해 matplotlib-fontja를 사용했습니다.
import matplotlib_fontja # noqa: F401 ← import 하면 일본어 폰트가 활성화됩니다
겪은 문제: Python 3.13에서 japanize_matplotlib
Streamlit Community Cloud에 배포하면서 Python 3.13에서 distutils가 제거되어 오류가 발생했습니다.
File "japanize_matplotlib/japanize_matplotlib.py", line 5, in
from distutils.version import LooseVersion
ModuleNotFoundError
해결 방법은 japanize-matplotlib을 matplotlib-fontja로 교체하는 것이었습니다.
- japanize-matplotlib>=1.1
+ matplotlib-fontja
데이터 주의사항
- MLB 로스터에 포함된 선수들만 포함됩니다; NPB 및 마이너리그 선수는 제외됩니다.
- 이름 매칭 제한 – 철자 변형이나 동명이인 경우 정확히 매치되지 않을 수 있습니다.
- WBC 2026 점수는 임시 – 로스터는 Baseball America의 2025년 2월 예측을 기반으로 하며 실제 로스터와 다를 수 있습니다.
- 배트 트래킹 정확도는 Baseball Savant 데이터 품질에 따라 달라집니다.
결과는 참고용으로 활용하시고, 최종적인 출처로 사용하지 마세요.
요약
- savant‑extras(내 OSS 라이브러리)를 사용해 데이터를 가져왔습니다.
- Streamlit으로 5개의 탭 대시보드를 만들었습니다.
- Streamlit Community Cloud에 무료로 배포했습니다.
Streamlit은 예상보다 쉬웠습니다. st.tabs() 로 탭을 만들고, st.expander() 로 아코디언을 만들며, st.columns() 로 컬럼 레이아웃을 구성하면 대부분의 기능을 구현할 수 있습니다. 데이터 분석을 공유 가능한 형태로 만들고 싶다면 Streamlit이 좋은 선택입니다.
링크
- 앱:
- savant‑extras (PyPI):
- savant‑extras (GitHub):
- Baseball Savant: