← Sandbox

🏛️ 지부 보고 시스템 독립 배포

서울지역본부 산하 38개 지부 간부가 보고를 올리면 본부장이 열람하고 지시사항을 다는 모바일 반응형 업무 시스템. 보고에서 출발해 업무·대장·조직점검·지부포털·자료실·회의자료 RAG·구글 캘린더까지 붙었고, app.py 한 파일이 7,293줄 · 라우트 163개인 현재 가장 큰 앱이다.

접근

내부망
http://192.168.0.10:5065
로그인
3종 — 관리자 admin / 본부사무처 개인계정(staff) / 지부(branch). 비밀번호는 소스가 아니라 .env·DB에 둔다
첫 화면
본부는 /dashboard, 지부는 /portal — 역할이 착지점을 가른다

기능 지도

권한 — 신원은 세션만 믿는다

CSS가 두 갈래인 이유

회의자료 RAG · Gemini

입력
NAS /mnt/nas/temp를 컨테이너에 읽기전용으로 물려 HWP·HWPX·PDF를 스캔하고, 본문과 첨부를 pair_key로 짝짓는다
파싱 사다리
Upstage Document Parse → 품질검증(0.55 이상 통과·0.35 이상 부분) → 로컬 파서 폴백. 키가 없으면 화면에 「로컬 폴백만 사용」이라고 알린다
구조화
Gemini로 회의 스키마(Pydantic) JSON을 만든 뒤 청크로 나눠 SQLite 레지스트리 + Chroma(/data/chroma)에 넣는다
임베딩
gemini-embedding-001 고정 — text-embedding-004는 404가 나 검색이 0건이 됐다. 모델을 바꾸면 기존 문서는 벡터가 비므로 강제 재색인이 필요하다
답변
질의 의도(회의차수 등)로 좁힌 뒤 검색·주입해 답하고 citation을 함께 돌려준다. 세션·이력은 DB에 남는다
쿼터
같은 Gemini 키를 다른 프로젝트와 공유하면 배치 색인 중 429가 난다 — MEETING_BATCH_DELAY(기본 2.5초)로 간격을 벌린다
구글 캘린더
서비스 계정으로 REST v3를 직접 호출한다. google-auth가 이미 깔려 있어 의존성 추가도 이미지 리빌드도 없었다. 키 파일은 data/secrets/에 두고 업로드 UI는 만들지 않았다 — 시크릿을 HTTP로 왕복시키지 않는다. 구글이 죽어도 업무 마감·교섭 일정은 보이도록 실패는 warnings[]로 삼킨다

배포·운영

스택
Python 3.11 · Flask 3.0.3 · SQLite · Gunicorn 23.0.0 · Jinja2 + Vanilla JS · openpyxl · python-docx · langchain/chromadb
배포
Docker Compose 독립 컨테이너 union-report (5065:5000). gunicorn은 --workers 1 --timeout 300 --reload — SQLite 경쟁조건을 피하려 워커를 1개로 묶었다
이미지
LibreOffice + 한글 폰트. rhwp가 폰트를 이름이 정확히 맞아야 렌더링해서 apt에 없는 Noto Sans KR을 빌드 때 따로 내려받는다
마운트
/app(코드 전체) · /data(DB·업로드·chroma) · NAS temp(ro) · INSPINIA dist(ro) · 공용 config.py(ro)
반영
Python 코드는 --reload로 자동. DB 스키마 변경은 재시작(init_db() 재실행), requirements.txt는 반드시 리빌드 — entrypoint가 의존성이 있으면 pip install을 건너뛴다
함정
/app이 통째로 바인드마운트라 이미지에 COPY된 코드는 런타임에 안 쓰인다. 「리빌드했는데 그대로」·「재시작했는데 라이브러리가 없다」가 전부 여기서 나온다
데이터
SQLite /data/union_report.db(테이블 44개, 비공개). init_db()CREATE TABLE IF NOT EXISTS+ALTER TABLE로 매 기동 때 스키마를 맞춘다
소스
/opt/docker/apps/union-report(자체 git 저장소, 운영 브랜치 boxy-redesign) · 문서 PROJECT_STATUS.md·docs/ 9건

결정 로그에서

※ sandbox 허브와 별개로 배포되는 독립 앱입니다. 이 페이지는 명세만 표시하며, 실제 보고 작성·열람은 위 주소에서 이뤄집니다. 계정·토큰·서비스 계정 키는 .envdata/secrets/에만 두고 코드·문서·이 카드에 적지 않습니다.