PROJECT DOCUMENTATION

5. 시나리오 테스트

로컬·첫 배포 실행 결과기준일 2026-09-19담당 김충식 · 류준(기능별 구현)

정상 동작, 예외 처리, AI 결과와 응답 시간을 어떤 방법으로 확인했고 무엇이 남았는지 기록합니다.

테스트 범위와 개발 아키텍처

단계 도구 대상
백엔드 단위·API·DB 통합 pytest 도메인 규칙, 라우터 계약, 게이트웨이, 수집·적재(테스트 전용 DB)
프론트엔드 단위·컴포넌트 Vitest · Testing Library, tsc 타입 검사 화면 컴포넌트, 상태·계산 보조 함수, mock API 픽스처
사용자 시나리오(E2E) Playwright headless 스크립트 frontend/tests/*.cjs 깔때기 전체 흐름, AI 리포트, 첫 화면 반응형
실서버 스모크 실행 중인 백엔드에 직접 요청 의도 해석, 금리, 입력 오류, AI 리포트 실호출

대상 구조는 상위 설계를 따릅니다. 9월 19일 밤까지의 로컬 자동 테스트와 운영 주소 검증을 함께 기록합니다. 운영 페르소나 검증 이후의 개선 재검증은 로컬 프론트와 운영과 같은 백엔드에서 수행했습니다. 부하·동시 요청 테스트는 아직 하지 않았습니다.

사전 준비사항

  • Docker로 데이터 스토어 실행(PostgreSQL·Redis·Neo4j)
  • 백엔드: pytest가 테스트 전용 DB(localhostdaegu_test)를 자동으로 만들고 마이그레이션·마스터 시드를 실행합니다. DB 이름이 _test로 끝나지 않으면 중단해 개발 DB를 보호합니다.
  • 실데이터 E2E·스모크: 공공데이터를 적재한 개발 DB, 실행 중인 백엔드(8300)·프론트엔드(3300), AI 리포트는 Gemini 키가 필요합니다.
  • E2E는 브라우저 창을 띄우지 않는 headless로 실행하고, 실행 중인 서버를 재사용하는 옵션(E2E_REUSE_SERVER=1, E2E_API_BASE)을 씁니다.

재현 제한: 일부 백엔드 테스트는 저장소에 올리지 않은 원본 데이터 파일(data/raw)이 있어야 통과합니다. 새로 받은 저장소나 CI에서는 그대로 재현할 수 없습니다.

실행 결과 요약

구분 결과 실행일 조건
백엔드 pytest 603 passed · 1 skipped 9/19 밤 최종 실행 지표 11업종·스냅샷 규칙·정직성 표기 후 원본 로그
프론트엔드 Vitest 226 통과 / 46 files, 타입 검사 통과 9/19 밤 빌드는 첫 배포 전 203개 테스트 시점 통과. 밤 변경 전체 빌드는 별도 확인
깔때기 E2E funnel.cjs PASS 9/18 사전상담·후속 작업 실백엔드로 최초 계산 → 재계산 → 최초안 재선택 → 상담자료 → 공식 링크. 분석 URL year=2025 확인
AI 리포트 E2E analysis.cjs PASS 9/18 후속 작업 실백엔드 전 구간 통과. 13.4초·제목 5개는 오전 review 검증값이며 최신 실행 시간은 별도 기록 없음
첫 화면 E2E home-design.cjs PASS 9/17 1440·1024·390·320px × 라이트·다크, 가로 스크롤 없음·키보드 제출
운영 페르소나 10건 10/10 상담자료 도달 9/19 운영 주소, 1인 평균 30.6초·자료 생성 평균 11.2초(자동 입력)
개선 후 페르소나 재검증 10/10 · 마찰 기록 0건 9/19 로컬 프론트 + 운영과 같은 백엔드. 수정 18건 반영
실서버 스모크 통과 9/19 Cloudflare 뒤 SSE 순차 도착·CORS·운영 4개 경로 200

프론트엔드에 ESLint 설정 파일이 없어 lint는 실행하지 않았습니다.

수치의 근거: jekyll.md의 9월 19일 밤 마무리·제안서 정정 기록을 기준으로 603/226을 표시합니다. 아래 개별 TC에는 이전 실행 시점을 보존했습니다. 서비스 작업 로그를 옮긴 결과이며 이번 문서 수정 중 전체 서비스 테스트를 재실행한 결과가 아닙니다.

단위 테스트 — 하나의 처리 규칙

9월 18일 작업 로그의 전체 테스트와 후속 검증 중 요구사항에 직접 연결되는 대표 항목입니다.

번호 대상 확인 내용 테스트 파일
UT-001 재무 엔진 초기 투자비·고정비, 손익분기 매출, 3개 시나리오와 회수 기간, 부족 자금·버틸 수 있는 기간, 금리 스트레스 test_finance_engine.py
UT-002 의도 해석 “달서구에서 카페”가 서구가 아니라 달서구(27290)로, “동성로 2층 카페 5천만원”의 예산이 5천만 원으로 인식 test_intent_parser.py
UT-003 위험도 가중치 합, 등급 구간(40·70점), 구성 요소 보고, 동순위·단일 표본 백분위 test_metric_risk.py
UT-004 레거시 금융상품 매칭 /matching의 보증 → 은행 → 정책 순서, 한도·업종·업력 필터, 나이 미입력 시 비제외, 구·군 한정 상품 제외, 운영 JSON의 업종 id test_matching.py
UT-005 키 노출 방지 가짜 키로 외부 API 오류를 흉내 냈을 때 오류 메시지에 키가 남지 않음, 연결 오류 재시도 test_gateway_key_redaction.py
UT-006 AI 리포트 조립 이벤트 순서, 에이전트 실패·AI 실패에도 완료 이벤트까지 진행, 섹션 대체 문구, 요청 1회 소비 test_analysis_interactor.py, test_analysis_sections.py
UT-007 BC 경계 matching이 다른 BC의 어댑터를 직접 import하지 않고 도메인은 다른 BC를 알지 못함 test_matching_bc_boundary.py
UT-008 스키마 고립 감시 고립 테이블 예외 2건의 추가·해소 감지, ORM 파일 직접 등록 test_schema_isolation.py

후속 검증에는 자금 구성 필드, handoff 필수 입력, 서버 재계산 비교표, 상담 후보·지역 필터, 미입력 구분과 캐시 프록시 연도 전달도 포함됩니다. 모델 어댑터·평가 하네스 테스트와 측정 조건은 모델 평가에 별도로 기록했습니다.

통합 테스트 — 모듈 연결과 외부 의존성

번호 연결 경계 준비·입력 결과 상태
IT-001 프론트엔드 → 실백엔드 전체 흐름 mock 대신 실제 API 주소 질문 → 지도 → 사전상담 → 최초 계산 → 수정·재계산 → 최초안 재선택 → 상담자료 → 공식 링크 통과(9/18)
IT-002 수집기 → 외부 API → DB 실제 키로 전량 수집 인허가 161,115건(8개 구·군 모두 > 0, 좌표 보유분 대구 범위 내 100%), 경계 142/144, 지표 7,856행 통과(9/16)
IT-003 분석 → 검색 → Gemini → SSE 대신동·카페 실호출 완료 이벤트까지 도달, 오류 상태 0, 대체 문구 0 통과(9/17)
IT-004 배포 프록시 → SSE 운영 도메인·Cloudflare Tunnel 첫 이벤트 0.2초, 첫 report_delta 1.4초, 12초대까지 순차 도착 통과(9/19 첫 배포)
IT-005 상담 화면 → 서버 기록 상담자료 생성·계획 재전송·GET 왕복 세션 1행·계획 2행, 같은 종류 재전송 시 행 증가 없음, 선택안·변경 이유 복원. 합성 데이터는 확인 후 삭제 통과(9/18 T7)

TC-001 · 한 문장에서 상담자료까지

항목 기록
요구사항 REQ-002, REQ-003
사전 조건 실행 중인 프론트엔드·실백엔드, 적재된 개발 DB
절차 첫 입력 → 지도에서 대신동 선택 → 사전상담 → 최초 계산 → 조건 수정 → 재계산 → 최초안 재선택 → 상담자료 → 공식 안내 링크
기대 결과 계산안이 구분되고 미제출 수정 중에는 선택이 잠김. 선택한 계획으로 자료가 생성되며 부족액 0원을 자기자본 충분으로 단정하지 않음
실제 결과 PASS(9/18), 실백엔드 8300. 미제출 수정 경고와 “자기자본으로 충분” 문구 부재 확인. 후속 E2E에서 분석 URL year=2025 확인
한계 9/19 운영 페르소나 10건은 상담자료까지 도달했습니다. 은행에 실제 자료를 전송하는 기능은 없습니다. 9/17의 기본값·결론 헤드라인 검증은 사전상담 전환 전 기록입니다.

TC-002 · 자금 계산과 금융상품 매칭

항목 기록
요구사항 REQ-002
사전 조건 상품 12건과 상담 메타데이터를 개발 DB에 시드한 실백엔드
절차 자금 구성 검산, 상담 후보의 근거·자격·지역 조건, 기존 /matching 응답 계약, 입력 오류·최신 금리 확인
기대 결과 조달 필요액과 희망대출 후 부족액을 구분. 한도가 작은 상담 후보도 유지하며 지역·자격 조건을 적용. 기존 매칭에서는 지역 한정 상품 제외
실제 결과 자기자본 4,000만·희망대출 2,500만 사례: 조달 필요 2,260만·부족액 0원. 지역 매칭 실측 중구 10건·달성군 11건·북구 11건(은행 후보와 차선 후보를 포함한 결과). 잘못된 입력 422, 최신 중소기업 대출금리 4.22%(9/18)
예외 원가율 + 수수료율 ≥ 1 → 422(과거 500이던 결함 수정)
남은 확인 재단 4건 취급은행, youth-1의 2026년 재공고. 계산 가정·미입력 표시와 금리 null 문구는 반영됨

TC-003 · AI 리포트

항목 기록
요구사항 REQ-003
사전 조건 실백엔드, Gemini 키, 검색 색인
절차 대신동·카페로 분석 시작 → SSE 수신 → 섹션·참고 자료 확인
기대 결과 섹션이 순서대로 오고 완료 이벤트로 끝남. 코드가 만든 수치와 AI 해석이 섞이지 않음. 오류·대체 문구 없음
실제 결과 9/17 1차: 이벤트 52건·10.4초·인용 10건·매칭 10건. 리뷰 수정 후 2차: 56건·12.3초·매칭 9건·본문 번호 인용 0·”서울” 언급 0. 9/18 E2E PASS(13.4초, 섹션 제목 5개·참고 자료)
예외 질문 501자 → 422(9/17 실서버). 없는 ID·이미 소비한 ID → 404(테스트)
후속 검증 handoff 섹션 분리·서버 재계산 비교표·재무 미입력 시 계산/매칭 생략, 선택 연도 전달과 캐시 프록시 누락 수정. 실백엔드 E2E 재통과
한계 모델 평가에서 검색 80건·LLM 후보당 28건을 측정했지만, 평가셋은 미검수이고 문장의 설득력·정확한 해석은 아직 평가하지 않았습니다. 9/19 다른 구·군 전용 문서를 제외하는 필터를 추가했습니다. 기간 필터는 없습니다.

TC-004 · 공통 예외 처리

상황 기대 동작 상태
필수 입력 누락·길이 초과 422로 안내하고 처리를 시작하지 않음 통과(테스트·실서버)
잘못된 재무 입력 422 통과(9/18 실서버)
없는·이미 소비한 분석 요청 404 ANALYSIS_NOT_FOUND 통과(테스트)
AI 호출 실패 섹션은 대체 문구, 스트림은 완료 이벤트까지 진행 통과(테스트)
외부 수집 API 오류 소스별로 격리하고 재시도, 실패는 종료 코드로 기록. 오류 메시지에 키가 남지 않음 통과(테스트). 뉴스 수집은 모든 키워드가 실패해도 정상 종료로 기록되는 문제가 남음
데이터 없는 지역·기간 없다고 표시하고 결론을 제한 9/19 데이터 없음 안내·확인된 사실 배지 제거·빈 지표 해석 생략 반영. 모든 지역·기간 조합은 미검증
같은 분석 요청 반복 조회 첫 조회만 스트림, 이후 404 통과(테스트)
handoff에 재무·상담 입력 누락 422 통과(사전상담 테스트)
자료 생성 중·review 결과의 상담자료 내보내기 완성된 handoff만 허용 차단 구현·프론트 검증 기록
상담 서버 기록 실패 자료 생성·이미 끝난 다운로드 유지 실패를 삼키도록 구현. 배포 장애 상황은 미검증

TC-005 · 상담 상태와 서버 기록

항목 기록
요구사항 REQ-002
확인 범위 최초안 고정·현재안 갱신·선택 잠금, 지역/업종 변경 시 무효화, 미입력 금액과 유효한 0원 구분
서버 계약 세션 생성·조회·전체 교체, 같은 plan_kind의 계획 갱신, 가정·확인 질문 노트 교체, 선택 계획안과 문서 해시 기록
기록된 결과 T7 세션·계획 왕복과 멱등 확인. 후속 노트·세션 갱신·문서 저장 구현 후 백엔드 472/1 skipped·프론트 203/40 files, 타입 검사·빌드 및 실백엔드 E2E 통과
제한 화면 정본은 sessionStorage이고 서버 기록은 감사·재현용입니다. 자동 복구·로그인·은행 전송·블록체인 검증은 구현 범위에 없습니다.

성능 측정 계획

TPS는 API 요청 처리량(req/s), 거래 처리량(tx/s), 모델 토큰 생성 속도(token/s)를 구분합니다. 블록체인 거래가 없으므로 거래 처리량은 해당 없음입니다. 아래는 단건 실측이며 목표값은 아직 정하지 않았습니다.

측정 구간 지표 조건 결과
AI 리포트 전체 스트림 소요 시간 로컬, 실 Gemini, 대신동·카페 1건 10.4초(9/17 1차) · 12.3초(2차) · 13.4초(9/18 E2E)
인허가 전량 수집 소요 시간 7업종 × 8개 구·군 약 18분, 161,115건(9/16)
검색 색인 증분 소요 시간 뉴스 1,595건, 유료 키 69.3초(9/17)
전체 요청 처리량·p50/p95 응답시간·실패율 동시 사용자·지속 시간 미측정
로컬 LLM 추론 토큰 생성 속도 후보당 28프롬프트, Ollama eval gemma4 48 · kanana 81 · exaone 85 token/s(9/18). 서비스 전체 처리량과는 별도
모델별 생성 첫 조각·총 시간 p50 같은 컨텍스트·프롬프트 Gemini 1.68/2.12초, gemma4 0.46/2.95초. 전체 리포트가 아닌 개별 프롬프트 기준

p95 응답시간은 요청 100건 중 약 95건이 그 시간 안에 끝났다는 뜻입니다. 목표값은 측정 전에 합의하고, 실측값과 구분합니다.

결과 기록 형식

테스트 ID / 실행일 / 코드 버전 / 데이터 / 환경 / 설정 / 절차 / 기대 결과 / 실제 결과 / 판정 / 로그 / 결함 / 재검증 결과를 기록합니다. 실행 원문과 스모크 출력은 서비스 저장소의 개발 기록과 작업 폴더에 남기고, 이 페이지에는 판정과 핵심 수치만 옮깁니다.

배포 후 같은 시나리오를 배포 주소에서 다시 실행한 결과는 최종 검수에 남깁니다.


맨 위로

053 · DAEGU · 2026