PROJECT DOCUMENTATION
3. 상위 설계서
실제로 구현한 모듈과 데이터 흐름, AI와 외부 서비스의 연결, 첫 배포와 남은 작업을 정리합니다.
개발 개요
9월 19일 밤 작업 로그의 첫 배포·데이터 배선·11업종 지표까지 반영한 구조입니다. 이전 자작 서비스 Metabole(서울 상권)을 대구 기준으로 바꿨고(DEC-006), 한 문장 질문 → 지도 선택 → 자금 계산·비교·선택 → 상담자료 → 공식 안내 흐름을 실백엔드로 완주했습니다. 9월 19일 첫 배포와 운영 페르소나 10건 검증을 마쳤습니다. 최신 프론트 변경 재배포는 남아 있습니다.
모듈 중심 Data Flow
2026-09-20 서비스 설계서·ORM·provider 설정·프론트 흐름 대조 기준. 2026-09-19 첫 배포 기록과 로컬 개발 구성을 구분했습니다. 색상별 박스는 기능 묶음으로 개별 모듈 수와 다르며, 화살표는 사용자 동선·요청·조회·적재 방향입니다.
- 사용자가 채팅 첫 화면에 한 문장을 입력하면 백엔드가 구·동·랜드마크, 업종, 예산을 추출합니다.
- 지도 화면이 해당 행정동을 보여 주고, 행정동 × 업종 지표와 위험도를 조회합니다.
- 비용·자기자본·예상 매출로 총 준비자금·조달 필요액·희망대출 반영 후 부족액을 계산하고, 최초안과 현재안을 비교·선택합니다. 상담 후보는 iM뱅크 연결 근거와 자격·자치구 조건으로 고릅니다.
- 상담자료 요청 시 입력을 서버 엔진으로 다시 계산하고 계획·비교·계산표·정책자금·확인 질문·상권 섹션을 SSE로 전달합니다. 수치·비교표·미확인 항목은 코드가 정하고 Gemini가 설명·질문을 씁니다. 선택 연도는 지표와 위험도까지 전달합니다.
- 화면 초안은 sessionStorage에 보관하고, 상담자료 생성 시 서버에 세션·계획·노트를 기록합니다. 재생성은 같은 세션을 갱신하며 완성된 자료 다운로드 시 선택안과 sha256 해시를 기록합니다. 공식 안내 이동은 은행에 자료를 전송하지 않습니다.
- 정기 수집 작업이 공공 데이터를 매일·매시 적재하고, 지표 재계산과 검색 색인을 갱신합니다.
모듈과 필수 조건
백엔드는 헥사고날 구조(도메인 · 유스케이스·포트 · 어댑터 · 조립)이며, 기능마다 bounded context를 둡니다.
| 기능 묶음 | 백엔드 모듈 | 프론트엔드 | 입력 → 출력 | 필수 조건 |
|---|---|---|---|---|
| 입력 해석 | intent |
intent-gate(채팅 첫 화면) |
한 문장 → 구·동 코드, 업종, 예산 | 긴 지명을 먼저 비교(“달서구”를 “서구”로 오인하지 않음), 단위가 붙은 금액 합산 |
| 상권 진단 | master(구·동·업종·경계), store(인허가), metric(지표·위험도) |
map-explorer(지도·사이드 패널·위험도 카드) |
행정동·업종·연도 → 점포 수·폐업률·점포 증감률, 위험도 | 기본 연도는 마지막 완결 연도. 위험도는 상대 순위이며 실패 확률로 표시하지 않음 |
| 자금 계산·매칭 | finance(재무 엔진), matching(후보), product(상품 DB), shock(금리) |
simulator(계산안 비교·선택·후보 카드) |
비용·자금·지역 → 자금 구성·시나리오·상담 후보 | 계산은 코드. 재무 미입력 시 계산·매칭 생략. matching은 product 입력 포트 사용 |
| 상담 기록 | consultation |
상담 초안·자료 내보내기 | 세션·계획·가정·확인 질문·문서 해시 | 화면 정본은 sessionStorage, 서버 기록은 감사·재현용. 저장 실패가 자료 생성을 막지 않음 |
| 외부 데이터 | dataset·indicator |
지도 패널 동네 특성·도시철도 승차 | 공공데이터 5종 → 행정동 지표 | 9/19 적재·화면 연결 완료. 센터 민간 데이터는 미확보 |
| AI 리포트 | analysis(목적별 구성·SSE), rag(검색), news·funding(근거 문서) |
agent-report(진행·자료 뷰) |
지역·연도·재무·상담 입력 → review 또는 handoff | 수치·비교표는 코드, 설명·질문은 AI. handoff에 재무·상담 입력 필수 |
| 수집 | store·funding·news·rent·shock·rag 수집기, scripts/*.sh |
— | 외부 API → DB·색인 | 소스별 오류 격리, 가장 나쁜 종료 코드 기록, 중복 실행 방지 |
편의점 상가정보 2,019건과 담배소매업 33,804건을 적재했습니다. 지표 원천은 인허가·담배소매인·어린이집 Strategy로 합성하며 등록 11업종을 연결합니다. 편의점은 담배소매인 대용, 학원·부동산·어린이집 폐업은 스냅샷 소실 추정으로 표시합니다.
AI 모델 학습·추론 흐름
학습·평가 준비 — 자체 학습 없음
모델을 직접 학습하거나 미세 조정하지 않습니다. 기본 경로는 외부 모델 API(Google Gemini)이고, 외부 API가 끊겼을 때를 위해 로컬 모델(Ollama) 경로를 같은 포트 뒤에 어댑터로 두었습니다.
| 용도 | 온라인(기본) | 오프라인(대체, 평가 완료·전환 전) | 비고 |
|---|---|---|---|
| 리포트 해석 문단 | gemini-3.8-flash |
gemma4:12b (환경변수 REPORT_WRITER_PROVIDER=ollama) |
팀 결정 “최신 정식 Flash 모델”(DEC-009). 로컬 대체는 DEC-022 |
| 검색 색인·질의 임베딩 | gemini-embedding-001(2560차원) |
qwen3-embedding:4b(2560차원) |
색인과 질의는 같은 임베더만 짝지어 사용. 9/19 halfvec(2560) 마이그레이션·Gemini 재색인·provider 설정화 완료. 로컬 전환 시 해당 임베더로 다시 재색인 |
9월 18일에 온라인·오프라인 후보를 같은 코퍼스(3,448건)·질문(80건)·프롬프트로 나란히 평가했습니다. 임베딩은 qwen@2560이 Top-1 0.762로 Gemini(0.700~0.738)와 동급 이상이었고, 리포트 생성은 gemma4:12b가 Gemini와 같은 게이트 전부 통과(1.000)를 냈습니다. 두 경로가 고르는 근거 문서는 절반가량 다릅니다. 상세는 모델 평가에 있습니다. 평가셋 80건은 자동 생성한 미검수 상태이며, 문장의 설득력·해석 정확도는 아직 재지 않았습니다.
서비스 추론 — 구현
분석 요청 저장(한 번만 쓰는 ID) → 에이전트가 차례로 자료 수집: 상권(지표·위험도) → 관련 뉴스 검색(pgvector) → 자금(재무 입력이 있으면 재무 계산, 금융상품 매칭, 정책 공고 검색) → 섹션마다 코드가 제목·점수·표를 먼저 전송 → Gemini가 해석 문단을 스트림 → 참고 자료와 함께 완료 이벤트 전송.
-
에이전트 하나가 실패해도 오류 상태만 알리고 나머지를 계속 진행하며, 스트림은 항상 완료 이벤트로 끝납니다.
- 사용자 질문과 검색 문서는 태그로 감싸고, 그 안의 지시는 따르지 않도록 시스템 지시에 명시했습니다.
- 임베딩 호출은 호출 한도(429)·일시적 5xx 오류에 재시도합니다. 해석 문단 생성이 실패한 섹션은 대체 문구로 채웁니다.
- 분석 요청 저장소가 메모리에 있어 백엔드는 워커 1개로 실행해야 합니다. 워커를 늘리려면 Redis 같은 공유 저장소 어댑터가 필요합니다.
개발 환경과 기술 요소
| 구분 | 사용 중인 기술 | 비고 |
|---|---|---|
| 문서 사이트 | Jekyll + Just the Docs, GitHub Pages | 서비스 저장소 개발 기록을 수동으로 반영 |
| 서비스 프론트엔드 | Next.js 16 · React 19 · Tailwind CSS 4 · TanStack Query · MapLibre GL | 포트 3300. 백엔드 계약을 흉내 낸 mock API 라우트 포함 |
| 서비스 백엔드 | Python 3.14 · FastAPI · SQLAlchemy 2 · Alembic · Pydantic Settings · google-genai | 포트 8300. 헥사고날 구조 |
| 데이터 저장소 | PostgreSQL 17 + pgvector(Docker) | 원천·지표·검색 색인 모두 저장 |
| 구성만 된 저장소 | Redis 7 · Neo4j 5(Docker) | 현재 코드에서 사용하지 않음. Neo4j를 쓸지 구성에서 뺄지는 여력 시 결정 |
| AI | Gemini API(생성·임베딩) · Ollama(로컬 대체 경로, 전환 전) | 키는 환경변수로 주입. 작성기·임베더는 provider 레지스트리로 교체 |
| 테스트 | pytest · Vitest · Testing Library · Playwright(headless) | 시나리오 테스트 참고 |
| 정기 실행 | 서버 crontab + 셸 스크립트 | 뉴스 매시, 인허가·공고·색인 매일, 금리·임대료 주 1회 |
| 인프라 | 로컬 개발 머신 | 프론트엔드 Vercel · 백엔드 Cloudflare Tunnel · DB 로컬 Docker로 확정, 9/19 첫 배포 완료(아래 배포 구조 참고) |
데이터 스토어 포트는 모두 127.0.0.1에만 열어 두었습니다(PostgreSQL 5437, Redis 6381, Neo4j 7476·7689).
외부 연동
| 연동 | 목적 | 현재 상태 | 남은 확인 |
|---|---|---|---|
| 공공데이터포털 인허가 7업종 | 개폐업 지표·위험도 | 연동·정기 수집 | 카페(휴게음식점) 단기 개폐업의 분류 근거 |
| 브이월드 | 행정동 경계, 지도 배경 | 연동(경계 142/144) | — |
| 한국부동산원 R-ONE · 한국은행 ECOS | 임대료·공실률 · 금리 | 연동·주 1회 수집. 금리는 기본값, 임대료는 상권·평수 선택 도우미에 사용 | 행정동 자동 매핑 없음 |
| 기업마당 · 온통청년 | 지원사업·청년 창업 정책(리포트 근거) | 연동·매일 수집 | 다른 구·군 전용 문서 제외 반영, 기간 필터 없음 |
| 구글 뉴스 RSS | 상권 뉴스(리포트 근거) | 연동·매시 수집 | 모든 키워드가 실패해도 정상 종료로 기록되는 문제 |
| Gemini API | 리포트 해석·임베딩 | 연동(유료 키) | 운영 키 주입·SSE 확인. 로컬 대체 배선 완료, 전환은 수동이며 자동 폴백 없음 |
| 금융상품 | 상담 후보 매칭 | 은행 API 연동 없음. 공개 자료 12건을 JSON에서 DB로 시드. 9/18 원문 대조 완료, 9/18 direct 2·linked 3·unverified 7 → 9/19 direct 2·linked 7·unverified 3(재단 보증 4건 승격, 제도 구조에 대한 팀 확인 근거) | 재단 4건 실제 취급은행·youth-1의 2026년 재공고 확인 |
| DIP 빅데이터활용센터 | 카드 소비·생활인구 | 미확보 | 이용·반출·공개 조건(OPEN-004) |
| 블록체인(리포트 해시 기록) | 리포트 진위·시점 증명 | 범위 제외(DEC-018). 상담 자료의 sha256 해시만 서버에 기록 | — |
배포 구조 — 9월 19일 첫 배포 완료
배포 주소는 localhostdaegu.cloud이며 9월 19일 첫 배포했습니다. 프론트엔드는 Vercel, 백엔드는 로컬 GPU 머신에 Cloudflare Tunnel, DB는 로컬 Docker로 정했습니다(DEC-020). 절차는 서비스 저장소 docs/deploy-vercel-cloudflare.md에 있습니다. 네임서버 Cloudflare 이전과 TLS·CORS 확인을 마쳤습니다. Vercel Git 연동이 푸시마다 자동 배포하며, 9/19 밤 기록에서 프론트 최신 변경 5개 커밋은 미푸시였습니다.
| 결정·확인 항목 | 현재 코드에서 확인한 조건 |
|---|---|
| AI 키 | 백엔드에 Gemini 키가 없으면 분석 시작 요청이 500. 리포트 모델은 환경변수로 바꿀 수 있고 코드 기본값은 gemini-3.8-flash |
| CORS | 로컬 출처는 항상 허용하고 CORS_ALLOW_ORIGINS(쉼표 구분)로 운영 도메인을 추가(9/18 반영) |
| 워커 수 | 분석 요청 저장소가 메모리라 워커 1개 |
| 프록시 | Cloudflare 뒤 첫 이벤트 0.2초·첫 report_delta 1.4초·12초대까지 순차 도착 확인 |
| 정기 수집 | crontab 수집 가동·9/19 온통청년 키 교체 확인. 추가 수집기 환경변수 배포 설정은 남음 |
요구사항별 구현 목표와 시나리오
REQ-002는 자금 구성·계산안 비교·지역별 상담 후보·자료 저장을, REQ-003은 선택 연도 전달과 목적별 리포트 구성을 확인합니다. 테스트 시나리오에 정상·예외 경로를 연결합니다. 기간 일치(①), AI 진행 안내(②), 자금 점검 동선·가정 표시(③), 데이터 신뢰 표시(④)는 9/19까지 반영 완료했습니다. 코드 프리즈는 해제했습니다.