Streamlit으로 데이터 분석 웹 앱 만들기: UI부터 모델 입력까지

Alchemist·2026년 9월 28일

KT AIVLE

목록 보기
26/130

Python으로 데이터 분석을 하다 보면 결과를 노트북 안에서만 확인하는 데 한계가 생긴다.
분석 결과를 다른 사람에게 보여주거나, 사용자가 직접 옵션을 바꿔가며 결과를 확인하게 하려면 웹 UI가 필요하다.

이때 Streamlit을 사용하면 HTML, CSS, JavaScript를 직접 작성하지 않아도 Python 코드만으로 데이터 분석용 웹 애플리케이션을 빠르게 만들 수 있다.

이번 글에서는 Streamlit의 기본 구조부터 텍스트, 데이터프레임, 입력 위젯, 차트, 버튼 이벤트까지 한 흐름으로 정리한다.

Python 데이터/모델
    ↓
Streamlit UI
    ↓
사용자 입력
    ↓
분석 또는 예측
    ↓
브라우저에서 결과 확인

Streamlit은 어떤 도구인가?

Streamlit은 Python 기반의 데이터 앱을 빠르게 만들기 위한 오픈소스 프레임워크다.

일반적인 웹 애플리케이션을 만들려면 프론트엔드와 백엔드를 따로 구성해야 하는 경우가 많지만, Streamlit은 Python 코드 안에서 화면 구성과 데이터 처리를 함께 작성할 수 있다.

예를 들어 다음과 같은 작업에 잘 어울린다.

  • 데이터 분석 결과 공유
  • 머신러닝 모델 데모
  • 내부 운영용 대시보드
  • 데이터 탐색 도구
  • 간단한 통계 리포트
  • 모델 입력값 테스트 화면

특히 분석 결과를 빠르게 웹 화면으로 보여주는 용도에서 진입장벽이 낮다.


먼저 설치하기

가상환경을 사용하고 있다면 해당 환경을 활성화한 뒤 설치하는 것이 좋다.

pip

pip install streamlit

Conda 환경에서 pip 사용

conda activate data_env
pip install streamlit

설치 여부는 다음 명령어로 확인할 수 있다.

streamlit --version

정상적으로 버전이 출력되면 준비가 끝난다.


가장 중요한 실행 방법

Streamlit 파일을 일반 Python 프로그램처럼 실행하면 웹 앱이 정상적으로 열리지 않을 수 있다.

예를 들어 다음처럼 실행하는 것은 Streamlit 앱 실행 방식이 아니다.

python app.py

Streamlit 앱은 반드시 다음처럼 실행한다.

streamlit run app.py

실행하면 기본적으로 로컬 웹 서버가 열리고 브라우저에서 확인할 수 있다.

보통 개발 환경에서는 다음 주소가 사용된다.

http://localhost:8501

만약 IDE에서 python app.py로 실행했는데 다음과 비슷한 안내가 보인다면,

To view this Streamlit app on a browser,
run it with the following command:

streamlit run app.py

코드 오류라기보다 실행 방식이 잘못된 경우다.


가장 작은 Streamlit 앱

app.py 파일을 하나 만들고 다음 코드부터 시작해보자.

import streamlit as st

st.title("서비스 데이터 대시보드")
st.write("Streamlit으로 만든 간단한 데이터 앱입니다.")

터미널에서 실행한다.

streamlit run app.py

브라우저에 제목과 문장이 표시된다면 기본 환경은 정상적으로 구성된 것이다.


Streamlit UI는 위에서 아래로 그려진다

Streamlit 코드의 중요한 특징은 작성한 순서대로 화면이 구성된다는 점이다.

import streamlit as st

st.title("대시보드")
st.header("오늘의 서비스 지표")
st.write("사용자 행동 데이터를 확인합니다.")

화면도 그대로 다음 순서로 표시된다.

대시보드
↓
오늘의 서비스 지표
↓
사용자 행동 데이터를 확인합니다.

처음 사용할 때는 이 단순한 구조를 이해하는 것이 중요하다.


텍스트를 표현하는 주요 함수

Streamlit은 제목, 설명, Markdown, 코드 등을 바로 출력할 수 있다.

import streamlit as st

st.title("서비스 분석")
st.header("트래픽 현황")
st.subheader("최근 7일")
st.write("API 요청량과 오류율을 확인합니다.")

st.markdown("""
**체크 포인트**

- 요청량
- 평균 응답시간
- 오류율
""")

자주 사용하는 함수는 다음과 같다.

함수용도
st.title()페이지 대표 제목
st.header()큰 섹션 제목
st.subheader()하위 섹션 제목
st.write()문자열, 객체 등을 범용적으로 출력
st.markdown()Markdown 문법 사용
st.code()코드 블록 출력
st.caption()보조 설명

데이터프레임 표시하기

데이터 분석 앱에서는 표를 보여주는 기능이 중요하다.

간단한 예제 데이터를 만들어보자.

import pandas as pd
import streamlit as st

df = pd.DataFrame({
    "endpoint": ["/login", "/products", "/cart", "/orders"],
    "requests": [1820, 3540, 1210, 890],
    "avg_latency_ms": [118, 96, 132, 165],
    "error_rate": [0.8, 0.4, 1.2, 0.9]
})

Streamlit에서는 다음처럼 출력할 수 있다.

st.dataframe(df)

st.dataframe()은 스크롤과 정렬 등 인터랙티브한 표 기능을 제공한다.

단순 정적 표가 필요하다면 다음도 사용할 수 있다.

st.table(df)

둘의 차이는 간단하다.

함수특징
st.dataframe()인터랙티브한 데이터 탐색에 적합
st.table()고정된 정적 표에 적합

분석용 화면이라면 대부분 st.dataframe()이 더 편하다.


체크박스로 화면 표시 여부 제어하기

사용자에게 필요한 정보만 선택해서 보여주고 싶다면 체크박스를 사용할 수 있다.

show_raw = st.checkbox("원본 데이터 보기")

if show_raw:
    st.dataframe(df)

핵심은 위젯이 값을 반환한다는 점이다.

checkbox 선택
    ↓
True
    ↓
if 문 실행
    ↓
데이터 출력

Streamlit의 많은 UI 요소는 이처럼 Python 변수와 바로 연결된다.


selectbox로 분석 항목 선택하기

여러 옵션 중 하나를 선택하게 하고 싶다면 selectbox가 편하다.

metric = st.selectbox(
    "확인할 지표를 선택하세요",
    [
        "요청량",
        "평균 응답시간",
        "오류율"
    ]
)

선택된 값은 일반 Python 문자열로 사용할 수 있다.

if metric == "요청량":
    st.bar_chart(
        df.set_index("endpoint")["requests"]
    )

elif metric == "평균 응답시간":
    st.bar_chart(
        df.set_index("endpoint")["avg_latency_ms"]
    )

else:
    st.bar_chart(
        df.set_index("endpoint")["error_rate"]
    )

이렇게 하면 하나의 페이지에서도 사용자가 보고 싶은 분석을 직접 바꿀 수 있다.


slider로 범위 입력받기

수치 범위를 직관적으로 조절할 때는 slider가 유용하다.

threshold = st.slider(
    "응답시간 경고 기준(ms)",
    min_value=50,
    max_value=500,
    value=150,
    step=10
)

선택된 값은 그대로 숫자로 사용할 수 있다.

slow_api = df[
    df["avg_latency_ms"] >= threshold
]

st.dataframe(slow_api)

이렇게 하면 사용자가 기준값을 바꿀 때마다 결과가 다시 계산된다.


radio로 명확한 선택지 만들기

선택지가 적고 모두 화면에 보여야 한다면 radio가 적합하다.

mode = st.radio(
    "조회 방식",
    [
        "전체 보기",
        "오류율 높은 API만 보기"
    ]
)
if mode == "전체 보기":
    result = df
else:
    result = df[df["error_rate"] >= 1.0]

st.dataframe(result)

selectbox와 비교하면 다음과 같다.

위젯적합한 경우
selectbox선택지가 많거나 화면을 작게 쓰고 싶을 때
radio선택지가 적고 모두 바로 보여주고 싶을 때

number_input으로 숫자 입력받기

모델이나 계산식에 숫자를 직접 넣어야 한다면 number_input을 사용할 수 있다.

requests = st.number_input(
    "예상 요청량",
    min_value=0,
    value=1000,
    step=100
)

latency = st.number_input(
    "평균 응답시간(ms)",
    min_value=0.0,
    value=120.0,
    step=5.0
)

반환값은 일반 숫자이므로 바로 계산에 사용할 수 있다.

load_score = requests * latency

st.write("간단한 부하 점수:", load_score)

버튼으로 계산 실행하기

입력값을 모두 받은 뒤 특정 시점에만 계산하고 싶다면 버튼을 사용한다.

if st.button("분석 실행"):
    score = requests * latency

    st.success(
        f"계산된 부하 점수는 {score:,.0f}입니다."
    )

이 구조는 머신러닝 예측 화면에서도 거의 동일하게 사용된다.

사용자 입력
    ↓
버튼 클릭
    ↓
전처리
    ↓
model.predict()
    ↓
결과 출력

상태 메시지 보여주기

Streamlit은 상태에 맞는 메시지를 쉽게 출력할 수 있다.

st.success("데이터 로딩이 완료되었습니다.")
st.info("분석 조건을 선택하세요.")
st.warning("응답시간이 기준값을 초과했습니다.")
st.error("데이터를 불러오지 못했습니다.")

데이터 앱에서는 처리 상태를 사용자에게 알려주는 것이 중요하다.


화면을 여러 열로 나누기

대시보드처럼 정보를 좌우로 배치하고 싶다면 st.columns()를 사용할 수 있다.

col1, col2, col3 = st.columns(3)

with col1:
    st.metric("요청량", "7,460")

with col2:
    st.metric("평균 응답시간", "128 ms")

with col3:
    st.metric("오류율", "0.8%")

이 방식은 KPI 카드 형태의 화면을 만들 때 자주 사용한다.


사이드바 활용하기

필터나 설정값은 본문보다 사이드바에 두는 것이 깔끔한 경우가 많다.

service = st.sidebar.selectbox(
    "서비스",
    [
        "전체",
        "인증",
        "상품",
        "주문"
    ]
)

min_requests = st.sidebar.slider(
    "최소 요청량",
    0,
    5000,
    500
)

본문에는 결과만 남길 수 있어 대시보드 구성이 더 명확해진다.


이미지 표시하기

로고나 분석 결과 이미지를 넣고 싶다면 st.image()를 사용할 수 있다.

st.image(
    "./assets/service-logo.png",
    width=160
)

프로젝트에서는 사용자 환경에 종속된 절대 경로보다 상대 경로를 사용하는 편이 관리하기 쉽다.

project/
├─ app.py
└─ assets/
   └─ service-logo.png

Matplotlib과 Seaborn 그래프도 출력할 수 있다

Streamlit이 자체 차트를 제공하지만 기존 Matplotlib/Seaborn 코드도 그대로 활용할 수 있다.

import matplotlib.pyplot as plt
import seaborn as sns

fig, ax = plt.subplots()

sns.scatterplot(
    data=df,
    x="requests",
    y="avg_latency_ms",
    ax=ax
)

st.pyplot(fig)

즉 기존 분석 노트북의 시각화 코드를 완전히 새로 작성할 필요 없이 웹 UI에 연결하는 방식으로 확장할 수 있다.


머신러닝 모델과 연결하는 기본 패턴

Streamlit은 이미 학습된 모델의 입력 화면을 만들 때도 많이 사용한다.

예를 들어 서비스 트래픽을 이용해 부하 점수를 예측하는 모델이 있다고 가정해보자.

import joblib
import numpy as np
import streamlit as st

model = joblib.load("./model.pkl")
scaler = joblib.load("./scaler.pkl")

사용자 입력을 받는다.

requests = st.number_input(
    "분당 요청량",
    min_value=0.0,
    value=1000.0
)

latency = st.number_input(
    "평균 응답시간(ms)",
    min_value=0.0,
    value=120.0
)

error_rate = st.number_input(
    "오류율(%)",
    min_value=0.0,
    max_value=100.0,
    value=1.0
)

버튼을 눌렀을 때 모델에 전달한다.

if st.button("예측하기"):
    new_data = np.array([
        requests,
        latency,
        error_rate
    ]).reshape(1, -1)

    scaled_data = scaler.transform(new_data)

    prediction = model.predict(
        scaled_data
    )

    st.success(
        f"예측 결과: {prediction[0]:.3f}"
    )

여기서 중요한 것은 학습 때 사용한 전처리를 예측 때도 동일하게 적용해야 한다는 점이다.

학습 데이터
→ scaler.fit()
→ scaler.transform()
→ model.fit()

새 입력
→ 같은 scaler.transform()
→ model.predict()

새로운 입력에서 다시 fit()하면 학습 당시 기준이 달라지므로 올바른 예측이 되지 않는다.


Streamlit 앱의 실행 구조 이해하기

Streamlit을 처음 사용할 때 가장 헷갈리는 부분 중 하나는 위젯 값이 바뀔 때 스크립트가 다시 실행된다는 점이다.

예를 들어 다음 코드가 있다고 하자.

value = st.slider(
    "값",
    0,
    100,
    50
)

st.write(value)

슬라이더를 움직이면 앱이 해당 시점의 값으로 다시 계산된다.

이를 단순하게 표현하면 다음과 같다.

사용자 입력 변경
    ↓
스크립트 재실행
    ↓
현재 위젯 상태 반영
    ↓
화면 다시 렌더링

따라서 일반적인 GUI 프레임워크처럼 모든 이벤트마다 별도 콜백을 작성하지 않아도 된다.

이 단순한 실행 모델이 Streamlit의 큰 장점이다.


하나의 작은 데이터 앱 만들어보기

지금까지 사용한 기능을 하나로 묶어보자.

import pandas as pd
import streamlit as st


st.set_page_config(
    page_title="API Metrics Dashboard",
    layout="wide"
)


st.title("API Metrics Dashboard")

df = pd.DataFrame({
    "endpoint": [
        "/login",
        "/products",
        "/cart",
        "/orders"
    ],
    "requests": [
        1820,
        3540,
        1210,
        890
    ],
    "avg_latency_ms": [
        118,
        96,
        132,
        165
    ],
    "error_rate": [
        0.8,
        0.4,
        1.2,
        0.9
    ]
})


metric = st.sidebar.selectbox(
    "확인할 지표",
    [
        "요청량",
        "평균 응답시간",
        "오류율"
    ]
)


show_table = st.sidebar.checkbox(
    "원본 데이터 보기"
)


col1, col2, col3 = st.columns(3)

with col1:
    st.metric(
        "전체 요청량",
        f"{df['requests'].sum():,}"
    )

with col2:
    st.metric(
        "평균 응답시간",
        f"{df['avg_latency_ms'].mean():.1f} ms"
    )

with col3:
    st.metric(
        "평균 오류율",
        f"{df['error_rate'].mean():.2f}%"
    )


if show_table:
    st.subheader("원본 데이터")
    st.dataframe(df)


st.subheader("지표 시각화")

chart_df = df.set_index("endpoint")

if metric == "요청량":
    st.bar_chart(
        chart_df["requests"]
    )

elif metric == "평균 응답시간":
    st.bar_chart(
        chart_df["avg_latency_ms"]
    )

else:
    st.bar_chart(
        chart_df["error_rate"]
    )

실행한다.

streamlit run app.py

이 정도 코드만으로도 다음 기능을 가진 간단한 데이터 앱이 된다.

사이드바 필터
+
KPI 카드
+
데이터프레임
+
선택 가능한 차트

개발자 관점에서 기억할 점

Streamlit은 전통적인 웹 프레임워크와 접근 방식이 다르다.

구분일반적인 웹 앱Streamlit
화면 구성HTML/JS/프레임워크Python 함수
상태 처리이벤트·상태 관리 필요위젯 상태 기반 재실행
목적범용 웹 서비스데이터/AI 앱
개발 속도구조 설계 필요빠른 프로토타이핑
UI 자유도높음상대적으로 제한적

따라서 Streamlit은 React나 Next.js를 대체하는 도구라기보다 데이터 분석 결과를 빠르게 제품 형태로 보여주는 도구에 가깝다.

예를 들어 다음 상황에서 특히 효율적이다.

모델 개발
    ↓
Jupyter Notebook 검증
    ↓
Streamlit 데모 앱
    ↓
사용자 피드백
    ↓
필요하면 정식 서비스로 확장

AI/데이터 프로젝트에서는 이 중간 단계가 상당히 유용하다.


자주 헷갈리는 부분

1. python app.py와 streamlit run app.py

Streamlit 앱은 다음 명령어로 실행해야 한다.

streamlit run app.py

2. st.table()과 st.dataframe()

탐색 가능한 표가 필요하면 st.dataframe()을 사용하는 것이 좋다.

st.dataframe(df)

3. 위젯 값은 바로 Python 변수다

selected = st.selectbox(
    "선택",
    ["A", "B", "C"]
)

selected에는 선택된 문자열이 저장된다.

4. 버튼은 조건문과 함께 사용한다

if st.button("실행"):
    st.success("작업 완료")

5. 모델 예측에서는 학습 시 전처리를 재사용한다

new_data = scaler.transform(new_data)
prediction = model.predict(new_data)

새 데이터로 scaler를 다시 학습시키면 안 된다.


핵심 정리

  • Streamlit은 Python만으로 데이터/AI 웹 앱을 빠르게 만들 수 있는 프레임워크다.
  • 실행할 때는 python app.py가 아니라 streamlit run app.py를 사용한다.
  • st.title(), st.header(), st.markdown() 등으로 텍스트 UI를 구성할 수 있다.
  • st.dataframe()을 사용하면 데이터프레임을 인터랙티브하게 표시할 수 있다.
  • checkbox, radio, selectbox, slider, number_input, button 등 다양한 입력 위젯을 사용할 수 있다.
  • 위젯의 반환값은 일반 Python 변수처럼 조건문과 계산에 사용할 수 있다.
  • st.columns()와 st.sidebar를 활용하면 간단한 대시보드 레이아웃을 만들 수 있다.
  • Matplotlib과 Seaborn 그래프도 st.pyplot()으로 연결할 수 있다.
  • 학습된 모델을 불러와 사용자 입력을 받아 예측 결과를 보여주는 웹 앱도 쉽게 만들 수 있다.
  • Streamlit은 범용 프론트엔드 프레임워크보다는 데이터 분석, 모델 데모, 내부 대시보드의 빠른 구현에 강점이 있다.

정리하며

Streamlit의 핵심은 웹 개발 문법을 많이 배우는 것이 아니라 Python 코드와 UI를 직접 연결하는 방식을 이해하는 데 있다.

기본 흐름은 생각보다 단순하다.

데이터 또는 모델 준비
→ UI 구성
→ 사용자 입력 받기
→ Python 코드 실행
→ 결과 화면 출력

분석 코드를 Jupyter Notebook 안에만 두는 것과, 사용자가 직접 조작할 수 있는 웹 화면으로 만드는 것은 활용도에서 큰 차이가 있다.

특히 데이터 분석이나 머신러닝 프로젝트에서는 Streamlit을 이용해 결과를 빠르게 웹 앱 형태로 만들어보는 것만으로도 분석 결과 공유 → 사용자 테스트 → 프로토타입 검증까지 자연스럽게 연결할 수 있다.

profile
html_programming_language

0개의 댓글