[시리즈] Streamlit 웹앱을 클라우드로 배포하기

Streamlit + Supabase로 내가 만든 웹앱을 배포해보자

Streamlit Community Cloud와 Supabase 연결하기

Intro

앞선 포스팅에서는 Streamlit이 무엇인지 알아보고, Streamlit으로 간단한 웹앱을 만들어보았다. 그리고 더 나아가 Streamlit Community Cloud를 통해 배포까지 진행해봤다.

이번 포스팅에서는 여기에 한 가지를 더 붙여보려고 한다. 바로 Supabase 데이터베이스와의 연결이 그것이다.

Streamlit은 파이썬 코드만으로 빠르게 웹앱을 만들 수 있다는 장점이 있다. 하지만 실제 서비스를 만들다 보면 데이터를 저장하거나 조회할 공간이 필요한 경우가 많다. 이 때 Supabase를 함께 사용하면, 별도의 백엔드 서버 또는 DB를 직접 구축하지 않더라도 PostgreSQL 기반의 데이터베이스와 백엔드를 비교적 간단하게 사용할 수 있다.

이번 포스팅에서는 Supabase에 만들어둔 users 테이블을 Streamlit Community Cloud에 배포한 앱에서 조회하는 실습을 진행해보겠다.

1. Supabase 간단 소개

Supabase는 Firebase의 오픈소스 대안으로 자주 소개되는 Backend-as-a-Service, BaaS 플랫폼이다.

Supabase에서 프로젝트를 생성하면, PostgreSQL 데이터베이스를 중심으로 인증, 스토리지, Edge Function, Realtime, REST API 등을 손쉽게 만들거나 활용할 수 있다. 쉽게 말해, PostgreSQL 기반의 온라인 백엔드 서비스라고 볼 수 있다.

이번 포스팅에서는 Supabase의 여러 기능 중에서 PostgreSQL 데이터베이스만을 사용할 예정이다. 구조는 아래와 같다.

1
2
3
4
5
Streamlit App
→ st.secrets에서 DB URL 조회
→ SQLAlchemy Engine 생성
→ Supabase PostgreSQL 조회
→ 화면에 데이터프레임으로 표시

2. Supabase 프로젝트 및 테이블 만들기

Streamlit에서 Supabase를 사용하려면 먼저 Supabase 프로젝트와 테이블이 준비되어 있어야 한다.

Supabase 프로젝트 생성과 SQLAlchemy, Alembic을 이용한 마이그레이션 방법은 이전 포스팅에서 다룬 바가 있으므로, 자세한 과정은 아래 글을 참고하면 된다.

[Supabase] Supabase 데이터베이스 마이그레이션(With SQLAlchemy & Alembic)

이번 포스팅에서는 Supabase DB에 users 테이블이 이미 만들어져 있다고 가정한다. 테이블은 id, name, email 세 개의 컬럼을 가진다.

그리고 Streamlit 앱에서 이 테이블에 접근하기 위해서는 Supabase DB 연결 URL이 필요하다. DB URL은 데이터베이스 서버 주소, 포트, 사용자 ID, 비밀번호, 데이터베이스 이름 등을 포함한다. 따라서 이 값은 절대 GitHub에 그대로 올리지 않도록 주의하자.

이 URL은 나중에 Streamlit Community Cloud의 Secrets에 등록해서 사용할 것이다.

3. Streamlit 코드에서 Supabase 조회하기

이제 Streamlit 앱에서 Supabase DB를 조회하는 코드를 작성해보자. 이번 예제에서는 SQLAlchemy를 사용한다. PostgreSQL에 연결해야 하므로 SQLAlchemy와 함께 PostgreSQL 드라이버도 설치한다.

1
uv add sqlalchemy psycopg2-binary

이제 DB 모델과 조회 함수를 작성한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# db/models.py
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, sessionmaker
from sqlalchemy import Integer, String, create_engine, select
import streamlit as st

ENGINE = create_engine(st.secrets["SUPABASE_DB_URL"])

class Base(DeclarativeBase):
    pass

class User(Base):
    '''유저테이블'''
    __tablename__ = "users"
    id    : Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True, comment="사용자 고유 ID")
    name  : Mapped[str] = mapped_column(String(50), comment="사용자 이름")
    email : Mapped[str] = mapped_column(String(100), unique=True, comment="사용자 이메일")

def retrieve_users():
    '''유저목록조회'''
    Session = sessionmaker(bind=ENGINE)
    with Session() as s:
        smtm = select(User.id, User.name, User.email)
        users = s.execute(smtm).all()
    return [{"id":u.id, "name":u.name, "email":u.email} for u in users]

여기서 눈여겨 봐야할 부분은 아래 코드다.

1
ENGINE = create_engine(st.secrets["SUPABASE_DB_URL"])

st.secrets["SUPABASE_DB_URL"]코드에 직접 DB URL을 적지 않고, Streamlit Community Cloud에 등록한 Secret 값을 불러오는 부분이다. 즉, 실제 DB 접속 정보는 GitHub에 올라가지 않고 Streamlit Cloud의 Secret 설정에만 저장할 것이다.

4. Streamlit 화면 코드 작성하기

이제 위에서 만든 retrieve_users() 함수를 Streamlit 화면 코드에서 사용해보자. 이전 포스팅에서 작성한 사용자 목록 화면 코드를 이어서 활용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# streamlit_app.py
import streamlit as st
import pandas as pd
from db.models import retrieve_users

st.title("Streamlit App Deploy Test")
st.write("유저 목록을 조회, 수정하는 웹앱")

def get_user_list() -> list[dict]:
    '''유저 목록 조회 함수'''
    try:
        return pd.DataFrame(retrieve_users())
    except:
        return None

# 01. 유저 목록 조회
user_data = get_user_list()
if user_data is None:
    user_data = [
        {
            "id": 1,
            "name": "김철수",
            "email": "cskim@example.com"
        },
        {
            "id": 2,
            "name": "남궁철수",
            "email": "ngcs@example.com"
        }
    ]

# 02. 세션에 유저 목록 초기화  
st.session_state.user_data = user_data

# 03. 데이터프레임 표출
if st.toggle("편집 모드"):
    edit_data = st.data_editor(pd.DataFrame(st.session_state.user_data),
                               use_container_width=True)
else:
    st.dataframe(pd.DataFrame(st.session_state.user_data),
                 use_container_width=True)

# 04. 누르면 풍선이 나오는 버튼 추가
st.button(label="풍선", on_click=st.balloons, type="primary")

이 코드는 먼저 Supabase DB에서 사용자 목록을 조회한다.

만약 DB 연결에 실패하면 예제 데이터를 대신 보여주도록 했다. 배포 과정에서 Secret 설정이 누락되었거나, DB URL이 잘못 입력된 경우에도 화면 자체는 확인할 수 있도록 하기 위함이다.

코드 작성이 끝났다면 GitHub에 푸시한다.

5. Streamlit Community Cloud 앱 생성하기

이제 Streamlit Community Cloud에서 앱을 생성한다.

이미 만들어둔 앱이 있다면 해당 앱의 설정을 수정해서 사용하면 된다. 아직 앱을 만들지 않았다면 아래 포스팅을 참고하여 먼저 Streamlit Community Cloud 앱을 생성한다.

[Streamlit] 파이썬 앱을 가장 쉽게 배포하는 방법 - Streamlit Community Cloud

여기까지의 흐름을 정리하면 다음과 같다.

1
2
3
4
5
6
1. Supabase 프로젝트와 users 테이블 준비
2. Streamlit 코드에서 st.secrets["SUPABASE_DB_URL"] 사용
3. 코드 GitHub에 푸시
4. Streamlit Community Cloud 앱 생성
5. Streamlit Cloud Secrets에 SUPABASE_DB_URL 등록
6. Deploy

코드에서 Secret을 먼저 읽도록 작성하고, 실제 Secret 값은 배포 설정에서 넣는다는 점을 반드시 기억하자.

6. Streamlit Community Cloud에 Secret 등록하기

이전 포스팅에서 Streamlit Community Cloud 앱을 생성할 때 Advanced Settings 기능을 잠깐 살펴본 적이 있다. 이 설정 화면에서는 파이썬 버전을 선택할 수 있고, 앱에서 사용할 Secrets도 함께 입력할 수 있다.

이번에는 이 Secrets에 Supabase DB URL을 등록한다.

이 값은 DB에 직접 접근할 수 있는 정보이므로 반드시 Secret에 넣어야 한다. GitHub 저장소에 .env, secrets.toml, DB URL 등을 그대로 올리지 않도록 주의해야 한다.

7. 웹앱 배포 및 확인

Secret 설정까지 완료했다면, Deploy 버튼을 눌러 배포를 수행한다. 배포가 완료되고 Streamlit 앱이 정상적으로 실행되면, Supabase DB에 저장된 users 테이블의 데이터가 화면에 표시된다.

이제 Streamlit Community Cloud에 배포된 앱이 Supabase PostgreSQL 데이터베이스를 조회하는 구조가 완성되었다.

8. 마치며

이번 포스팅에서는 Streamlit Community Cloud와 Supabase를 연결하는 방법을 살펴보았다. 핵심은 복잡하지 않다.

Streamlit 코드에서는 st.secrets를 통해 DB URL을 읽고, 실제 DB 접속 정보는 Streamlit Community Cloud의 Secrets에 따로 등록한다. 그리고 SQLAlchemy를 이용해 Supabase PostgreSQL에 연결하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Supabase
→ 프로젝트 생성
→ 테이블 준비
→ DB URL 확인

Streamlit 코드
→ SQLAlchemy로 DB 조회 코드 작성
→ st.secrets["SUPABASE_DB_URL"] 사용
→ GitHub에 푸시

Streamlit Community Cloud
→ 앱 생성
→ Secrets에 SUPABASE_DB_URL 등록
→ 배포 후 확인

즉, 코드와 설정을 분리하는 것이 가장 중요하다.

DB URL처럼 외부에 노출되면 안 되는 값은 코드에 직접 적지 않고, Streamlit Community Cloud의 Secrets를 통해 관리해야 한다. 이렇게 구성하면 GitHub에는 안전한 코드만 올리고, 실제 접속 정보는 배포 환경에서만 사용할 수 있다.

Reference

Connect Streamlit to Supabase - Streamlit Docs

[Streamlit Works With Supabase](https://supabase.com/partners/integrations/streamlit)

[시리즈] Streamlit 웹앱을 클라우드로 배포하기

Streamlit + Supabase로 내가 만든 웹앱을 배포해보자

Comments