Skip to content

Streamlit과 Caching 소개

Streamlit은 기계 학습 및 데이터 과학 프로젝트용으로 개발자가 대화형이고 사용자 친화적인 웹 애플리케이션을 만들 수 있는 오픈 소스 Python 라이브러리입니다. 프론트엔드 개발 기술이 필요하지 않고 몇 줄의 코드만으로 데이터 스크립트를 공유 가능한 웹 앱으로 변환하는 데 데이터 과학자와 엔지니어를 돕도록 설계되었습니다.

캐싱이란 컴퓨팅에서 데이터를 임시 저장 영역인 캐시에 저장하여 데이터 검색을 가속화하는 기술입니다. Streamlit의 맥락에서는 캐싱을 사용하여 대용량 데이터셋이나 복잡한 계산과 작업을 수행할 때 특히 웹 애플리케이션의 성능을 크게 향상시킬 수 있습니다.

Streamlit이란?

Streamlit은 데이터 과학과 기계 학습 분야에서 혁신적인 도구입니다. Streamlit을 사용하면 대화형이고 견고한 데이터 애플리케이션을 빠르게 구축할 수 있습니다. Streamlit을 사용하면 몇 줄의 Python 코드로 아름답고 데이터 중심의 웹 애플리케이션을 생성할 수 있습니다. 이것은 대용량 데이터셋과 복잡한 계산을 처리하도록 설계되어 데이터 과학자와 기계 학습 엔지니어에게 강력한 도구가 됩니다.

캐싱이란?

캐싱은 데이터를 일시적으로 고속 데이터 저장 계층인 캐시에 저장하는 기술입니다. 캐싱의 주요 목적은 기존의 느린 저장 계층에 접근할 필요 없이 데이터 검색 속도를 높이는 데 있습니다. 데이터가 요청되면 시스템은 먼저 캐시를 확인합니다. 데이터가 발견되면 즉시 반환됩니다. 그렇지 않으면 시스템은 데이터를 원래 저장소에서 가져오고 반환한 후 미래의 요청을 위해 캐시에 저장합니다.

Streamlit에서 캐싱이 필요한 이유

Streamlit에서 앱에서 상호작용이 발생할 때마다 전체 스크립트가 처음부터 다시 실행됩니다. 이 모델은 프로그래밍 모델을 간단하게 만들지만 비효율성을 초래할 수 있습니다. 예를 들어, 스크립트에 대용량 데이터셋을 로드하는 함수나 시간이 오래 걸리는 계산을 수행하는 함수가 포함되어 있다면, 스크립트가 재실행될 때마다 그 함수를 실행하고 싶지 않을 것입니다. 이때 캐싱이 필요합니다. Streamlit의 캐싱을 사용하면 특정 함수가 입력 값이 변경될 때만 다시 실행되도록 할 수 있습니다.

Streamlit 캐싱 사용의 장점

Streamlit의 캐싱은 여러 가지 이점을 제공합니다:

  • 성능 향상: 캐시에 비싼 함수 호출 결과를 저장함으로써 Streamlit 앱의 속도를 대폭 높일 수 있습니다. 특히 대용량 데이터셋이나 복잡한 기계 학습 모델과 함께 작업할 때 데이터 로드 또는 계산에 오랜 시간이 걸리는 경우에 이점이 큽니다.

  • 효율성 증대: 캐싱을 통해 불필요한 계산을 피할 수 있습니다. 함수가 이전과 같은 인수로 이전에 호출된 경우, Streamlit은 함수의 결과를 다시 계산하는 대신 캐시에서 결과를 검색할 수 있습니다.

  • 사용자 경험 향상: 로드 시간이 더 빠르고 반응성이 높은 앱은 더 좋은 사용자 경험을 제공합니다. 캐싱을 사용하면 사용자는 앱과 상호작용할 때마다 데이터가 로드되거나 계산이 완료될 때까지 기다릴 필요가 없습니다.

Streamlit의 캐싱 메커니즘을 사용하면 함수 계산 결과를 캐시에 저장하여 데이터 검색 속도를 높이고 앱 성능을 향상시킬 수 있습니다. 이 섹션에서는 Streamlit 캐싱 작동 방식, 이점 및 도전 과제에 대해 알아보겠습니다.

Streamlit 캐싱 사용의 도전 과제

캐싱은 강력한 기능이지만 몇 가지 도전 과제도 존재합니다:

  • 캐시 관리: 캐시 관리는 까다로울 수 있습니다. 캐시가 너무 많은 메모리를 소비하지 않도록하고 캐시된 함수의 입력이 변경된 경우에 올바르게 무효화되도록 보장해야 합니다.

  • 디버깅: 캐싱을 사용하면 디버깅이 더 복잡해질 수 있습니다. 함수의 출력이 캐시에서 읽혀지는 경우, 함수의 출력문이나 부작용이 발생하지 않아 디버깅이 더 어려울 수 있습니다.

  • 캐시 지속성: 기본적으로 Streamlit의 캐시는 Streamlit 서버를 다시 실행할 때마다 지워집니다. 여러 실행에서 지속적인 캐싱이 필요한 경우에는 고급 캐싱 옵션 또는 외부 캐싱 솔루션을 사용해야 합니다.

Streamlit 캐싱 작동 방식

Streamlit은 함수 정의 앞에 추가할 수 있는 @st.cache 데코레이터를 제공합니다. @st.cache 데코레이터로 함수를 표시하면 Streamlit은 해당 함수가 이전과 같은 입력과 함께 호출된 적이 있는지 확인합니다. 이전에 호출되었다면, Streamlit은 함수의 출력을 캐시에서 읽어옵니다. 그렇지 않다면 함수를 실행하고 결과를 캐시에 저장하고 결과를 반환합니다.

다음은 Streamlit 캐싱을 사용하는 간단한 예입니다:

@st.cache
def load_data():
    data = pd.read_csv('large_dataset.csv')
    return data

이 예제에서 load_data 함수는 스크립트가 몇 번이나 재실행되더라도 한 번만 실행됩니다. 결과는 캐시에 저장되어 나중에 사용하기 위해 저장되므로 시간과 계산 리소스를 절약할 수 있습니다.

Streamlit 캐싱 메커니즘: @st.cache, st.cache_data, 그리고 st.cache_resource

Streamlit은 여러 가지 캐싱 메커니즘을 제공하며 필요에 따라 사용할 수 있습니다. 이 섹션에서는 @st.cache, st.cache_data, st.cache_resource의 차이점을 설명합니다.

@st.cache

@st.cache는 함수 정의 앞에 추가하여 캐싱을 사용하도록 표시할 수 있는 데코레이터입니다. @st.cache가 표시된 함수가 호출되면 Streamlit은 해당 함수가 이전과 같은 입력으로 호출되었는지 확인합니다. 이전에 호출되었다면 Streamlit은 함수의 출력을 캐시에서 읽어옵니다. 그렇지 않다면 함수를 실행하고 결과를 캐시에 저장하고 결과를 반환합니다.

@st.cache를 사용하는 방법의 예입니다:

```python
@st.cache
def load_data():
    data = pd.read_csv('large_dataset.csv')
    return data

이 예제에서 `load_data` 함수는 스크립트를 재실행하는 횟수에 상관없이 한 번만 실행됩니다. 결과는 미래의 사용을 위해 캐시에 저장됩니다.

#### st.cache_data

`st.cache_data`는 데이터프레임 변환, 데이터베이스 쿼리 또는 머신러닝 추론과 같은 데이터를 반환하는 함수를 캐시하는 데 사용되는 데코레이터입니다. 캐시된 객체는 "pickled" 형태로 저장되며, 캐시된 함수의 반환 값은 pickleable해야 합니다. 캐시된 함수를 호출하는 각 호출자는 캐시된 데이터의 고유한 사본을 받게 됩니다. 함수의 캐시를 `func.clear()`로 지울 수 있고, 전체 캐시를 `st.cache_data.clear()`로 지울 수 있습니다. 글로벌 리소스를 캐시하려는 경우 `st.cache_resource`를 사용하는 것이 좋습니다.

함수 서명은 다음과 같습니다:

```python
st.cache_data(func=None, *, ttl, max_entries, show_spinner, persist, experimental_allow_widgets, hash_funcs=None)

매개변수는 캐시할 함수, 캐시에 항목을 유지할 최대 시간, 캐시에 유지할 최대 항목 수, spinner를 활성화할지 여부, 캐시된 데이터의 위치, 캐시된 함수에서 위젯을 사용할지 여부, 타입이나 완전한 이름을 해시 함수에 매핑하는 것 등이 포함됩니다.

st.cache_resource

st.cache_resource는 데이터베이스 연결 또는 머신러닝 모델과 같은 글로벌 리소스를 반환하는 함수를 캐시하는 데 사용되는 데코레이터입니다. 캐시된 객체는 모든 사용자, 세션 및 재실행에서 공동으로 사용됩니다. 이들은 여러 스레드에서 동시에 액세스될 수 있기 때문에 스레드 안전성이 보장되어야 합니다. 스레드 안전성이 문제인 경우 세션별로 리소스를 저장하기 위해 st.session_state를 사용하는 것이 좋습니다. 함수의 캐시를 func.clear()로 지울 수 있고, 전체 캐시를 st.cache_resource.clear()로 지울 수 있습니다.

함수 서명은 다음과 같습니다:

st.cache_resource(func, *, ttl, max_entries, show_spinner, validate, experimental_allow_widgets, hash_funcs=None)

매개변수는 캐시된 리소스를 생성하는 함수, 캐시에 항목을 유지할 최대 시간, 캐시에 유지할 최대 항목 수, spinner를 활성화할지 여부, 캐시된 데이터에 대한 선택적 유효성 검사 함수, 캐시된 함수에서 위젯을 사용할지 여부, 타입이나 완전한 이름을 해시 함수에 매핑하는 것 등이 포함됩니다.

Streamlit 캐싱 실전: 사용 사례 및 예제

Streamlit 캐싱은 데이터 애플리케이션의 성능을 개선하기 위해 다양한 시나리오에서 사용할 수 있습니다. 이 섹션에서는 일반적인 사용 사례를 탐색하고 Streamlit에서 캐싱을 구현하는 방법에 대한 예제를 제공합니다.

머신러닝 모델 캐싱

머신러닝 모델을 로드하는 것은 큰 모델의 경우 시간이 오래 걸릴 수 있습니다. 모델 로드 프로세스를 캐싱함으로써 Streamlit 앱의 성능을 크게 향상시킬 수 있습니다. 다음은 예입니다:

@st.cache(allow_output_mutation=True)
def load_model():
    model = load_your_model_here()  # 여기서 모델 로드 코드로 교체하세요
    return model

이 예제에서는 allow_output_mutation=True 옵션을 사용하는데, 이는 머신러닝 모델이 종종 해시할 수 없는 타입을 포함하기 때문에 Streamlit의 기본 캐싱과 호환되지 않는 경우입니다.

데이터 시각화 캐싱

데이터 시각화는 대량의 데이터셋을 처리할 때 계산적으로 요구되는 프로세스입니다. 데이터 시각화 함수의 결과를 캐싱하면 Streamlit 앱이 더 반응적이게 됩니다. 다음은 예입니다:

@st.cache
def create_plot(data):
    fig = perform_expensive_plotting_here(data)  # 여기서 플로팅 코드로 교체하세요
    return fig

이 예제에서는 create_plot 함수는 data 입력이 변경될 경우에만 다시 실행되며, 시간과 계산 리소스를 절약합니다.

API 호출 캐싱

Streamlit 앱이 API 호출을 수행하는 경우, 캐싱은 API 요청률 한도 초과를 방지하고 API 호출 수를 줄여 앱의 성능을 향상시킬 수 있습니다. 다음은 예입니다:

@st.cache
def fetch_data(api_url):
    response = requests.get(api_url)
    return response.json()

이 예제에서는 fetch_data 함수가 새로운 api_url로 호출될 경우에만 API 호출을 수행하고, 그렇지 않은 경우에는 캐시된 응답을 반환합니다.

웹 스크래핑 결과 캐싱

웹 스크래핑은 느릴 수 있는 프로세스이며, 동일한 웹사이트를 반복적으로 스크래핑하면 IP 차단될 수 있습니다. 웹 스크래핑 함수의 결과를 캐싱함으로써 불필요한 네트워크 요청을 피할 수 있습니다. 다음은 예입니다:

@st.cache
def scrape_website(url):
    data = perform_web_scraping_here(url)  # 여기서 웹 스크래핑 코드로 교체하세요
   
    return data

이 예제에서 scrape_website 함수는 새로운 url로 호출될 경우에만 웹 사이트를 스크래핑하고, 그렇지 않은 경우에는 캐시된 데이터를 반환합니다.

Streamlit 캐싱 최적화 기법

Streamlit 캐싱을 사용할 때 몇 가지 최적화 기법을 염두에 두어야 합니다:

  • @st.cache는 많이 사용하지 않아야 합니다: 캐싱은 앱의 성능을 크게 향상시킬 수 있지만, 조심해서 사용하지 않으면 많은 메모리를 소비할 수 있습니다. @st.cache는 주로 계산이 많이 필요한 함수나 큰 데이터셋을 처리하는 함수에만 사용하십시오.

  • 캐시된 함수에서 부작용을 피하세요: @st.cache로 표시된 함수는 부작용(side effects)을 가지지 않아야 합니다. 부작용이란 함수가 환경을 변경하는 것을 말합니다. 예를 들어, 전역 변수 수정이나 파일에 쓰기와 같은 작업이 있습니다. 부작용이 있는 함수가 캐시되면 부작용은 함수 호출시에만 발생합니다.

  • 가변 인수에 주의하세요: 캐시된 함수가 리스트나 사전과 같은 가변 인수를 사용하는 경우, Streamlit은 이러한 인수의 초기 값을 사용하여 캐시된 결과를 식별합니다. 함수를 호출한 후에 인수를 수정하면 Streamlit은 수정 사항을 인식하지 못하고 캐시된 결과를 반환합니다.

- **비 해시 가능한 출력에 `allow_output_mutation=True` 사용을 고려하십시오:** 기본적으로 Streamlit의 캐시는 함수의 출력이 해시 가능해야합니다. 기계 학습 모델과 같은 해시 불가능한 출력을 반환하는 경우, `allow_output_mutation=True` 옵션을 사용하여이 요구 사항을 우회 할 수 있습니다.

## 보너스: Streamlit의 대화 형 위젯

Streamlit의 대화 형 위젯은 다른 데이터 시각화 도구와 구별되는 주요 기능입니다. 이러한 위젯을 사용하면 사용자가 Streamlit 앱과 상호 작용하고 앱의 동작을 제어하며 데이터와 실시간으로 상호 작용 할 수 있습니다.

### 슬라이더

슬라이더 위젯을 사용하면 사용자는 수평 스케일을 따라 핸들을 슬라이드하여 값이나 값의 범위를 선택할 수 있습니다. 이것은 사용자가 앱의 숫자 매개 변수를 제어 할 수 있도록하는 데 유용합니다.

```python
age = st.slider('당신은 몇 살입니까?', 0, 130, 25)
st.write("저는", age, '살입니다')

이 예제에서 슬라이더를 사용하면 사용자는 0에서 130 사이의 연령을 선택하고 기본값을 25로 설정할 수 있습니다.

체크 박스

체크 박스 위젯을 사용하면 사용자는 이진 옵션을 켜거나 끌 수 있습니다. 이것은 사용자가 앱에서 특정 기능을 활성화하거나 비활성화 할 수 있도록하는 데 유용합니다.

agree = st.checkbox('동의합니다')
if agree:
    st.write('좋아요!')

이 예제에서 체크 박스를 사용하면 사용자는 문장에 동의하거나 동의하지 않을 수 있습니다. 사용자가 체크 박스를 선택하면 앱에 "좋아요!" 메시지가 표시됩니다.

텍스트 입력

텍스트 입력 위젯을 사용하면 사용자가 텍스트 문자열을 입력 할 수 있습니다. 이것은 사용자가 앱에 텍스트 데이터를 입력 할 수 있도록하는 데 유용합니다.

title = st.text_input('영화 제목', '브라이언의 삶')
st.write('현재 영화 제목은', title, '입니다')

이 예제에서 텍스트 입력을 사용하면 사용자는 영화를 입력 할 수 있습니다.

개코 하는 코딩의 Sven이 제작 한 이 멋진 데이터 분석 및 데이터 시각화 도구로 Streamlit App을 Tableau로 변환해 보셨나요?

PyGWalker (opens in a new tab)는 Streamlit 앱에 Tableau와 유사한 사용자 인터페이스를 쉽게 통합 할 수 있도록 도와주는 Python 라이브러리입니다. Coding is Fun (opens in a new tab)의 Sven이 제작 한이 강력한 데이터 시각화 Python 라이브러리로 Streamlit 앱에 힘을 실어주는 자세한 단계를 설명하는 놀라운 비디오를 확인하십시오!


Sven 및 그의 훌륭한 기여 (opens in a new tab)에 특별히 감사드립니다 PyGWalker 커뮤니티!

추가로 PyGWalker GitHub 페이지 (opens in a new tab)에서 PyGWalker 예제를 더 확인할 수도 있습니다.

결론

Streamlit의 캐싱 메커니즘은 불필요한 계산을 피하여 앱을 크게 가속화 할 수있는 강력한 도구입니다. Streamlit의 캐싱 작업 방식과 효과적인 사용 방법을 이해하면 더 효율적이고 응답성있는 앱을 만들 수 있습니다. 데이터 변환, 기계 학습 모델 또는 API 호출과 같은 데이터 캐시를 사용하면 Streamlit의 캐싱이 원활하고 상호 작용이있는 사용자 경험을 제공하는 데 도움이됩니다.

성능을 향상시킬 수는 있지만 캐싱이 항상 옳은 해결책은 아닙니다. 언제나 트레이드 오프를 고려하고 캐싱이 예상치 못한 동작을 유발하지 않고 앱의 성능을 향상시키는지 꼼꼼히 테스트하십시오.

슬라이더, 체크 박스 및 텍스트 입력과 같은 Streamlit의 대화 형 위젯은 사용자가 앱과 상호 작용하고 동작을 제어하는 방법을 제공합니다. 이러한 위젯을 Streamlit의 캐싱 메커니즘과 결합하여 강력하고 응답성있는 데이터 애플리케이션을 만들 수 있습니다.

마지막으로, Streamlit의 간결성, 유연성 및 데이터와 기계 학습에 대한 집중이 데이터 애플리케이션을 구축하기에 좋은 선택이 됩니다. 캐싱 메커니즘과 대화 형 위젯을 사용하여 강력하고 효율적이며 상호 작용적 인 앱을 만들 수 있습니다.

개코 하는 코딩의 Sven이 제작 한 이 멋진 데이터 분석 및 데이터 시각화 도구로 Streamlit App을 Tableau로 변환해 보셨나요?

PyGWalker (opens in a new tab)는 Streamlit 앱에 Tableau와 유사한 사용자 인터페이스를 쉽게 통합 할 수 있도록 도와주는 Python 라이브러리입니다.

PyGWalker을 사용한 Streamlit에서의 데이터 시각화 (opens in a new tab)

자주 묻는 질문

Streamlit 캐시는 어떻게 작동합니까?

Streamlit의 캐시 메커니즘은 함수 호출 결과를 캐시에 저장하여 작동합니다. @st.cache로 장식 된 함수가 호출되면 Streamlit은 이전에 동일한 입력으로 함수가 호출되었는지 확인합니다. 그렇다면 Streamlit은 함수를 실행하는 대신 캐시 된 결과를 사용할 수 있습니다. 이렇게하면 데이터로드 또는 기계 학습 모델 실행과 같은 비용이 많이 드는 계산을 피할 수 있으므로 앱이 크게 가속화될 수 있습니다.

Streamlit 캐시의 제한 사항은 무엇인가요?

Streamlit의 캐싱 메커니즘은 강력하지만 일부 제한 사항이 있습니다. 예를 들어, 캐시된 함수의 반환 값은 pickleable해야하며 Python의 pickle 모듈을 사용하여 직렬화 및 직렬화 할 수 있어야합니다. 캐시 된 함수에서는 모든 Python 객체가 반환 될 수없는 의미입니다. 추가적으로 캐시 된 함수에는 부작용이 없어야합니다. 이는 함수가 호출되는 첫 번째 시간에만 실행됩니다.

Streamlit에서 캐시를 지우는 방법은 무엇인가요?

st.cache.clear() 함수를 사용하여 Streamlit에서 캐시를 지울 수 있습니다. 이렇게하면 캐시에서 모든 항목이 제거됩니다. 특정 함수의 캐시를 지우려면 func.clear() 메서드를 사용할 수 있습니다. 여기서 func는 캐시 된 함수입니다.

Streamlit 캐시가 어디에 있습니까? Streamlit의 캐시는 기본적으로 메모리에 저장됩니다. 이는 Streamlit 앱이 재시작될 때마다 캐시가 지워진다는 것을 의미합니다. 그러나 @st.cache 데코레이터의 persist 매개변수를 True로 설정하여 Streamlit에서 캐시를 디스크에 유지할 수 있습니다.