[Service] Streamlit


앞서 프로토타입 등을 빠르게 구현할 때 사용할 수 있는 라이브러리로 Streamlit 이 있다고 했다. 이에 대해 알아보자.

Streamlit

  • 다른 웹 서비스 구현 라이브러리인 Voila 는 노트북에서 쉽게 프로토타입을 만들 수 있지만, 대시보드처럼 레이아웃을 잡기 어렵다는 단점이 있다.
  • 또한 JavaScript, React, Vue 등을 사용해 프로토타입을 만드는 것은 시간 효율적이지 않다.
  • 처음부터 HTML/JavaScript + Flask/FastAPI 가 아닌 기존 코드를 조금만 수정해서 웹 서비스를 만드는 것이 목표일 때, Streamlit 을 사용할 수 있다.
  • 아래 이미지는 데이터 분석가(또는 데이터 사이언티스트)가 웹 서비스를 만드는 Flow 에 대해 나타내고 있다.

    Untitled

  • 데이터 Product 가 중요하다면 프론트엔드/PM 조직과 협업한다. 단 프론트엔드/PM 조직은 다른 웹도 만들고 있어 빠르게 이터레이션 하기 어렵다.

    UntitledStep 1 에서 requirements 는 라이브러리가 아니라 요구사항을 뜻한다.

  • Streamlit 은 다른 조직의 도움 없이 빠르게 웹 서비스를 만들 수 있는 장점이 있다.

    Untitled

  • 여기서 유념해야 할 것은, 모든 것은 프로젝트의 요구조건에 따라 다르고, 프로젝트 설계에 따라 다르다는 점이다.
  • Streamlit 의 대안으로는 아래와 같은 도구들이 있다.
    • R 의 Shiny
    • Flask, Fast API : 백엔드를 직접 구성 + 프론트엔드 작업도 진행
    • Dash : 제일 기능이 풍부한 Python 대시보드 라이브러리
    • Voila : jupyter notebook 을 바로 시각화할 수 있으나, UX 나 레이아웃을 잡기에는 까다롭다.

      Untitled

  • Streamlit 은 공식문서를 제공한다. Streamlit Docs에 들어가보면 확인할 수 있다.
  • Streamlit 의 장점은 아래와 같다.
    • 파이썬 스크립트 코드를 조금만 수정하면 웹을 띄울 수 있다.
    • 백엔드 개발이나 HTTP 요청을 구현하지 않아도 된다.
    • 다양한 Component 제공해 대시보드 UI 구성할 수 있다.
    • Streamlit Cloud 도 존재하기 떄문에 쉽게 배포할 수 있다. 단, Community Plan 은 Public Repo 만 가능하다.
    • 화면 녹화 기능(Record)이 존재한다. 이를 github README.md 에 올릴 수 있다.
    • 굉장히 적은 코드로 프론트엔드 기능을 할 수 있다.
  • 아래와 같이 CLI 로 streamlit run streamlit-basic.py 명령어만 입력하면 바로 확인해볼 수 있다.

    Untitled

Streamlit Component

  • 아래는 Streamlit 에서 제공하는 component 들이며, 코드와 웹에서 보이는 결과를 보여주는 이미지를 보자.
  • Title, Header, subheader, Write something

    Untitled

  • 버튼

    Untitled

  • 체크박스
    • value argument 에 인자를 넘겨주면 default 값을 설정할 수 있다.

      Untitled

      Untitled

  • Pandas Dataframe, Markdown
    • st.write : 보여줄 수 있는 것이면 어떤 것이든 보여준다.
    • st.dataframe : Interactive 한 Dataframe, 컬럼 클릭이 가능하고 정렬도 가능하다.
    • st.table : Static 한 Dataframe

      Untitled

    • 강조도 가능하다.

      Untitled

  • Metric, Json
    • 지표 등을 작성할 수 있다.

      Untitled

  • Line Chart

    Untitled

  • Map Chart

    Untitled

  • 그 외에 plotly chart 등도 쉽게 사용할 수 있다. 자세한 것은 Streamlit Docs 의 Chart elements 를 확인해보자.

    Untitled

  • Radio Button, Select Box

    Untitled

  • multi select box

    Untitled

  • Slider

    Untitled

  • input box, caption, code, latex

    Untitled

  • sidebar
    • st.sidebar.button(”hi”) 와 같이 사용한다. Sidebar 에는 파라미터를 지정하거나 암호를 설정할 수 있다.

      Untitled

  • columns

    Untitled

  • Expander

    Untitled

  • Spinner

    Untitled

  • Ballons
    • st.balloons() 을 사용하면 웹 화면에 풍선이 나오는 이쁜(?) 효과를 발생시킨다.
  • Status Box

    Untitled

  • Form

    Untitled

  • file uploader

    Untitled

  • Streamlit API Document 에는 굉장히 많은 Component 가 존재한다. Streamlit cheat sheet를 보자.

Streamlit Data Flow

  • Streamlit 의 화면에서 무언가 업데이트 되면, 전체 Streamlit 코드가 다시 실행되는 구조다.
    • 코드가 수정되는 경우
    • 사용자가 Streamlit 의 위젯과 상호작용 하는 경우(버튼 클릭, 입력 상자에 텍스트 입력 등)
  • streamlit 의 data flow 로 인해 매번 코드가 재실행되며 중복 이벤트를 할 수 없다. 따라서 Global Variable 처럼 서로 공유할 수 있는 변수가 필요하다.
  • streamlit 0.84 버전에서 이러한 역할을 하는 Session State 가 개발되었다.
  • st.session_state.{seesion_state_value} 와 같이 사용하며, session_state_value 에 저장해서 활용하는 방식이다. 이를 Global Variable 처럼 쓸 수 있다.
  • 만약 session state 가 없다면 아래와 같이 코드를 짤 수 있다.

    Untitled

  • 그러나 increment 버튼을 아무리 눌러도 계속 결과는 1 이다.
  • 한 번 버튼을 누르면 재실행이 되어 count value 가 계속 0 으로 초기화 되기 때문이다. 즉 한 번 버튼을 누를 때마다 코드 전체가 재실행되는 것이다.
  • 이제 session state 가 있다면 아래와 같다.

    Untitled

  • 이제는 코드가 재실행이 되어도 st.session_state 의 값은 변하지 않아, 버튼을 누른 만큼 count 가 됨을 확인할 수 있다.
  • 따라서 계속 반복해서 사용하고 싶은 변수가 있으면 session_state 에 저장해주는 것이 중요하다.
  • session_state 를 사용할 때는 처음에 default value 변수가 있는지 확인하고 없으면 init 해준다. 만약 위 코드에서 if 문 없이 st.session_state.count = 0 으로 바로 할당했다면 계속 재실행 되어 무조건 0 으로 남게 된다. 따라서 처음에 st.session_state 에 해당 변수가 없을 때만 0 으로 init 한 것이다.
  • 이후 특정 조건 충족 시 session_state 에 저장한 변수가 증가하도록 만들면 된다.
  • 이와 관련해서 Session State 에 대해 잘 정리한 Streamlit blog 글을 보자.
  • 두 번째로 on_change Callback 함수를 사용할 수 있다.
  • 아래 그림과 같이 Streamlit Cache 를 뜻하는 @st.cache 를 데코레이터로 함수 위에 붙여준다.

    Untitled

  • Streamlit 은 매번 다시 실행하는 특성 때문에 데이터도 매번 다시 읽을 수 있다. 이런 경우 @st.cache 데코레이터를 사용해서 캐싱하면 좋다.
    • 캐싱은 성능을 위해 메모리 등에 저장하는 행위다.
    • 데이터를 읽는 함수를 만들고 @st.cache 데코레이터를 적용하게 되면, 다시 실행이 되더라도 캐싱이 되어 더 빠르게 실행된다.
맨 위로 이동 ↑

댓글 남기기