서문
모든 것은 하나의 엑셀 파일에서 시작되었습니다. 저 혼자 공정 현황을 관리하던 시절,
'엑셀 + SQLite' 기반의 WIP(Work-In-Process) 시스템은 완벽한 제 비서였습니다.
하지만 동료들이 하나둘씩 제 시스템의 가치를 알아보고 함께 사용하기 시작했을 때,
비서는 비명을 지르기 시작했습니다. 데이터는 엉키고, 현장은 소리 없는 아우성을 쳤습니다.
"파일이 잠겼어요!", "이거 최신 버전 맞아요?", "외부에서는 왜 접속이 안 되나요?"
이 반복되는 질문들 속에서 저는 깨달았습니다. 이것은 더 이상 저 혼자만의 문제가 아니며,
로컬 자동화를 넘어 클라우드 협업 시스템으로 진화해야 할 때가 왔다는 것을.
🚩 문제 정의: SQLite의 한계
SQLite는 뛰어난 로컬 데이터베이스지만, 태생적으로 단일 사용자 환경에 최적화되어 있습니다.
여러 사람이 동시에 데이터를 쓰면, 파일이 잠기거나 손상되는 문제가 반복되었습니다.
“회사에서는 잘 돌아가던 게, 현장에서 동시에 열면 멈춥니다.”
— 실제 현장 팀장님의 목소리였습니다.
수동 백업은 더 큰 문제였습니다.
매번 파일을 옮겨야 했고, 어떤 파일이 최신인지 구분조차 어려워 데이터 유실의 위험이 항상 존재했습니다.
해결책: Supabase로의 전환
Supabase는 PostgreSQL 기반의 완전 관리형 백엔드 서비스입니다.
단순히 DB를 서버로 옮기는 것을 넘어, 실시간 데이터 동기화, 사용자 인증, API까지 모두 제공하는 강력한 솔루션입니다.
제가 Supabase를 선택한 이유는 명확했습니다.
- 실시간성: 현장에서 공정 상태를 바꾸면, 본사 사무실 화면도 즉시 바뀌어야 한다.
- 보안성: 사용자별로 데이터 수정 권한을 다르게 부여할 수 있어야 한다.
- 확장성: 앞으로 프로젝트가 수백 개로 늘어나도 흔들림 없이 안정적이어야 한다.


🔧 구현 단계
1️⃣ Supabase 연결
from supabase import create_client
import streamlit as st
# secrets.toml로 보안 키를 안전하게 관리
SUPABASE_URL = st.secrets["supabase"]["SUPABASE_URL"]
SUPABASE_KEY = st.secrets["supabase"]["SUPABASE_KEY"]
supabase = create_client(SUPABASE_URL, SUPABASE_KEY)
data = supabase.table("wip_projects").select("*").execute()
st.dataframe(data.data)
Supabase 클라이언트를 통해 데이터를 불러와 대시보드에 출력하는 것은 놀랍도록 간단했습니다.
2️⃣ 캐싱으로 속도 개선
@st.cache_data(ttl=60) # 60초 동안 결과 캐싱
def load_wip_data():
return supabase.table("wip_projects").select("*").execute().data
초기 로딩에 20초 가까이 걸리던 쿼리가, 캐싱을 적용하자 1초 이내로 단축되었습니다. 사용자 경험이 극적으로 향상된 순간입니다.
3️⃣ 실시간 반영 (Realtime)
from supabase.realtime import Client
client = Client(SUPABASE_URL, SUPABASE_KEY)
def on_update(payload):
st.toast(f"프로젝트 상태 변경: {payload['record']['status']}")
# 'wip_projects' 테이블의 모든 변경사항을 구독
client.subscribe("wip_projects", callback=on_update)
이제 누군가 데이터를 변경하면, 앱을 보고 있는 모든 사람의 화면에 새로고침 없이 즉시 반영됩니다. 이 기능을 본 직원들의 첫마디는 "이제 진짜 시스템 같다"였습니다.
🤖 Human-AI Hybrid Team: 개발 과정을 이끈 어벤져스
이번 Supabase 전환은 저 혼자만의 힘으로 이뤄낸 것이 아닙니다.
저는 총괄 PM으로서 방향을 제시했고, 각기 다른 전문성을 가진 AI 어시턴트들이 팀원이 되어주었습니다.
- @지니 (전략/기획): 저와 함께 전체적인 마이그레이션 전략을 수립하고,
- 스키마 분리와 같은 기술적 리스크를 분석하며 최적의 경로를 제안했습니다.
- @클로 (백엔드/DB):
tenant_id를 포함한 미래 확장형 Supabase 스키마를 설계하고, - 복잡한 데이터 관계와 보안 정책을 담은 SQL 스크립트를 작성했습니다.
- @채트 (프론트엔드/UI): Streamlit 코드를 Supabase 클라이언트에 맞게 수정하고,
- 실시간 UI 반영 로직과 사용자 인증(로그인) 화면을 구현했습니다.
이처럼 인간이 비전과 문제 정의를 제시 및 앱 사용 피드백을 하고,
AI가 각자의 전문 분야에서 구현을 담당하는 협업 모델은 개발 속도를 극적으로 높여주었습니다.
🧩 시스템 구조 다이어그램
mermaid
flowchart LR
A[사용자 입력] --> B[Streamlit UI]
B --> C{PtopEngine API}
C --> D[Supabase]
D -->|실시간 이벤트| E[WebSocket]
E --> B
“Streamlit이 프런트엔드, Supabase가 백엔드 ‘문제 해결’
⚙️ 핵심 기능 요약 (v0.7)
| 기능 | 설명 |
|---|---|
| 실시간 프로젝트 현황판 | 총/진행/임박/완료 자동 계산 |
| 업체별 발주 현황 필터 | 특정 협력업체만 조회 가능 |
| 상태 업데이트 자동 반영 | WebSocket 기반 실시간 반영 |
| Supabase Auth 통합 | 로그인/세션/관리자 권한 부여 |
📊 성능 비교 (전/후)
| 항목 | SQLite (Local) | Supabase (Cloud) | 개선 효과 |
|---|---|---|---|
| 저장 방식 | 파일 기반 | REST API | 안정성 확보 |
| 사용자 수 | 1명 | 동시 다중 | 협업 가능 |
| 반응 속도 | 평균 18~20초 | 1초 이내 | 95% 속도 향상 |
| 데이터 충돌 | 빈번 | 없음 | 신뢰도 향상 |
| 백업 | 수동 | 자동 | 데이터 보호 |
| 실시간 반영 | 불가 | 가능 | 업무 효율 극대화 |
결과: “로컬 자동화”에서 “클라우드 협업”으로 한 단계 도약했습니다.
🔒 인증 시스템 도입
auth_ui.py 모듈을 추가하여, Supabase Auth를 활용한 로그인 + 세션 관리 + 권한 구분을 구현했습니다.
- 일반 사용자: 데이터 조회
- 관리자: 수정·삭제 권한
- 비로그인 사용자: 접근 차단
“누가, 언제, 무엇을 변경했는지”까지 추적 가능한 구조로 발전했습니다.
🧠 교훈 (Lessons Learned)
- '파일 잠김'은 진화의 신호탄입니다.
동료가 당신의 엑셀 파일을 궁금해 한다면? 그 시스템이 인정을 받았다는 뜻! 이제는 클라우드 서비스로 진출! - DB 설계는 건물의 설계도와 같습니다.
Supabase 전환의 성패 80%는 SQL 스키마 설계에서 결정됩니다.tenant_id같은 컬럼 하나가 확장을 쉽게 해주죠. - Supabase는 'IT 부서 없는' 중소기업을 위한 최고의 무기!
서버 관리, DB 설정, API 개발의 부담 없이, 오직 '문제 해결'이라는 본질에만 집중하게 해줍니다.
비전공자들에게는 최고의 선택입니다.
🔮 다음 이야기 예고
다음 글 [개발기 #5]에서는 이 Supabase 기반 시스템에 권한 관리(Auth) + SaaS 구조를 결합해,
“실제 회사 단위로 배포 가능한 버전”으로 확장한 과정을 공유하겠습니다.
'Project_Aegis > [BIM & Automation]' 카테고리의 다른 글
| 실시간 공정관리, MES 도입 전 반드시 확인해야 할 3가지 실패 패턴 (0) | 2025.10.20 |
|---|---|
| 앱 성장기, 단일 고객용 툴에서 멀티테넌트 SaaS로의 진화 (1) | 2025.10.14 |
| [개발기 #3] PDF 파싱이라는 '멋진 실수', 그리고 제가 찾은 '진짜' 자동화 (0) | 2025.10.10 |
| [개발기 #1] 매일 4시간 걸리던 엑셀 노가다, Python 코드 2줄로 10분 만에 끝낸 방법 (0) | 2025.10.06 |
| 파이썬 3주만에 '금속 구조물 자동화 시스템' 프로토타입 v1.0 개발기 (0) | 2025.09.22 |