부서별 자체 개발 · 사내 호스팅

각 부서가 자기 문제를
직접 만들어 쓴다

플랫폼을 넘어, 각 부서가 자기 업무의 불편을 Claude Code와 함께 직접 풀어 만들고 사내에 호스팅해 운영 중인 앱들입니다. 인사지원실의 회의실 예약, 커머스전략의 bq-explorer — 그리고 이들을 하나로 묶는 드롭인 SSO.

FastAPI React / Vite DuckDB Google Workspace Google OAuth SSO
🎯 핵심: 부서가 스스로 만들고, 공통 인증(SSO)만 재사용해 안전하게 사내 배포한다.
🧩
GCX팀 · 스크립트/자동화 호스팅
HQ_GCX 스크립트 호스팅

GCX팀의 자동화 자산 — Tampermonkey 유저스크립트 · Python 스크래퍼 · GAS · Apify — 을 플랫폼의 static + job 런타임으로 호스팅합니다. 브라우저 확장 스크립트는 정적으로 버전 서빙, 데이터 수집 스크래퍼는 스케줄 잡으로.

🧩 유저스크립트 (static)
Amazon MCF/Invoice 자동화 등 Tampermonkey .user.js를 엣지에서 버전관리·배포. 각자 수동 설치 대신 중앙에서.
⏰ 스크래퍼 (job)
리뷰·순위 등 수집 Python 스크래퍼를 cron 스케줄 잡으로. SP-API 키 등은 시크릿 주입, 결과는 저장소로.
🔌 외부 연동도 한 콘솔에서
GAS·Apify·Sheets 등 외부 실행을 시크릿 금고 + 트리거로 엮어 한 콘솔에서 관측·관리.
📈
커머스전략사업부 · 자체 개발
bq-explorer · 커머스 데이터 대시보드

BigQuery 원본을 로컬 DuckDB에 미러링해 매출·재고·할인을 KPI·차트·드릴다운으로 보는 커머스 분석 대시보드. @spigen.com 구글 SSO 게이트로 접근을 제한합니다.

BigQuery → 로컬 미러 → 대시보드
☁️
BigQuery
매출·재고·상품 원본
🦆
DuckDB 미러
주기 동기화 · 로컬 고속 쿼리
📊
대시보드
매출·재고·할인·YoY 드릴다운
🔐
SSO 게이트
@spigen.com Google 로그인
BQ → DuckDB 동기화
원본을 로컬에 미러링해 빠른 탐색. 자연어/SQL로 즉석 조회.
다중 대시보드
매출·재고·할인·YoY 등 커머스 지표를 KPI·차트·드릴다운으로.
드롭인 SSO 게이트
아래의 공통 SSO 모듈을 그대로 얹어 @spigen.com만 접근.
공통 자산 · 드롭인 SSO
부서 앱마다 다시 만들지 않는다

부서 앱이 늘어날수록 매번 로그인을 새로 붙이는 건 낭비 — 그래서 "폴더 하나 복사 + 한 줄"이면 @spigen.com 구글 로그인 게이트가 붙는 재사용 SSO 모듈을 만들었습니다. FastAPI 앱이면 어디든 동일하게.

한 줄로 적용
from sso_login import installinstall(app). 미인증 접근은 로그인으로, 로그인 사용자만 통과. 새 의존성 0(표준 라이브러리만).
두 가지 모드
직접 Google OAuth(앱에 도메인+HTTPS가 있을 때) / 브로커 위임(사내 IP 앱은 중앙 브로커에 위임해 토큰만 검증). 상황에 맞게 선택.
사내 IP도 HTTPS로
구글은 사설 IP·http 콜백을 거부하므로, nip.io 도메인 + 자체 인증서로 감싸 사내 서버에서도 구글 로그인이 되게 함.
설정은 함께 이동
모드·클라이언트 ID는 폴더 내 설정 파일로 git과 함께 이동, 비밀 값은 커밋하지 않고 배포 시 주입. 접속 주소는 자동 도출.
호스팅 콘솔 · 탄생 과정
"정적 호스팅"에서 사내 미니 PaaS로

부서 앱이 늘자, 매번 서버를 잡아주는 대신 APM 위에 사내 호스팅 콘솔을 얹기로 했습니다. 그 결론에 이르기까지 오간 판단들입니다.

① 처음엔 "파이어베이스식 정적 호스팅"
private GitHub에 올린 결과물을 연결하면 정적으로 서빙해주자는 구상에서 출발.
② 부서 프로젝트를 뜯어보니 정적이 아니었다
bq-explorer는 장수 FastAPI 서버, GCX는 스케줄 스크래퍼 + 스크립트 — 순수 정적은 없었음. → "정적-only" 폐기.
③ 멀티런타임으로 확정
static · container · job 세 런타임으로 재설계. Dockerfile이 완비된 bq-explorer를 이상적 container 파일럿으로.
④ 왜 APM 위에 얹나
APM은 이미 SSH실행·위협탐지·IP차단·가동률·알림을 쥔 control plane. 여기 얹으면 "호스팅했다"는 사실만으로 보안·관측이 공짜로 붙음 — 필요 부품의 70%가 이미 존재.
호스팅 방식 · 분류 기준
앱의 실행 성격으로 런타임을 나눈다

"정적 배포냐 · 상주 실행이냐 · 스케줄 실행이냐" — 앱의 성격에 따라 세 런타임으로 나누고, 각자에 맞는 것을 플랫폼이 제공합니다. 앱이 강제받는 계약은 spgapp.json 매니페스트 한 장뿐(프레임워크 락인 없음).

📄 static — 정적 서빙
빌드 산출물·정적 파일. 예: GCX Tampermonkey .user.js. 엣지 서빙 · 버저닝 · visibility 정책.
📦 container — 상주 서버앱
장수 프로세스. 예: bq-explorer(FastAPI+DuckDB). 컨테이너 실행 · 영속 볼륨 · 시크릿 주입 · 헬스체크.
⏰ job — 스케줄 실행
워커·스크래퍼. 예: GCX Python 스크래퍼. cron 스케줄 · 시크릿 · 결과 저장소.
신뢰 경계로 나뉜 4평면

사용자 앱이 뚫려도 전사 SSH 키·DB master가 함께 털리지 않도록, 실행존과 control plane의 신뢰 경계를 분리합니다.

인터넷/사내망 → 엣지 → (호스팅 · 데이터 게이트웨이) → APM
🌐
① 엣지 (nginx)
host/path 라우팅 · TLS · rate limit · 위협탐지 연동
📦
② 호스팅 격리존
static/container/job 실행 · 빌드 샌드박스
🔑
③ 데이터 API 게이트웨이
앱별 키·스코프 · read-only 쿼리빌더 · 시크릿 금고
🧠
④ Control Plane = APM
SSH키·iptables·DB master (★ 인터넷 비노출)
계약은 매니페스트 한 장
spgapp.json에 런타임·포트·볼륨·시크릿·visibility만 선언. 코드는 자유.
시크릿 금고 → 자동 주입
콘솔 vault에 한 번 넣으면 배포마다 env·파일로 주입(SA 키는 600 파일로 마운트). 레포엔 비밀 0.
day-1 샌드박스
사용자 코드는 gVisor(runsc) 컨테이너 + 별도 계정에서만 실행 — SSH 키 보유 박스와 신뢰존 분리.
인증 & 접근 제어
토큰 인증 + (콘솔 로그인) SSO

관리·서빙은 토큰으로 인증하고, 콘솔에 사람이 로그인하는 문은 SSO로 둡니다(예정). 인증 백엔드는 SpigenAPM과 공유 — 같은 토큰이 콘솔에서도 통합니다.

🔑 토큰 인증 (구현됨)
관리 API는 Bearer JWT(role admin·owner), 서빙(설치/유저스크립트)은 서명 토큰(?t=). 평문 저장 없이 해시·HTTPS 전용, 팀 단위 폐기·회전.
🔓 콘솔 로그인 SSO (예정)
현재는 SpigenAPM 로그인 공유. 목표는 SpigenLM 위임 Google SSO(@spigen.com)를 배포 주체 로그인의 앞단 게이트로 — 아직 미구현(APM SSO 통합에 의존).
🧩 라우팅 vs 실행
nginx 엣지가 라우팅·TLS·WAF, 실제 앱 실행은 docker 컨테이너(격리존). static은 nginx가 직접 서빙, container는 nginx가 127.0.0.1:<port>로 프록시.
🗓️
인사지원실 · 자체 개발
회의실 예약 시스템

구글 워크스페이스(캘린더·챗·디렉터리)와 연동한 사내 회의실 예약 웹앱. 회의실별 구글 리소스 캘린더에 예약을 만들고 참석자를 초대하며, 회의 시작 시각에 구글 챗 DM으로 알립니다.

예약 → 캘린더 반영 → 시작 시 알림
🔐
Google 로그인
@spigen.com 계정만
🗓️
예약 생성
회의실 리소스 캘린더 이벤트 + 참석자 초대
🔄
실시간 반영
예약 변경 SSE 푸시
💬
시작 알림
구글 챗 DM (참석/불참 확인)
FastAPI + React(Vite)
가벼운 풀스택 구성. 백엔드 REST + 프론트 SPA, HTTPS 개발 서버.
구글 리소스 캘린더 연동
서비스 계정 도메인 위임으로 회의실 캘린더에 예약 생성/수정/취소 · 참석자 초대.
구글 챗 DM 알림
회의 시작 시각에 예약자에게 챗봇 DM. 스케줄러가 자동 발송.