본문 바로가기

[6] streamlit session state

들어가며

🏫 전체 강의 영상

📕 포켓몬 도감 실습 프로젝트

 ▶️  강의 영상

 

이번 챕터에서는 session state를 이용해서 데이터를 관리하는 방법을 배워보겠습니다.

streamlit session state

streamlit session state는 페이지가 살아있을 때, 데이터를 저장하는 일종의 딕셔너리입니다.

streamlit session state 문서: https://docs.streamlit.io/library/api-reference/session-state

streamlit이 공식적으로 제공하는 설명 영상이 상당히 자세해서 정확히 이해하고 싶으신 분들은 한번 보시기를 추천합니다. 간단히 요약하면 session state를 사용하면 streamlit에 의해서 페이지가 리로딩 될 때에도 상태 정보를 유지할 수 있습니다. 하나씩 이해해보겠습니다.

streamlit 동작 방식

session state를 자유롭게 사용하기 위해서는 먼저 streamlit이 동작하는 방식을 이해해야 합니다. streamlit은 UI에 변경 사항이 생길 경우, 전체 페이지를 리로딩합니다. python 코드를 처음부터 다시 실행한다고 생각하면 됩니다. 한번 페이지 최상단에 print문을 추가해보겠습니다.

import streamlit as st

print("page reload")
...

그 다음 submit 버튼을 눌러보면 “page reload”가 출력되면서 전체 python 스크립트가 재실행 되는 것을 확인할 수 있습니다.

포켓몬이 추가되지 않은 이유

포켓몬이 계속해서 추가되지 않고 1마리만 추가된 이유는 바로 페이지 리로딩 때문에 그렇습니다. 페이지가 리로딩 할 때마다 pokemons라는 변수에 6마리의 포켓몬이 들어있는 배열을 할당합니다. 여기에 현재 폼에 입력된 데이터만 추가하므로 아무리 submit을 하더라도 7마리의 포켓몬만 배열에 들어있게 됩니다.

# 페이지가 리로딩 될 때마다 pokemons에 여섯마리 포켓몬을 할당
# 이전 시점에 추가한 포켓몬은 날아감
pokemons = [
    {
        "name": "피카츄",
        "types": ["전기"],
        "image_url": "https://i.namu.wiki/i/R9GjiUEKY9snXwP9mqXDRsHkZ0yK5GVoJtFHEMCamYe5jd4FeIrcMMU6ZRuMnJ0Pckci7qhOhWhXLqqoRNfovfVysbJVtiO1J2aiwwlf6Xi-_KHpXCnkchch9GxvW5zVKf_5PeTtSQD5xm6yLrdMdw.webp",
    },
    ...
]
...
# 6마리가 할당되어 있는 pokemons에 새 포켓몬 추가
pokemons.append({
    "name": name,
    "types": types,
    "image_url": image_url if image_url else "./images/default.png"
})

session state를 이용한 포켓몬 추가

페이지 리로딩에 대해서 알아봤으니 이제 session state를 사용해서 문제를 해결해보겠습니다. 먼저 기존의 pokemons 변수명을 initial_pokemons로 바꿔주겠습니다. 그 다음 session_state에 pokemons라는 키 값이 있는지 체크하고, 없으면 initial_pokemons를 할당해주겠습니다.

# pokemons -> initial_pokemons 변수명 변경
initial_pokemons = [
    {
        "name": "피카츄",
        "types": ["전기"],
        "image_url": "https://i.namu.wiki/i/R9GjiUEKY9snXwP9mqXDRsHkZ0yK5GVoJtFHEMCamYe5jd4FeIrcMMU6ZRuMnJ0Pckci7qhOhWhXLqqoRNfovfVysbJVtiO1J2aiwwlf6Xi-_KHpXCnkchch9GxvW5zVKf_5PeTtSQD5xm6yLrdMdw.webp",
    },
    ...
]

# session_state에 키 값 체크, 없으면 초기값 할당
if "pokemons" not in st.session_state:
    st.session_state.pokemons = initial_pokemons

그 다음, 새 포켓몬을 추가하거나 화면에 그려줄 때에는 그냥 pokemons 배열에 접근하는 것이 아니라, session_state의 pokemons에 접근하도록 코드를 수정합니다.

...
with st.form(key="form"):
		...
    if submit:
        ...
        else:
            st.success("포켓몬을 추가할 수 있습니다.")
            st.session_state.pokemons.append({
                "name": name,
                "types": types,
                "image_url": image_url if image_url else "./images/default.png"
            })

for i in range(0, len(st.session_state.pokemons), 3):
    row_pokemons = st.session_state.pokemons[i:i+3]
    ...

정리

이번 챕터에서는 form을 이용해서 유저의 입력을 받고, 데이터를 추가하는 기능을 구현해보겠습니다. 다음 챕터에서는 session state를 이용해서 데이터를 관리하는 방법을 배워보겠습니다.