🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

스트림릿 UI 구성 완벽 가이드 - 슬라이드 1/8
A

AI Generated

2025. 12. 4. · 14 Views

스트림릿 UI 구성 완벽 가이드

파이썬으로 웹 애플리케이션을 만들 때 가장 쉽고 빠르게 UI를 구성할 수 있는 Streamlit의 핵심 기능을 다룹니다. 레이아웃부터 위젯, 세션 상태 관리까지 실무에서 바로 활용할 수 있는 내용을 담았습니다.


목차

  1. 기본_레이아웃과_열_레이아웃
  2. 사이드바_레이아웃_구성
  3. 페이지_환경_설정하기
  4. 버튼과_입력_위젯_사용
  5. 선택형_위젯_활용
  6. 파일_업로드_위젯
  7. 세션_상태_관리

1. 기본 레이아웃과 열 레이아웃

김개발 씨는 데이터 분석 결과를 보여주는 대시보드를 만들어야 했습니다. 그런데 막상 화면을 구성하려니 모든 요소가 세로로만 쭉 나열되어 답답해 보였습니다.

"옆으로 나란히 배치할 수는 없을까?"

st.columns는 화면을 여러 개의 열로 나누어 요소들을 가로로 배치할 수 있게 해주는 함수입니다. 마치 신문의 단 나누기처럼 화면을 분할하여 정보를 효율적으로 배치할 수 있습니다.

이를 활용하면 대시보드나 비교 화면을 깔끔하게 구성할 수 있습니다.

다음 코드를 살펴봅시다.

import streamlit as st

# 화면을 3개의 열로 균등 분할
col1, col2, col3 = st.columns(3)

# 각 열에 서로 다른 콘텐츠 배치
with col1:
    st.header("매출 현황")
    st.metric("이번 달", "1,234만원", "+12%")

with col2:
    st.header("방문자 수")
    st.metric("오늘", "5,678명", "-3%")

with col3:
    st.header("전환율")
    st.metric("평균", "3.2%", "+0.5%")

# 비율을 다르게 설정할 수도 있음
left, right = st.columns([2, 1])

김개발 씨는 입사 6개월 차 주니어 데이터 분석가입니다. 팀장님께서 이번 주까지 영업 실적 대시보드를 만들어 달라고 하셨습니다.

파이썬으로 데이터 분석은 자신 있지만, 웹 화면을 구성하는 것은 처음이라 막막했습니다. 선배인 박시니어 씨가 다가와 물었습니다.

"스트림릿 써봤어요? 파이썬만 알면 금방 대시보드 만들 수 있어요." 김개발 씨는 바로 스트림릿을 설치하고 코드를 작성하기 시작했습니다.

그런데 문제가 생겼습니다. 모든 차트와 지표가 세로로 길게 나열되어 한눈에 보기가 어려웠던 것입니다.

이럴 때 필요한 것이 바로 st.columns 함수입니다. 쉽게 비유하자면, st.columns는 마치 책상 위에 칸막이를 세우는 것과 같습니다.

넓은 책상을 여러 구역으로 나누면 각 구역에 서로 다른 물건을 정리할 수 있듯이, 화면도 여러 열로 나누면 각 열에 서로 다른 정보를 배치할 수 있습니다. 사용법은 매우 간단합니다.

**st.columns(3)**이라고 작성하면 화면이 3등분됩니다. 반환되는 값을 변수에 담아 각각의 열로 사용하면 됩니다.

열의 비율을 다르게 하고 싶다면 어떻게 할까요? 숫자 대신 리스트를 전달하면 됩니다.

**st.columns([2, 1])**이라고 작성하면 왼쪽 열이 오른쪽 열보다 2배 넓어집니다. 각 열에 콘텐츠를 넣을 때는 with 문을 사용합니다.

with col1: 블록 안에 작성한 모든 요소는 첫 번째 열에 표시됩니다. 이렇게 하면 코드도 깔끔하고 어떤 열에 무엇이 들어가는지 한눈에 알 수 있습니다.

실제 현업에서는 대시보드의 핵심 지표를 나란히 보여줄 때 자주 사용합니다. 매출, 방문자, 전환율 같은 KPI를 한 줄에 배치하면 경영진도 한눈에 현황을 파악할 수 있습니다.

주의할 점이 있습니다. 열을 너무 많이 만들면 각 열의 너비가 좁아져서 오히려 보기 불편해집니다.

보통 2개에서 4개 사이가 적당합니다. 김개발 씨는 3개의 열로 핵심 지표를 배치하고, 아래에는 2개의 열로 차트를 나란히 놓았습니다.

팀장님께서 "오, 깔끔하네!"라고 하셨을 때, 김개발 씨는 작은 보람을 느꼈습니다.

실전 팁

💡 - 모바일에서는 열이 자동으로 세로로 쌓이니 반응형 걱정은 덜어도 됩니다

  • gap 파라미터로 열 사이 간격을 조절할 수 있습니다

2. 사이드바 레이아웃 구성

대시보드가 점점 복잡해지자 김개발 씨에게 새로운 고민이 생겼습니다. 필터 기능을 추가하고 싶은데, 본문에 넣자니 지저분해 보였습니다.

"필터는 옆에 따로 빼둘 수 없을까?"

st.sidebar는 화면 왼쪽에 접었다 폈다 할 수 있는 사이드바를 만들어주는 기능입니다. 마치 서랍장처럼 필요할 때 열어서 설정을 바꾸고, 필요 없을 때는 접어둘 수 있습니다.

필터, 설정, 네비게이션 같은 보조 기능을 담기에 안성맞춤입니다.

다음 코드를 살펴봅시다.

import streamlit as st

# 사이드바에 제목 추가
st.sidebar.title("필터 설정")

# 사이드바에 셀렉트박스 추가
department = st.sidebar.selectbox(
    "부서 선택",
    ["전체", "영업팀", "마케팅팀", "개발팀"]
)

# 사이드바에 날짜 범위 선택
start_date = st.sidebar.date_input("시작일")
end_date = st.sidebar.date_input("종료일")

# 사이드바에 슬라이더 추가
min_sales = st.sidebar.slider("최소 매출액", 0, 1000, 100)

# 메인 화면에는 필터링된 결과 표시
st.title("영업 실적 대시보드")
st.write(f"선택된 부서: {department}")

김개발 씨의 대시보드가 팀 내에서 인기를 얻기 시작했습니다. 그러자 요청 사항도 늘어났습니다.

"부서별로 필터링 좀 해줘", "기간 선택 기능도 넣어줘", "최소 매출액 기준도 설정할 수 있으면 좋겠어". 처음에는 필터 위젯들을 본문 상단에 배치했습니다.

그런데 필터가 늘어날수록 화면이 어수선해졌습니다. 정작 중요한 차트와 데이터는 스크롤을 한참 내려야 볼 수 있게 되었습니다.

박시니어 씨가 힌트를 주었습니다. "사이드바 써봐요.

필터는 옆으로 빼고 본문은 깔끔하게 유지할 수 있어요." st.sidebar는 마치 옷장의 서랍과 같습니다. 자주 입는 옷은 눈에 잘 보이는 곳에 걸어두고, 계절이 지난 옷이나 속옷은 서랍에 정리해두듯이, 핵심 콘텐츠는 메인 화면에 두고 부가 기능은 사이드바에 넣어두는 것입니다.

사용 방법은 정말 간단합니다. 기존에 사용하던 모든 위젯 앞에 **st.sidebar.**만 붙이면 됩니다.

st.selectboxst.sidebar.selectbox가 되는 식입니다. 사이드바는 기본적으로 펼쳐진 상태로 시작합니다.

사용자가 왼쪽 상단의 화살표를 클릭하면 접을 수 있습니다. 모바일에서는 햄버거 메뉴 아이콘을 터치하면 나타납니다.

실무에서 사이드바는 정말 다양하게 활용됩니다. 데이터 필터링 조건, 차트 옵션 설정, 페이지 네비게이션, 사용자 정보 표시 등 보조적인 기능을 담기에 제격입니다.

한 가지 팁을 드리자면, 사이드바에 너무 많은 기능을 넣지 마세요. 스크롤이 길어지면 사용자가 피로감을 느낍니다.

정말 필요한 필터만 선별해서 넣는 것이 좋습니다. 김개발 씨는 부서 선택, 날짜 범위, 매출액 필터를 사이드바로 옮겼습니다.

메인 화면이 훨씬 깔끔해졌고, 사용자들도 필터 변경이 쉬워졌다며 좋아했습니다.

실전 팁

💡 - st.sidebar.image로 회사 로고를 사이드바 상단에 넣으면 전문적인 느낌이 납니다

  • with st.sidebar: 블록을 사용하면 여러 위젯을 그룹으로 묶어 관리하기 편합니다

3. 페이지 환경 설정하기

대시보드를 배포하려는데 김개발 씨는 뭔가 허전함을 느꼈습니다. 브라우저 탭에는 "Streamlit"이라고만 표시되고, 아이콘도 스트림릿 기본 아이콘이었습니다.

"우리 회사 대시보드처럼 보이게 할 수는 없을까?"

st.set_page_config는 페이지의 기본 설정을 변경하는 함수입니다. 브라우저 탭에 표시되는 제목, 파비콘, 레이아웃 너비, 사이드바 초기 상태 등을 설정할 수 있습니다.

이 함수는 반드시 스크립트의 맨 처음에 호출해야 합니다.

다음 코드를 살펴봅시다.

import streamlit as st

# 반드시 다른 st 함수보다 먼저 호출해야 함
st.set_page_config(
    page_title="영업 실적 대시보드",  # 브라우저 탭 제목
    page_icon="📊",                    # 파비콘 (이모지 또는 이미지 경로)
    layout="wide",                     # wide 또는 centered
    initial_sidebar_state="expanded"   # expanded 또는 collapsed
)

# 이제 다른 콘텐츠 작성
st.title("2024년 영업 실적")
st.write("환영합니다!")

# 메뉴 옵션도 설정 가능
st.set_page_config(
    menu_items={
        'Get Help': 'https://docs.company.com',
        'About': '# 영업팀 대시보드 v1.0'
    }
)

김개발 씨는 대시보드 개발을 거의 마무리했습니다. 기능은 완벽한데, 어딘가 아마추어 같은 느낌이 들었습니다.

브라우저 탭을 보니 그냥 "Streamlit"이라고만 적혀 있었습니다. "이거 우리 회사 서비스 같지가 않아요." 팀장님의 피드백이었습니다.

박시니어 씨가 알려주었습니다. "st.set_page_config 써봤어요?

페이지 제목이랑 아이콘 바꿀 수 있어요." 이 함수는 마치 새 가게를 열 때 간판을 다는 것과 같습니다. 내부 인테리어(콘텐츠)를 아무리 잘 해도, 간판(제목과 아이콘)이 없으면 사람들이 무슨 가게인지 모릅니다.

브라우저 탭에 표시되는 제목과 아이콘은 서비스의 첫인상을 결정합니다. 여기서 중요한 규칙이 있습니다.

st.set_page_config는 반드시 파이썬 스크립트의 맨 처음에 호출해야 합니다. 다른 어떤 st. 함수보다 먼저 와야 합니다.

이 규칙을 어기면 에러가 발생합니다. page_title 파라미터는 브라우저 탭에 표시되는 제목입니다.

사용자가 여러 탭을 열어놓았을 때 우리 서비스를 쉽게 찾을 수 있게 해줍니다. page_icon은 파비콘을 설정합니다.

이모지를 직접 넣어도 되고, 이미지 파일 경로를 지정해도 됩니다. 회사 로고를 파비콘으로 쓰면 더 전문적으로 보입니다.

layout 파라미터는 콘텐츠의 너비를 결정합니다. 기본값인 "centered"는 콘텐츠가 가운데 정렬되어 양쪽에 여백이 생깁니다.

"wide"로 설정하면 화면 전체를 사용합니다. 대시보드처럼 많은 정보를 보여줘야 할 때는 "wide"가 좋습니다.

initial_sidebar_state는 사이드바의 초기 상태입니다. "expanded"면 펼쳐진 채로, "collapsed"면 접힌 채로 시작합니다.

모바일 사용자가 많다면 "collapsed"가 나을 수 있습니다. 김개발 씨는 페이지 제목을 "영업 실적 대시보드"로, 아이콘은 차트 이모지로, 레이아웃은 "wide"로 설정했습니다.

이제 진짜 우리 회사 서비스처럼 보였습니다.

실전 팁

💡 - menu_items로 오른쪽 상단 메뉴에 도움말 링크나 버전 정보를 추가할 수 있습니다

  • 파비콘으로 PNG 파일을 사용하면 더 선명하게 표시됩니다

4. 버튼과 입력 위젯 사용

대시보드에 새로운 기능 요청이 들어왔습니다. 사용자가 직접 데이터를 입력하고, 버튼을 눌러 계산 결과를 확인하는 기능이었습니다.

김개발 씨는 고민에 빠졌습니다. "사용자 입력은 어떻게 받지?"

스트림릿은 다양한 입력 위젯을 제공합니다. st.button으로 클릭 이벤트를 받고, st.text_input으로 텍스트를, st.number_input으로 숫자를 입력받을 수 있습니다.

이 위젯들은 사용자와 애플리케이션이 상호작용하는 창구 역할을 합니다.

다음 코드를 살펴봅시다.

import streamlit as st

st.title("매출 예측 계산기")

# 텍스트 입력
product_name = st.text_input("상품명을 입력하세요", "신제품 A")

# 숫자 입력 (최소값, 최대값, 기본값, 증가단위 설정 가능)
unit_price = st.number_input("단가 (원)", min_value=0, value=10000, step=1000)
quantity = st.number_input("예상 판매량", min_value=0, value=100)

# 버튼 클릭 이벤트
if st.button("매출 계산하기", type="primary"):
    total = unit_price * quantity
    st.success(f"{product_name}의 예상 매출: {total:,}원")

# 텍스트 영역 (여러 줄 입력)
memo = st.text_area("메모", height=100)

영업팀에서 새로운 요청이 왔습니다. 신제품 출시를 앞두고, 예상 매출을 빠르게 계산해볼 수 있는 도구가 필요하다는 것이었습니다.

단가와 예상 판매량을 입력하면 총 매출이 나오는 간단한 계산기였습니다. 김개발 씨는 HTML 폼을 만들어야 하나 걱정했습니다.

하지만 스트림릿에서는 그럴 필요가 없었습니다. 스트림릿의 입력 위젯은 마치 설문지의 문항과 같습니다.

설문지에 이름 적는 칸, 나이 적는 칸, 동의 체크박스가 있듯이, 스트림릿에도 텍스트 입력, 숫자 입력, 버튼 등 다양한 위젯이 준비되어 있습니다. st.text_input은 한 줄짜리 텍스트를 입력받습니다.

첫 번째 인자는 라벨(안내 문구)이고, 두 번째 인자는 기본값입니다. 사용자가 아무것도 입력하지 않으면 기본값이 사용됩니다.

st.number_input은 숫자 전용 입력 필드입니다. 옆에 플러스, 마이너스 버튼이 자동으로 생겨서 마우스로도 값을 조절할 수 있습니다.

min_valuemax_value로 입력 범위를 제한하고, step으로 증감 단위를 설정합니다. st.button은 클릭할 수 있는 버튼을 만듭니다.

이 함수는 버튼이 클릭되면 True를, 그렇지 않으면 False를 반환합니다. 그래서 if st.button(): 형태로 클릭 이벤트를 처리합니다.

여기서 스트림릿의 독특한 동작 방식을 이해해야 합니다. 사용자가 버튼을 클릭하거나 입력값을 변경하면, 스크립트 전체가 위에서 아래로 다시 실행됩니다.

이것을 리렌더링이라고 합니다. 처음에는 어색하지만, 이 방식 덕분에 복잡한 상태 관리 없이도 인터랙티브한 앱을 만들 수 있습니다.

st.text_area는 여러 줄의 텍스트를 입력받을 때 사용합니다. height 파라미터로 높이를 조절할 수 있습니다.

버튼의 **type="primary"**를 설정하면 버튼이 강조 색상으로 표시됩니다. 가장 중요한 액션 버튼에 사용하면 좋습니다.

김개발 씨는 단가와 판매량을 입력받는 필드를 만들고, "매출 계산하기" 버튼을 추가했습니다. 영업팀 직원들은 여러 시나리오의 매출을 빠르게 계산해볼 수 있게 되었습니다.

실전 팁

💡 - st.button은 클릭 후 리렌더링되면 다시 False가 되므로, 결과를 유지하려면 세션 상태를 활용하세요

  • text_input에 type="password"를 설정하면 비밀번호 입력 필드가 됩니다

5. 선택형 위젯 활용

매출 계산기에 새로운 요구사항이 추가되었습니다. 할인율을 적용하고 싶은데, 자유롭게 숫자를 입력받기보다는 미리 정해진 옵션 중에서 선택하게 하고 싶었습니다.

"정해진 값 중에서 고르게 하려면 어떻게 하지?"

스트림릿은 다양한 선택형 위젯을 제공합니다. st.selectbox는 드롭다운 메뉴, st.radio는 라디오 버튼, st.multiselect는 복수 선택, st.slider는 범위 내 값 선택을 지원합니다.

사용자의 선택을 제한하여 입력 오류를 방지하고 사용성을 높일 수 있습니다.

다음 코드를 살펴봅시다.

import streamlit as st

st.title("주문 옵션 선택")

# 드롭다운 선택
size = st.selectbox(
    "사이즈를 선택하세요",
    ["Small", "Medium", "Large", "Extra Large"]
)

# 라디오 버튼 (단일 선택)
payment = st.radio(
    "결제 방법",
    ["신용카드", "계좌이체", "간편결제"],
    horizontal=True  # 가로 배치
)

# 복수 선택
toppings = st.multiselect(
    "추가 토핑 선택 (복수 가능)",
    ["치즈", "베이컨", "올리브", "피망", "양파"]
)

# 슬라이더
discount = st.slider("할인율 (%)", 0, 50, 10)

st.write(f"선택: {size}, {payment}, 토핑: {toppings}, 할인: {discount}%")

매출 계산기가 인기를 얻자, 마케팅팀에서도 활용하고 싶다는 요청이 왔습니다. 다만 할인율 적용 시 아무 숫자나 입력하면 계산이 복잡해지니, 5%, 10%, 15%, 20% 중에서만 선택하게 해달라는 조건이 붙었습니다.

김개발 씨는 "입력값을 검증하는 코드를 추가해야 하나?" 고민했습니다. 하지만 더 좋은 방법이 있었습니다.

애초에 선택지만 제공하면 잘못된 입력 자체가 불가능해지니까요. 선택형 위젯은 마치 음식점 메뉴판과 같습니다.

손님에게 "뭐 드시겠어요?"라고 열린 질문을 하면 "짜장면 반 짬뽕 반이요"처럼 메뉴에 없는 주문이 들어올 수 있습니다. 하지만 메뉴판에서 고르게 하면 그런 일이 없습니다.

st.selectbox는 가장 흔히 쓰이는 드롭다운 메뉴입니다. 클릭하면 선택지가 펼쳐지고, 하나를 고르면 접힙니다.

선택지가 많을 때 화면을 깔끔하게 유지할 수 있습니다. st.radio는 라디오 버튼입니다.

모든 선택지가 항상 보입니다. 선택지가 2개에서 5개 정도로 적고, 사용자가 한눈에 비교해야 할 때 좋습니다.

horizontal=True를 설정하면 가로로 나열됩니다. st.multiselect는 복수 선택이 가능한 위젯입니다.

피자 토핑처럼 여러 개를 동시에 선택해야 할 때 사용합니다. 선택한 항목은 태그 형태로 표시되고, X 버튼으로 제거할 수 있습니다.

st.slider는 연속적인 범위에서 값을 선택할 때 사용합니다. 최소값, 최대값, 기본값을 지정하면 사용자가 드래그로 값을 조절합니다.

할인율, 수량, 가격 범위 등을 입력받을 때 편리합니다. 이런 위젯들은 선택지를 리스트나 튜플로 전달합니다.

선택된 값은 바로 변수에 담겨서 사용할 수 있습니다. st.multiselect의 경우 선택된 항목들이 리스트로 반환됩니다.

실무에서는 데이터 필터링에 이 위젯들을 많이 활용합니다. 날짜 범위는 슬라이더로, 카테고리는 셀렉트박스로, 여러 태그 필터는 멀티셀렉트로 구현하면 깔끔합니다.

김개발 씨는 할인율을 슬라이더로, 결제 방법을 라디오 버튼으로 바꿨습니다. 이제 사용자들이 잘못된 값을 입력할 걱정이 없어졌습니다.

실전 팁

💡 - selectbox의 index 파라미터로 기본 선택값의 인덱스를 지정할 수 있습니다

  • slider에 두 개의 기본값을 튜플로 전달하면 범위 선택 슬라이더가 됩니다

6. 파일 업로드 위젯

어느 날 재무팀에서 요청이 왔습니다. 엑셀 파일을 업로드하면 자동으로 분석해주는 기능이 필요하다는 것이었습니다.

김개발 씨는 "파일 업로드는 복잡한 서버 설정이 필요하지 않나?" 걱정했지만, 스트림릿에서는 놀라울 정도로 간단했습니다.

st.file_uploader는 사용자가 파일을 업로드할 수 있는 위젯입니다. 드래그 앤 드롭도 지원하며, 허용할 파일 형식을 지정할 수 있습니다.

업로드된 파일은 바이트 스트림으로 반환되어 pandas 등의 라이브러리로 바로 처리할 수 있습니다.

다음 코드를 살펴봅시다.

import streamlit as st
import pandas as pd

st.title("매출 데이터 분석기")

# 파일 업로드 위젯
uploaded_file = st.file_uploader(
    "엑셀 파일을 업로드하세요",
    type=["xlsx", "csv"],  # 허용할 파일 형식
    help="xlsx 또는 csv 파일만 가능합니다"
)

# 파일이 업로드되었을 때만 처리
if uploaded_file is not None:
    # 파일 정보 표시
    st.write(f"파일명: {uploaded_file.name}")
    st.write(f"파일 크기: {uploaded_file.size:,} bytes")

    # pandas로 데이터 읽기
    if uploaded_file.name.endswith('.csv'):
        df = pd.read_csv(uploaded_file)
    else:
        df = pd.read_excel(uploaded_file)

    # 데이터 미리보기
    st.dataframe(df.head())
    st.write(f"총 {len(df)}개의 행이 있습니다")

재무팀 이 대리는 매달 같은 작업을 반복하고 있었습니다. 엑셀 파일을 열고, 피벗 테이블을 만들고, 차트를 그리고, 보고서를 작성하는 일이었습니다.

"이거 자동화할 수 없을까요?" 김개발 씨에게 좋은 기회였습니다. 파일을 업로드하면 자동으로 분석해주는 도구를 만들면 되니까요.

하지만 파일 업로드라니, 웹 개발에서 가장 까다로운 부분 중 하나가 아니던가요? 다행히 스트림릿에서는 한 줄이면 됩니다.

st.file_uploader는 마치 이메일의 첨부파일 기능과 같습니다. 사용자가 버튼을 클릭하거나 파일을 드래그해서 놓으면, 그 파일을 프로그램에서 사용할 수 있게 됩니다.

type 파라미터는 매우 중요합니다. 여기에 허용할 파일 확장자를 리스트로 전달합니다.

이렇게 하면 지정한 형식이 아닌 파일은 아예 선택되지 않습니다. 보안과 사용성 두 마리 토끼를 잡을 수 있습니다.

업로드된 파일은 UploadedFile 객체로 반환됩니다. 이 객체는 파일 이름(name), 크기(size), 타입(type) 같은 정보를 담고 있습니다.

그리고 바이트 스트림처럼 동작해서 pandasread_csvread_excel에 바로 전달할 수 있습니다. 여기서 주의할 점이 있습니다.

파일이 업로드되기 전에는 uploaded_file 변수가 None입니다. 그래서 반드시 if uploaded_file is not None: 조건문으로 감싸야 합니다.

그렇지 않으면 에러가 발생합니다. st.dataframe은 pandas 데이터프레임을 예쁜 표 형태로 보여줍니다.

정렬, 검색, 스크롤 기능이 자동으로 포함되어 있어서 대용량 데이터도 문제없이 표시됩니다. 여러 파일을 동시에 업로드받고 싶다면 accept_multiple_files=True 옵션을 추가하면 됩니다.

이 경우 반환값이 파일 객체의 리스트가 됩니다. 김개발 씨는 파일 업로드 기능을 추가하고, 업로드된 데이터로 자동 분석과 시각화까지 구현했습니다.

이 대리는 이제 매달 반복하던 2시간짜리 작업을 5분 만에 끝낼 수 있게 되었습니다.

실전 팁

💡 - 대용량 파일 업로드 시 st.spinner로 로딩 표시를 해주면 사용자 경험이 좋아집니다

  • accept_multiple_files=True로 여러 파일을 한 번에 업로드받을 수 있습니다

7. 세션 상태 관리

김개발 씨는 이상한 버그를 발견했습니다. 카운터 앱을 만들었는데, 버튼을 누를 때마다 숫자가 1에서 늘어나지 않는 것이었습니다.

"분명 count += 1 했는데 왜 계속 1이지?" 스트림릿의 동작 원리를 이해해야 풀리는 문제였습니다.

스트림릿은 사용자 입력이 있을 때마다 스크립트 전체를 다시 실행합니다. 이 때문에 일반 변수는 매번 초기화됩니다.

st.session_state는 이 문제를 해결하는 딕셔너리로, 리렌더링 사이에도 값이 유지됩니다. 로그인 상태, 장바구니, 폼 데이터 등을 저장하는 데 필수적입니다.

다음 코드를 살펴봅시다.

import streamlit as st

st.title("장바구니 시스템")

# 세션 상태 초기화 (최초 실행 시에만)
if 'cart' not in st.session_state:
    st.session_state.cart = []
if 'total' not in st.session_state:
    st.session_state.total = 0

# 상품 목록
products = {"사과": 1000, "바나나": 1500, "오렌지": 2000}

# 상품 추가 버튼
for name, price in products.items():
    if st.button(f"{name} 담기 ({price:,}원)"):
        st.session_state.cart.append(name)
        st.session_state.total += price

# 장바구니 현황 표시
st.subheader("장바구니")
st.write(f"담긴 상품: {st.session_state.cart}")
st.write(f"총 금액: {st.session_state.total:,}원")

# 비우기 버튼
if st.button("장바구니 비우기"):
    st.session_state.cart = []
    st.session_state.total = 0

김개발 씨는 간단한 카운터 앱을 만들려고 했습니다. 버튼을 누르면 숫자가 1씩 증가하는 앱이었습니다.

코드는 단순했습니다. count = 0이라고 선언하고, 버튼을 누르면 count += 1을 하고, st.write(count)로 표시하면 될 것 같았습니다.

그런데 결과는 예상과 달랐습니다. 버튼을 아무리 눌러도 화면에는 계속 1만 표시되었습니다.

무엇이 문제일까요? 박시니어 씨가 설명해 주었습니다.

"스트림릿의 동작 원리를 이해해야 해요. 버튼을 누르면 스크립트 전체가 처음부터 다시 실행돼요." 이것은 스트림릿의 가장 중요한 특징입니다.

사용자가 버튼을 클릭하거나, 입력값을 변경하거나, 어떤 상호작용을 하면 파이썬 스크립트 전체가 위에서 아래로 다시 실행됩니다. 그래서 count = 0도 다시 실행되고, count += 1을 해도 결국 1이 되는 것입니다.

이 문제를 해결하는 것이 바로 st.session_state입니다. st.session_state는 마치 브라우저의 쿠키나 로컬 스토리지와 같습니다.

페이지를 새로고침해도 로그인 상태가 유지되는 것처럼, 스크립트가 다시 실행되어도 st.session_state에 저장된 값은 유지됩니다. 사용 방법은 딕셔너리와 똑같습니다.

st.session_state['count'] = 0처럼 대괄호로 접근하거나, st.session_state.count = 0처럼 점 표기법으로 접근할 수 있습니다. 초기화할 때는 반드시 조건문을 사용해야 합니다.

if 'count' not in st.session_state: 라고 먼저 확인하고, 없을 때만 초기값을 설정합니다. 이렇게 하지 않으면 매번 초기값으로 덮어씌워집니다.

실무에서 세션 상태는 정말 많이 사용됩니다. 사용자 로그인 정보, 장바구니 내역, 폼의 중간 저장 데이터, 멀티 스텝 위자드의 현재 단계 등을 저장합니다.

위 예제의 장바구니 시스템을 보겠습니다. st.session_state.cart 리스트에 담긴 상품들이 저장되고, st.session_state.total에 총 금액이 저장됩니다.

상품을 담을 때마다 이 값들이 업데이트되고, 리렌더링 후에도 유지됩니다. 김개발 씨는 드디어 카운터가 제대로 동작하는 것을 보았습니다.

"아, 그래서 계속 1이었구나!" 세션 상태를 이해하고 나니 스트림릿으로 만들 수 있는 것들이 훨씬 많아졌습니다.

실전 팁

💡 - 세션 상태는 사용자별로 독립적입니다. 다른 사용자의 세션과 섞이지 않습니다

  • st.session_state.clear()로 모든 세션 데이터를 한 번에 지울 수 있습니다

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#Streamlit#Layout#Widgets#SessionState#WebApp#Python,Streamlit,UI

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.