Streamlit Study
Streamlit을 사용하다보면 유저로 하여금 scroll을 하게 하는 것과 같이 특정 상황에 특정 위치로 이동시켜야 하는 케이스가 종종 발생한다. 이는 멀티 페이지나 멀티 탭으로 구현하는 기능과는 다르며 한 페이지 내에서 작동해야 하는데, 문제는 streamlit 자체적으로는 이러한 기능이 존재하지 않는다.
이에 대해 streamlit cummunity 등에서 몇 개의 topic이 진행되고 있으나 그들이 원하는 바대로 제대로 동작하는지 애매한 코드들이 많아, 이를 정리해놓고자 한다.
기본적으로 streamlit에서 scroll을 위해선 크게 세 단계를 거쳐야 하며, 이는 다음과 같다.
1. 이동하고자 하는 element의 위치를 특정하는 값을 찾는다(ex. js_path, id)
2. 해당 element로 이동하도록 js를 작성한다
3. js가 동작하도록 streamlit v1 components의 html을 사용한다
(markdown으로는 안됨)
이를 코드로 구현하며 기초부터 구현해보면 다음과 같다.
기본적으로 Streamlit 컴포넌트들이 위에서부터 아래로 생성되기에 단방향 프로세스를 가진 서비스라면 중간중간에 제일 아래로 내리는 것만으로도 충분하다. 이럴 때 사용할 수 있는 코드는 다음과 같다.
위 코드는 반드시 존재할 수밖에 없는 main 태그를 찾아 그 아래로 쭉 내리는 방식이다. 만약 마지막까지 내리는 것이 아니라면 위 코드 4번째 줄의 9999999999를 적당히 작은 값으로 바꿔주며 테스트하면 된다.
이를 이용해 다음과 같이 간단한 코드를 작성하고 테스트해볼 수 있다.
위 코드를 살펴보면 하나의 title 아래로 두 개의 컨테이너를 구축했고, 그 안에는 scroll할만큼 긴 페이지를 만들기 위해 20개의 st.write를 사용한 화면이다. 사이드바를 통해 하나의 버튼을 추가했고, 이 버튼을 누르면 화면의 제일 밑으로 scroll하는 함수가 호출되도록 callback을 작성했다.
위 페이지를 시연한 영상은 아래와 같다.
Streamlit에서는 굳이 custom component를 만들지 않더라도 java script 등을 통해 사전에 구현되지 않은 기능을 적용할 수 있다. 여기서 사용할 것은 간단하게 js path를 이용해 특정 컨텐츠를 찾는 방식인데, id를 사용하는 방법도 있지만 이는 특정 컴포넌트를 만들면서 고유 id를 삽입해야 하는 등의 문제가 있을 수 있으므로 넘어간다.
전체코드를 먼저 살펴보면 아래와 같다.
위 코드는 첫 번째와 본문의 코드는 동일하나, 스크롤하는 방식에서 차이가 있다. 위 코드는 js path를 찾아 해당 컴포넌트로 이동하는 코드인데, 각각 첫 번째 컨테이너, 두 번째 컨테이너, 제일 밑으로 scroll되도록 한다. 위 코드만으로는 현재 정상적으로 동작하지 않는데, 그 이유는 첫 번째와 두 번째 컨테이너의 js_path를 입력하지 않았기 때문이다.
이는 아래 영상을 보며 어떻게 js_path를 지정하는지 살펴보면 된다.
참고로 제일 밑으로 내려가는 코드는 모든 페이지에 필수적인 footer를 이용했으며, 이는 별도로 찾지 않아도 된다. 이 단계까지 할 수 있다면 이젠 특정 Component로 이동하는 것은 크게 어렵지 않다. streamlit으로 생성한 component가 동적으로 생성되긴 하지만, 내부적인 규칙이 있기 때문에 모든 UI가 완성된 상태라면 js path가 바뀌어 온전히 작동하지 않는 걱정은 하지 않아도 된다.
이번 단계에서 할 것은 그저 scroll하는 방식을 좀 더 디테일하게 조정하는 것이다. 이전 단계에서 사용한 스크롤 방식은 특정 위치로 순식간에 이동하기에 사용자 경험상 그리 유쾌한 방식은 아니다. 그렇기 때문에 조금 더 부드럽게 이동하거나, 보다 원하는 위치로 이동할 수 있는 코드를 구현하면 아래와 같다.
위 코드는 java script의 scrollIntiView 내부의 파라미터를 지정해 보다 부드럽게 이동하고, 우리가 지정한 컴포넌트가 페이지의 가운데 오도록 한다. 이를 구현한 영상은 아래와 같다.