[개발기 #4] WIP 공정관리 시스템 v0.7 — Supabase로 완전 전환한 실시간 제조 관리 앱의 탄생기

반응형

서문

모든 것은 하나의 엑셀 파일에서 시작되었습니다. 저 혼자 공정 현황을 관리하던 시절,

'엑셀 + SQLite' 기반의 WIP(Work-In-Process) 시스템은 완벽한 제 비서였습니다.

하지만 동료들이 하나둘씩 제 시스템의 가치를 알아보고 함께 사용하기 시작했을 때,

비서는 비명을 지르기 시작했습니다. 데이터는 엉키고, 현장은 소리 없는 아우성을 쳤습니다.

"파일이 잠겼어요!", "이거 최신 버전 맞아요?", "외부에서는 왜 접속이 안 되나요?"

이 반복되는 질문들 속에서 저는 깨달았습니다. 이것은 더 이상 저 혼자만의 문제가 아니며,

로컬 자동화를 넘어 클라우드 협업 시스템으로 진화해야 할 때가 왔다는 것을.


🚩 문제 정의: SQLite의 한계

SQLite는 뛰어난 로컬 데이터베이스지만, 태생적으로 단일 사용자 환경에 최적화되어 있습니다.

여러 사람이 동시에 데이터를 쓰면, 파일이 잠기거나 손상되는 문제가 반복되었습니다.

“회사에서는 잘 돌아가던 게, 현장에서 동시에 열면 멈춥니다.”
— 실제 현장 팀장님의 목소리였습니다.

수동 백업은 더 큰 문제였습니다.

매번 파일을 옮겨야 했고, 어떤 파일이 최신인지 구분조차 어려워 데이터 유실의 위험이 항상 존재했습니다.


 해결책: Supabase로의 전환

Supabase는 PostgreSQL 기반의 완전 관리형 백엔드 서비스입니다.

단순히 DB를 서버로 옮기는 것을 넘어, 실시간 데이터 동기화, 사용자 인증, API까지 모두 제공하는 강력한 솔루션입니다.

제가 Supabase를 선택한 이유는 명확했습니다.

  1. 실시간성: 현장에서 공정 상태를 바꾸면, 본사 사무실 화면도 즉시 바뀌어야 한다.
  2. 보안성: 사용자별로 데이터 수정 권한을 다르게 부여할 수 있어야 한다.
  3. 확장성: 앞으로 프로젝트가 수백 개로 늘어나도 흔들림 없이 안정적이어야 한다.

 

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)

  1. '파일 잠김'은 진화의 신호탄입니다.
    동료가 당신의 엑셀 파일을 궁금해 한다면? 그 시스템이 인정을 받았다는 뜻! 이제는 클라우드 서비스로 진출!
  2. DB 설계는 건물의 설계도와 같습니다.
    Supabase 전환의 성패 80%는 SQL 스키마 설계에서 결정됩니다. tenant_id 같은 컬럼 하나가 확장을 쉽게 해주죠.
  3. Supabase는 'IT 부서 없는' 중소기업을 위한 최고의 무기!
    서버 관리, DB 설정, API 개발의 부담 없이, 오직 '문제 해결'이라는 본질에만 집중하게 해줍니다.
    비전공자들에게는 최고의 선택입니다.

🔮 다음 이야기 예고

다음 글 [개발기 #5]에서는 이 Supabase 기반 시스템에 권한 관리(Auth) + SaaS 구조를 결합해,
“실제 회사 단위로 배포 가능한 버전”으로 확장한 과정을 공유하겠습니다.


반응형