기본을 넘어: Streamlit 버튼 완벽 가이드
Updated on
Streamlit은 Python 스크립트를 손쉽게 인터랙티브 앱으로 바꿔 주며, 버튼은 사용자들이 가장 먼저 기대하는 상호작용입니다. st.button
위젯은 단순해 보이지만 간단한 토글부터 복잡한 다단계 작업까지 다양한 워크플로를 열어 줍니다. 이 개정 가이드는 최신 API를 정리하고 흔한 오해를 바로잡으며, 안정적인 버튼 기반 경험을 설계할 수 있는 검증된 패턴을 제공합니다.
Streamlit 프로젝트에 바로 활용할 수 있는 시각 분석 컴포넌트를 찾고 있나요?
PyGWalker (opens in a new tab)는 Tableau와 유사한 탐색 UI를 Streamlit 앱에 직접 삽입합니다. 실제 모습을 보고 싶다면 PyGWalker로 데이터를 탐색하는 방법 (opens in a new tab)을 시청하거나 통합 가이드를 확인하세요.
st.button
이해하기
빠른 시작
st.button
은 클릭 가능한 요소를 렌더링하고, 클릭 직후 실행되는 스크립트 런에서 True
를 반환합니다. 이 불리언 값만으로도 단순한 흐름은 충분히 제어할 수 있습니다.
import streamlit as st
if st.button("인사하기"):
st.write("안녕하세요, Streamlit!")
Streamlit은 위젯이 변경될 때마다 스크립트 전체를 다시 실행합니다. 이런 재실행 모델 때문에 if
블록 안에서 수행하는 작업은 멱등성을 갖거나 추가 상태로 보호해야 합니다.
알아 두면 좋은 주요 인자
st.button
은 대부분의 커스터마이징 요구를 충족하는 여러 선택적 인자를 제공합니다.
key
: 동일한 라벨의 버튼을 여러 개 둘 때 사용하는 고유 식별자.help
: 마우스를 올렸을 때 표시되는 툴팁 텍스트.on_click
: 버튼이 눌릴 때 실행되는 콜백.args
/kwargs
: 콜백으로 전달되는 위치/키워드 인자.type
: Streamlit 테마에 맞춘"primary"
및"secondary"
스타일 프리셋.disabled
: 버튼과의 상호작용을 차단.use_container_width
: 부모 컨테이너 너비에 맞춰 버튼을 확장.
def refresh_data(verbose: bool = False, limit: int | None = None) -> None:
st.session_state["last_result"] = load_data(limit=limit)
if verbose:
st.success("데이터가 업데이트되었습니다")
st.button(
"데이터 새로고침",
key="refresh",
help="API에서 최신 레코드를 가져옵니다",
type="primary",
use_container_width=True,
on_click=refresh_data,
args=(True,),
kwargs={"limit": 500},
)
반환값 그 이상 다루기
콜백과 세션 상태 사용하기
콜백은 Streamlit이 위젯 변경 사항을 수집한 뒤 실행되므로, 로직을 캡슐화하고 st.session_state
를 업데이트하는 데 적합합니다.
import datetime as dt
import streamlit as st
if "last_clicked" not in st.session_state:
st.session_state.last_clicked = None
def mark_timestamp() -> None:
st.session_state.last_clicked = dt.datetime.now(dt.timezone.utc)
st.button("타임스탬프 기록", on_click=mark_timestamp, type="primary")
st.write("마지막 클릭:", st.session_state.last_clicked or "아직 없음")
콜백을 활용하면 상위 스크립트를 선언적으로 유지하고, if
의 깊은 중첩을 피하면서 재실행 간 상태를 보존할 수 있습니다.
토글 동작 만들기
버튼은 눌린 상태를 유지하지 않지만, 세션 상태와 조합하면 토글과 유사한 인터랙션을 구현할 수 있습니다.
import streamlit as st
st.session_state.setdefault("show_advanced", False)
if st.button("고급 옵션 전환"):
st.session_state.show_advanced = not st.session_state.show_advanced
if st.session_state.show_advanced:
st.info("여기에 고급 설정이 표시됩니다.")
지속적인 온/오프 상태가 필요하다면, st.checkbox
나 st.toggle
같은 위젯이 더 명확한 의미를 전달합니다.
버튼 레이아웃 기법
Streamlit은 작성 순서대로 요소를 배치하지만, 컨테이너를 이용하면 여전히 레이아웃을 제어할 수 있습니다.
col1, col2 = st.columns(2)
with col1:
st.button("이전", key="prev", type="secondary")
with col2:
st.button("다음", key="next", type="primary", use_container_width=True)
with st.sidebar:
st.button("필터 초기화", key="reset")
st.container()
나 st.expander()
로 관련 작업을 묶고, st.columns()
로 버튼을 같은 행에 배치하면, HTML에 의존하지 않고도 정렬할 수 있습니다.
스타일 옵션과 CSS 오버라이드
Streamlit은 일관성을 위해 직접적인 스타일 변경을 제한하지만, 다음과 같은 선택지가 있습니다.
- 강조가 필요하면 기본 제공 프리셋
type="primary"
, 반응형 배치를 원하면use_container_width=True
를 사용하세요. - 전역 테마 설정(
.streamlit/config.toml
)으로 기본 색상을 조정하세요. - 맞춤 스타일이 필요할 때는
st.markdown(..., unsafe_allow_html=True)
로 범위를 제한한 CSS를 주입하세요.
import streamlit as st
st.markdown(
"""
<style>
.custom-button button {
background: linear-gradient(135deg, #005bbb, #00bcd4);
color: white;
border: 0;
padding: 0.6rem 1.5rem;
border-radius: 999px;
transition: transform 0.1s ease-in-out;
}
.custom-button button:hover {
transform: translateY(-1px);
}
</style>
""",
unsafe_allow_html=True,
)
with st.container():
st.markdown('<div class="custom-button">', unsafe_allow_html=True)
st.button("그라데이션 버튼", key="custom")
st.markdown("</div>", unsafe_allow_html=True)
CSS 오버라이드는 필요한 부분에만 집중하세요. 거대한 인라인 블록은 유지보수가 어렵고, Streamlit이 내부 클래스 이름을 바꾸면 깨질 수 있습니다.
실전 패턴
- 점진적 공개:
st.session_state
와 버튼을 조합하여 필요할 때만 추가 입력이나 설명을 노출합니다. - 데이터 처리 단계: 파일 업로드나 인증 토큰 같은 선행 조건이 준비될 때까지 버튼을 비활성화(
disabled=True
)합니다. - 다운로드 흐름: 파일 제공이 목적이면
st.download_button
을 사용하고, 앱 내부 로직 실행에는st.button
을 사용하세요.
마무리
버튼은 Streamlit 사용자 여정의 핵심입니다. 반환되는 불리언 값, 콜백 API, st.session_state
를 조합하면 반응형 패러다임을 유지한 채 복잡한 동작을 조율할 수 있습니다. 정렬에는 레이아웃 프리미티브를 활용하고, CSS는 필요할 때만 사용하며, 지속적인 상태 표시가 더 명확하다면 다른 위젯도 고려하세요. 세심하게 설계된 버튼은 Streamlit 앱을 빠르고 직관적이며 신뢰할 수 있게 만들어 줍니다.
자주 묻는 질문
Streamlit에서 버튼을 만드는 방법은?
st.button("라벨")
을 사용하세요. 클릭으로 트리거된 실행에서 True
가 반환되므로, 해당 if
블록에 로직을 배치하거나 on_click
으로 콜백을 전달하면 됩니다.
Streamlit에서 버튼 위치를 조정하려면?
st.columns
, st.container
, st.sidebar
, st.expander
와 같은 레이아웃 프리미티브로 위젯을 감싸세요. HTML을 직접 사용하지 않고도 배치를 제어할 수 있습니다.
Streamlit에서 라디오 버튼은 어떻게 만들까요?
st.radio(label, options)
을 사용하면 상호 배타적인 선택지를 제공할 수 있습니다. 선택된 값은 즉시 반환되며 st.session_state
에 저장해 후속 로직에서 활용할 수 있습니다.
Streamlit의 단점은 무엇인가요?
Streamlit의 스크립트 재실행 모델은 개발을 단순화하지만, 세밀한 레이아웃 제어, 장시간 백그라운드 작업, 깊은 스타일 커스터마이징이 필요할 때는 제약으로 느껴질 수 있습니다. 다만 생태계가 빠르게 발전하고 있어 새로운 위젯, 테마 옵션, 세션 상태 도우미가 이러한 격차를 점차 해소하고 있습니다.