NLP Development/Streamlit

데이터 과학자를 위한 웹 개발 도구 Streamlit - 상태 관리 & 상호 작용

patrick610 2025. 7. 13. 20:43
반응형
SMALL

 

 

 

 

Streamlit에서는 상태 관리와 상호 작용을 위한 여러 기능들을 제공합니다.

예를 들면 상태 관리는 로그인, 필터 조건, 폼 입력 같은 경우, 페이지를 다시 로드하거나 돌아가도 값이 살아있는 상태로 지니고 있을 수 있습니다.

상호 작용은 용량이 큰 데이터와 머신러닝/딥러닝 모델을 캐시로 저장하여 빠르게 반환할 수 있습니다.


상태 관리

💾 세션 상태 유지 st.session_state

Streamlit 앱은 버튼 클릭이나 입력 등 모든 상호작용 이후 스크립트를 처음부터 다시 실행합니다.

그러나 st.session_state를 사용하면 세션 변수를 저장해 동일 사용자에 대한 값들이 유지됩니다.

예) 폼 입력, 필터 조건, 로그인 세션 등

 

 

🔄 콜백 기능

위젯 상태가 변경될 때, 특정 함수를 실행하고 상태를 업데이트할 수 있습니다. 복잡한 UI 순서 변경이나 비동기 반응이 필요할 때 유용합니다.

예) on_change, on_click

 

 

📑 다중 페이지 간 상태 공유

멀티페이지 앱에서 각 페이지 간 공통 세션 데이터를 참조하고 유지가 가능합니다.

 

 

 

💡 st.session_state 예시

import streamlit as st

# 초기화
if "user" not in st.session_state:
    st.session_state.user = None

def login():
    st.session_state.user = "alice"  # 샘플 로그인

if st.session_state.user is None:
    st.button("로그인", on_click=login)
else:
    st.write("안녕하세요,", st.session_state.user)
    st.button("로그아웃", on_click=lambda: st.session_state.__setitem__("user", None))

 

로그인을 버튼으로 처리하는 간단한 예시를 한 번 보겠습니다.

엄청 간단하게 구성한 로그인 처리이고 실제로는 아이디, 비밀번호를 입력받아 암호화하고 상태 관리하는 구조로 짜볼 수 있겠죠.
위 코드에서 st.session_state는 상태 관리를 제공하는데요. st.session_state에 user라는 키가 없으면 user를 None으로 설정해 뒀고
user 키가 None이므로 로그인 st.button이 보입니다. 로그인 버튼에서 클릭하면 콜백으로 login 함수에서 user 키에 아이디를 넣어주고
그 이후는 user 키에 alice가 있으니 안녕하세요와 로그아웃 버튼이 뜨는 걸 볼 수 있습니다.
로그아웃 버튼에 콜백 함수는 람다로 설정해서 user키를 None을 다시 돌리는 걸 볼 수 있습니다.


 

상호 작용

streamlit에서는 st.cache는 Streamlit의 느린 함수 실행을 피하고, 앱 성능을 개선하는 데 사용하는 함수 결과 저장 장치입니다. 최신 버전에서는 아래 두 개의 데코레이터로 역할이 분리되어 있습니다.

 

@st.cache_data

  • 데이터 반환 함수에 사용
  • csv 읽기, API 호출, Dataframe 반환 등 직렬화 가능한 객체에 적합
  • 실행은 동일 입력이 반복되면 딱 1회 진행하고 이후는 캐시에서 불러와 빠르게 반환 – 새로운 입력은 다시 시작

@st.cache_data: 데이터 반환 함수에 사용. CSV 읽기, API 호출, 데이터프레임 변환 등, 직렬화 가능한 객체에 적합합니다.
직렬화는 데이터프레임이나 리스트, 딕셔너리 같은 파이썬 객체를 바이트 형태로 바꿔 저장했다가 불러오는 기술입니다.
함수도 재사용하기 위해 사용하는 것이지만 뭔가 복잡하거나 하는 것들이 매번 다시 돌면 시간이 오래 걸리는데 동일 입력이면 캐시에 있는 데이터를 불러와 활용합니다.

 

@st.cache_resource

  • 머신러닝 모델, DB 연결처럼 직렬화가 불가능하거나 리소스로 유지하고 싶은 객체에 적합
  • 반환된 객체가 전역 공유되므로, 변경 시 주의 필요

@st.cache_resource: 머신러닝 모델, DB 연결처럼 직렬화 불가능하거나 리소스로 유지하고 싶은 객체에 사용합니다. 단, 반환된 객체가 모든 사용자, 세션에 전역 공유되므로, 변경 시 주의해야 합니다.
25

 

 

💡 @st.cache_data 예시

import streamlit as st
import pandas as pd

# cache_data
@st.cache_data(
      ttl="30m",  # Time‑to‑live. 캐시 항목의 유효 기간을 지정합니다. 예: ttl=3600 (초), "1h",
      max_entries=None  # 캐시 저장 가능한 최대 항목 수. 기본은 None(제한 없음). 넘치면 오래된 항목부터 제거.
      show_spinner="Loading CSV…",  # 캐시 미스 시 스피너 표시 여부. True면 기본 텍스트
)
def load_csv(path: str) -> pd.DataFrame:
    return pd.read_csv(path)

# 파일 업로드
st.title('st.file_uploader')
st.subheader('CSV 입력')
uploaded_file = st.file_uploader("파일 선택")
if uploaded_file is not None:
  df = load_csv(uploaded_file)  # 첫 호출만 느림
  st.subheader('DataFrame')
  st.write(df)
else:
  st.info('☝️ CSV 파일을 업로드하세요')

 

cache_data의 예제 코드입니다.

st.cache_data를 데코레이터로 사용하여 load_csv를 캐시 가능한 함수로 만들어 줍니다.
cache_data에는 time-to-live로 캐시 유효 시간을 지정할 수 있고 캐시 저장 항목 수, 캐시 미스 시 문구를 지정할 수 있습니다.
그래서 파일 업로드로 해당 함수를 사용하면 처음에 딱 1회 실행하고, 이후는 캐시에서 불러와 빠르게 반환됩니다.


💡 @st.cache_resource 예시

@st.cache_resource()
def get_model():
    model_name = cfg.model_name
    
    # 생략 … 모델 불러오는 코드
    print("Model done!")
    return tokenizer, model
tokenizer, model = get_model()

msg = st.chat_input(
    placeholder="메시지를 입력하세요",
    key="chat_msg"
)
# 사용자가 메시지를 입력하고 보내기를 누르면 생성됨
if msg:
    # 생략 … 모델을 통한 답변 생성
    # 1. 토크나이즈
    # 2. 모델 생성 호출
    # 3. prompt_length 계산 (토큰 수 기준)
    # 4. 응답 토큰만 선택
    # 5. 디코딩해서 최종 응답 얻기
    st.write(f"🗨️ **사용자**: {msg}")
    st.write(f"🤖 **모델**: {bot_response}")

 

다음은 cache_resource로 모델을 불러와 답변하는 코드인데요.
요즘 kt에서 오픈소스 모델로 허깅페이스에 등록된 믿음2.0을 활용하여 질문을 답변하는 코드를 구성해 봤습니다.
한국어 전용 토크나이저로 학습했다고 하고 2.3B 미니 버전으로 8비트로 양자화했는데 결과가 나쁘지 않아서 예제에 적용해 봤습니다. 코드가 좀 길어서 모델 불러오고 생성하는 부분은 생략했고요.
주목해 주실 부분은 모델을 불러오는 get_model()을 cache_resource 데코레이터를 활용하면 해당 함수의 반환값을 모든 세션에서 맨 처음 단 1회만 로드하고 메모리에 공유해 준다는 겁니다. 대용량 객체(ML 모델, DB 세션 등)는 한 번 로드만으로 성능 향상됩니다.
즉, 앱을 사용하는 사용자 수에 관계없이 get_model()은 처음 한 번만 실행되며, 이후에는 tokenizer, model 객체가 즉시 재사용되어 메모리와 시간을 굉장히 줄여줍니다.

@st.cache_data처럼 복사하지 않아 메모리 사용 효율화됩니다. 단, 반환 후 해당 객체를 사용자 코드에서 변경하면 모든 세션이 공유 자원을 수정하게 되어 유의해야 합니다.

 

 

✅ 정리

@st.cache_data, @st.cache_resource 두 데코레이터는 @st.cache의 복잡성과 성능 이슈를 해결하기 위해 도입되었으며, 각각 experimental_memo와 experimental_singleton의 역할을 계승합니다.

  • @st.cache_data는 데이터 중심(cached data) 함수에 최적화되어 있습니다.
    → 예: CSV, DataFrame, API 응답, 모델 추론 결과 등
    → 각 호출 시 복사된 새로운 데이터를 반환해, 상태 무결성을 유지합니다.
  • @st.cache_resource는 전역 자원(cached resources) 관리에 적합합니다.
    → 예: DB 연결, ML 모델 인스턴스, 외부 API 클라이언트 등
    → 전 세션 · 전 사용자에 걸쳐 공유되며 중복 로딩을 방지합니다.

 

반응형
LIST