fingu-tips-rnd-evaluation — 코드 전수 분석

2026-05-19 작성 · 레포 FINGU-GRINDA/fingu-tips-rnd-evaluation · 브랜치 alpha @ f531aa5 · 데이터: 4 병렬 에이전트 깊이 분석

TL;DR

KSEL 7-KPI 평가용 풀스택 모놀리식 PoC. FastAPI 백엔드 + React 19 SPA + nginx 정적 + Claude Agent SDK 통합. 단일 EC2 (t4g.xlarge AL2023) · alpha push → GitHub Actions → rsync → Infisical export → rolling restart → smoke (deploy_id 일치 검증). 3-tier requirements (vercel stub / EC2 real / dev) 로 250MB Vercel 제약과 ~7GB HF 모델 풀파이프라인을 같은 코드베이스에서 처리. 7개 KPI 각각의 모델 어댑터 · stub fallback · 측정 결과 ndjson · 단위/통합 테스트가 갖춰져 있어 KSEL 검토자가 시연·검증·증빙을 한 화면에서 끝낼 수 있는 구조.

총 코드~ 1.7 MB 백엔드 Pythonsrc 48 + api 9 프론트엔드React 19 + Vite 6 + TS 5.6 테스트pytest 31 files · 3,289 LOC 데이터셋23 files · 10 MB · 15,050 sample KPI7개 (목표 71.07~99 사이) API 라우트30+ Agent 도구8

1. 레포 개요

1.1 디렉터리 분포

경로파일용량역할
src/48404 KB도메인 · KPI 구현 · 모델 어댑터 · 메트릭 · Agent
api/992 KBFastAPI 진입점 · chat · agent · ksel 라우터
frontend/55524 KBReact 19 SPA · 4 페이지 · 측정 패널
deploy/520 KBCaddyfile · setup-ec2.sh · 대체 compose
scripts/1496 KBbuild_datasets/ · deploy.sh · export csv
tests/31172 KBpytest 단위/통합 · KPI contract · 메트릭별
datasets/2310 MBKPI 평가 데이터셋 (jsonl + csv 쌍)
evidence/5252 KBKSEL 시험의뢰서 · 기술 PDF
public/162.8 MB정적 자산
notebooks/1*4 KB실제로는 비어있음 — KSEL 녹화용 예정

1.2 운영 토폴로지 (한 줄)

Cloudflare (orange-cloud, WAF/CDN) → EC2 t4g.xlarge AL2023
  ├─ nginx (80/443, origin TLS) → /api/* proxy → fingu-tips-api:8001
  ├─ fingu-tips-web (nginx + SPA build, 128 MB)
  └─ fingu-tips-api (Python 3.12 + FastAPI + Uvicorn, 6 GB limit)
     └─ HF cache volume + Infisical-pulled .env

1.3 분기 / 운영 환경

2. 백엔드 (Python · FastAPI)

2.1 진입점 & 부트스트랩

FastAPI app
src/api.py:235FastAPI(title="TIPS R&D KPI Evaluation API", version="0.6.0")
Vercel 진입
api/index.py — Vercel builder 가 app 심볼 인식
로컬 실행
uvicorn src.api:app --host 0.0.0.0 --port 8000
환경 정규화
import 시점에 ENABLE_REAL_PIPELINE, ENABLE_API_PIPELINE, ENABLE_FINETUNED_PIPELINE 정규화 (src/api.py:53~72)
전역 시드
SEED=20260514 — KPI별 KPI{n}_STUB_SEED 로 분기. 모든 stub 측정 재현 가능
미들웨어
x-request-id 자동 주입 · CORS (PUBLIC_ORIGIN + localhost) · 구조화 로깅 ContextVar

2.2 7 개 KPI 구현 — 모듈 / 데이터셋 / 메트릭 / 합격선

KPI모듈데이터셋어댑터메트릭합격선
① 재무 F1src/kpi/kpi1_finance_qa.pykpi1_financial_qa.jsonl 1,050pipelines/agents.py:classify_scenario() — 16개 시나리오metrics/f1_score.py macro71.07
② 텍스트 분류src/kpi/kpi2_text_classification.pykpi2_text_classification.jsonl 1,000pipelines/thread_titles.py:classify_intent()metrics/accuracy.py99.0 %
③ BLEU (FT)src/kpi/kpi3_translation.pykpi3_finetune_qa.jsonl 500pipelines/finetune_inference.py:generate() — vLLM + Qwen-ORPO · stub fallbackmetrics/bleu.py char-level78.0
④ 처리속도src/kpi/kpi4_throughput.pykpi4_throughput_payloads.jsonl 10,000 (라벨 무)pipelines/data_augmentation.py:augment_record()metrics/throughput.py — 1분×5회 · SHA-256 무결성500/min + 99.9 %
⑤ 개인화 추천src/kpi/kpi5_personalized_recommendation.pykpi5_personalized_recommendation.jsonl 500pipelines/recommendations.py:score_personalization() — 4 단계 Rec-Promptmetrics/llm_rec_score.py0.31
⑥ NQ 검색src/kpi/kpi6_finance_search.pykpi6_nq_finance.jsonl 1,000pipelines/search.py:search_top_k() — Pinecone/Faiss + sentence-transformers · BM25 fallbackmetrics/nq_em.py Recall@5/1064.06
⑦ 상품추천 F1src/kpi/kpi7_product_recommendation.pykpi7_product_recommendation.jsonl 1,000 + 카탈로그pipelines/recommendations.py:recommend_top_k()per-user F1@1086.0

2.3 AI 모델 어댑터 레이어 (src/ai_clients/)

클라이언트generateembed비고
AnthropicClientO (Claude)X (raise)기본 claude-sonnet-4-6
OpenAIClientOOOPENAI_API_KEY
EmbeddingClientXOsentence-transformers · HF API
LocalModelClientO (vLLM)FINETUNED_*_API_URL 3종
GeminiClientOGoogle Gemini

공통 베이스: src/ai_clients/_base.py::BaseClient (ABC). 모듈 import는 SDK 없이도 성공, 호출 시점에만 NotImplementedError. _errors.pyConfigError/ProviderError/UnsupportedOperationError 정의.

2.4 Claude Agent (/api/chat, /api/agent/*)

구현체
src/agents/financial_agent.py::FinancialAgent
기본 모델
claude-opus-4-7 · max_tokens 4096 · effort "high" · max_turns 6
Prompt caching
시스템 프롬프트 + 8 도구 정의에 cache_control={"type":"ephemeral"} — 캐시 히트로 ~10× 절감
스트리밍
client.messages.stream() — text / thinking / tool_use 이벤트 SSE 전달
Fallback 체인
Claude Agent → OpenAI gpt-4o-mini → canned 응답 (api/chat.py)

등록 8 도구 (src/agents/tools.py)

  1. get_portfolio_overview — 페르소나 자산/부채/지출
  2. get_recent_transactions — N건 + 카테고리 합계
  3. classify_intent — 8 의도 + 신뢰도 (KPI ②)
  4. recommend_products — Top-K 상품 (KPI ⑦)
  5. simulate_financial_plan — N년 시뮬
  6. search_finance_knowledge — RAG (KPI ⑥)
  7. calculate_dti_ltv — DTI/LTV
  8. classify_finance_scenario — 시나리오 → 16 도구 (KPI ①)

2.5 측정 결과 & 로깅

2.6 페르소나 fixture (api/personas_data.py:22~107)

ID나이직업자산위험도
jiyu25스타트업 마케터1,200만high
minjae35IT 부장8,500만mid
eunyoung62은퇴4억low
soyeon28프리랜서 디자이너1,800만high
junho38개업 의사1.5억mid
jaesung55공무원2.5억low

12개월 자산 추이 · 카테고리별 지출 % · 자산 클래스 비중 · 부채 유형별 분해 등 모두 random.Random(seed) 로 재현 가능.

3. 프론트엔드 (React 19 SPA)

3.1 빌드 스택

프레임워크
React 19.0.0
빌드
Vite 6.0.0 · pnpm 10.20.0
언어
TypeScript 5.6.0
라우팅
react-router-dom 7.1.0
상태
React Context × 3 + TanStack Query 5.59
스타일
Tailwind CSS 4.0 (Vite plugin)
차트
recharts 3.8.1
CSV
papaparse 5.5.3
마크다운
react-markdown + remark-gfm
호스팅
nginx 정적 SPA · dev proxy /api → :8001

3.2 라우트 (4 페이지)

경로역할KPI 연결
/대시보드 — 페르소나별 자산·거래·차트
/chatAI 어시스턴트 — 채팅 + 우측 측정 패널 + CSV 배치①②③⑤⑥ 통합
/recommendTop-10 추천 + 적합도 ring + 인사이트
/analysis10/15/20년 재무 시뮬 + 처리속도 정밀 검증④ (1분 × 5회)
/admin/logsKSEL 검토자용 실시간 로그 뷰어 · SSE · CSV/JSONL 다운로드전체

3.3 측정 UI 아키텍처

/chat 우측 패널

  • EmbeddedMeasurementPanel — KPI ①②③⑤⑥ 5개 동시 누적 평균
  • KpiHistoryPanel — 대화 ID별 측정 히스토리 (in-memory 최대 500)
  • AdvancedKpiPanel — CSV 업로드 → 5건 병렬 worker (Promise.all) → 라이브 평균

/recommend

  • SingleShotKpi7Result — 페르소나별 F1@10 단건 시연
  • Kpi7MeasurementMode — CSV 업로드 (id, user_id, expected)
  • 페르소나 → user_id 매핑 jiyu→user_0000, soyeon→user_0050, ...

/analysis · ThroughputVerifyCard

  • 1분 × 5 회 자동 루프 (Kpi4MeasurementContext)
  • 회차별 — 처리속도(건/min) · Integrity · Security pass rate
  • App 레벨 컨텍스트 → 페이지 이동해도 백그라운드 측정 지속
  • 250 ms 틱으로 경과시간 갱신

/admin/logs

  • ADMIN_LOG_TOKEN 검증 + localStorage 캐싱
  • SSE 실시간 + auto-scroll (하단 50px 이내일 때만)
  • 레벨별 컬러 / KPI · run_id 필터 / CSV · JSONL 다운로드
  • 서버 측 PII 마스킹 (input/expected/prompt redacted)

3.4 페르소나 컨텍스트 (3개)

Contextscope특징
PersonaContextApplocalStorage 영속 + StorageEvent 멀티탭 동기화 + UI 이벤트 로깅
KpiHistoryContextApp대화별 KPI ①②③⑤⑥ 누적 (~500건 ≈ 0.5MB) · 새로고침 시 초기화
Kpi4MeasurementContextApp1분 × 5회 정밀 검증 백그라운드 상태 보존 (페이지 이동 무관)

3.5 SSE 구현

EventSource 미사용 — POST + ReadableStream 직접 파싱 (AbortController 호환). 이벤트 타입: text_delta · thinking_delta · tool_use_start · tool_use_done · done. frontend/src/api/agent.ts, measurement.ts 참조.

4. 인프라 · CI/CD

4.1 GitHub Actions (.github/workflows/)

워크플로트리거역할
ci-cd-alpha.ymlalpha pushEC2 자동 배포 · concurrency: deploy-alpha · cancel-in-progress: false (직렬화)
ci.ymlPR / push경로 필터 분기 — API pytest · Frontend tsc+build · Docker 이미지 캐시

4.2 배포 흐름 (deploy.sh, ~1.5 KB)

  1. SSH 키 로드 (webfactory/ssh-agent)
  2. rsync 동기화 — .git, node_modules, __pycache__, .env* 제외
  3. 원격에서 infisical export --env=beta --path=/fingu-tips --format=dotenv.env 생성
  4. DEPLOY_ID=${{github.sha}}.env 끝에 append → compose 컨테이너 주입
  5. docker compose build --quiet → rolling restart (api healthcheck wait → web)
  6. 외부 smoke — /api/health.deploy_id == github.sha · /healthz == "ok" · 5회 지수백오프 (2/4/6/8/10초)

4.3 컨테이너 (운영 docker-compose.yml)

서비스이미지포트리소스헬스
apiDockerfile.api · Python 3.12-slim · uvicorn 1 worker · --no-access-log8001 (expose)mem 6 GB / res 256 MB/api/health 30s
webDockerfile.frontend · nginx 1.27-alpine (multi-stage build)80, 443mem 128 MB/healthz 30s

api 의 --no-access-log는 uvicorn raw access log 가 query string 노출 위험이 있어 비활성 — 자체 api.request.done 구조화 로그로 대체.

4.4 nginx 리버스 프록시 (nginx.conf)

4.5 EC2 부트스트랩 (deploy/setup-ec2.sh)

  1. Docker + docker-compose 설치
  2. git clone -b alpha https://github.com/FINGU-GRINDA/fingu-tips-rnd-evaluation.git
  3. .env 생성 (OPENAI_API_KEY · HF_TOKEN · DOMAIN 입력)
  4. docker compose -f deploy/docker-compose.yml up -d --build

4.6 Requirements 3-tier

파일용도크기주요 추가 의존성
requirements.txtVercel stub~ 250 MBfastapi, uvicorn, anthropic
requirements-real.txtEC2 real pipeline> 7 GB+ torch (CPU wheel), transformers, sentence-transformers, openai
requirements-test.txtCI unitcompact+ pytest, pytest-mock (torch 제외)
requirements-dev.txt로컬full+ sklearn, rouge-score, faiss-cpu, pinecone

4.7 scripts/ 14 파일 분포

분류파일
운영deploy.sh
데이터셋 빌드build_datasets/kpi1~7.py · 각 150~300 LOC · _common.py (OpenAI 클라이언트 · CostTracker · resumable writer)
변환export_datasets_csv.py (JSONL → CSV · KSEL 친화) · md_to_pdf.py

4.8 보안

5. 테스트 · 증빙 · 데이터셋

5.1 pytest 구성

파일
31 개 · 3,289 LOC
conftest
autouse fixture _clear_ai_secrets — 실수 API 호출 방지 위해 모든 테스트에서 SECRET_ENV_KEYS 제거
contract test
test_kpi_contract.py — 7개 KPI parametrize · load_test_set/call_model/evaluate/main 존재 + MIN_SAMPLES KSEL 기준 일치 검증
메트릭 단위
test_f1_score.py · test_bleu.py · test_nq_em.py · test_llm_rec_score.py · test_throughput.py
KPI 세부
test_kpi5_breakdown.py (per_user_category) · test_kpi7_breakdown.py (per_product_category)
CI
pytest tests/ -q --timeout=30 · 빠른 반복 위해 30 s 타임아웃

5.2 데이터셋 분포 (JSONL · CSV 쌍)

KPI파일줄수용량출처라이선스라벨
1kpi1_financial_qa.jsonl1,050302 KBGPT-4o-mini 합성OpenAI 약관O
2kpi2_text_classification.jsonl1,000234 KBGPT-4o-miniOpenAI 약관O
3kpi3_finetune_qa.jsonl500352 KB출처 문서 참조출처 문서 참조O
4kpi4_throughput_payloads.jsonl10,0003.2 MBFaker (seed 20260514)MITX · 의도
5kpi5_personalized_recommendation.jsonl500359 KB출처 문서 참조출처 문서 참조참고용
6kpi6_nq_finance.jsonl1,000294 KBGPT-4o-miniOpenAI 약관O
7kpi7_product_recommendation.jsonl + 카탈로그1,000554 KBFakerMITO

각 KPI별 _source.md 메타 문서로 출처 · 생성 스크립트 · 라이선스 · 라벨 분포 · 재현 명령 기록. CSV는 KSEL 검토 친화 형태 (헤더 포함).

5.3 evidence/ 5 파일

파일크기용도상태
Technical-overview-of-data-collection-and-model-fine-tuning.pdf211 KB기술 설명서 5 페이지 · 데이터 수집 · 파인튜닝제출용
KSEL_시험의뢰서_2026-05-08.docx21 KBKSEL 공식 시험 의뢰서제출 완료
TIPS_성능평가_의뢰서_참고자료_2026-05-08.docx15 KBTIPS 참고 자료제출용
ksel/KSEL 결과 보관 예정대기
kolas/KOLAS 표준 활용 예정대기

5.4 측정 결과 스키마 (src/kpi/_common.py::save_result)

{
  "kpi": "kpi1_finance_qa",
  "metric": "f1",
  "score": 71.07,
  "target": 71.07,
  "verdict": "pass|conditional|fail",
  "details": { ... },
  "timestamp": "2026-05-19T15:30:45Z",
  "n_samples": 1050,
  "duration_sec": 12.34
}

5.5 주의 사항

6. KSEL 검토 체크포인트

항목상태근거
CI/CD 완전 자동화충족alpha push → 5분 이내 운영
배포 진실성 검증충족github.sha → /api/health.deploy_id 일치 (현재 f531aa5)
시크릿 관리충족Infisical + GH secrets 이중화
인프라 재현성충족docker-compose · setup-ec2.sh · 3-tier requirements
로깅 보안충족nginx mask + uvicorn raw 비활성 + 구조화 JSON
측정 재현성충족전역 시드 20260514 · 결정적 random
실시간 가시화충족SSE 측정 패널 + /admin/logs 라이브 뷰
KPI ④ 1분 × 5회 정밀충족App 레벨 컨텍스트로 백그라운드 유지
KPI ⑤ 라벨 부재주의전략별 비교만 가능 — 시험 절차 문서로 보완 필요
notebooks 비어 있음주의KSEL 녹화 진행 시 7 KPI별 노트북 생성 필요
SSM Agent 미설치참고SSH 외 통제 채널 없음 (별도 PR 권장)
SG 22 0.0.0.0/0주의본인 IP/32 또는 VPN 으로 축소 권장

7. 부록

7.1 API 라우트 전체

메서드경로핸들러 (path:line)
GET/api/healthsrc/api.py:358
GET/api/kpisrc/api.py:386
GET/api/kpi/{n}/datasetsrc/api.py:417
POST/api/kpi/{n}/evaluatesrc/api.py:442
POST/api/kpi/4/evaluate?run=Nsrc/api.py:504
POST/api/kpi/measure-allsrc/api.py:579
GET/api/kpi/{n}/resultssrc/api.py:768
GET/api/kpi-summarysrc/api.py:784
POST/api/kpi/{n}/dataset/uploadsrc/api.py:668
POST/api/kpi/{n}/evaluate/with-datasetsrc/api.py:717
GET/api/kpi/{n}/dataset/samplesrc/api.py:751
POST/api/kpi/{n}/samplesrc/api.py:978
POST/api/kpi/4/evaluate/streamsrc/api.py:1022 (SSE)
POST/api/kpi/{n}/evaluate/streamsrc/api.py:1105 (SSE)
GET/api/personassrc/api.py:856
GET/api/personas/{id}src/api.py:862
GET/api/personas/{id}/portfoliosrc/api.py:874
GET/api/personas/{id}/recommendationssrc/api.py:919
GET/api/personas/{id}/recommendations/shufflesrc/api.py:927
POST/api/chatsrc/api.py:899
POST/api/analysis/simulatesrc/api.py:1260
GET/api/agent/healthapi/agent.py:34
GET/api/agent/toolsapi/agent.py:69
POST/api/agent/tools/{name}api/agent.py:91
POST/api/agent/converseapi/agent.py:113
POST/api/agent/converse/streamSSE

7.2 환경변수 전체

변수기본설명
ENABLE_REAL_PIPELINEfalse실모델 호출 vs stub
ENABLE_API_PIPELINEfalseAPI 기반 어댑터 활성화
ENABLE_FINETUNED_PIPELINEfalsevLLM 미세조정 모델
FINETUNED_KPI2_API_URLKPI2 vLLM 엔드포인트
FINETUNED_KPI3_API_URLKPI3 vLLM 엔드포인트
FINETUNED_API_URL공통 vLLM fallback
ANTHROPIC_API_KEYClaude Agent
ANTHROPIC_AGENT_MODELclaude-opus-4-7Agent 모델
ANTHROPIC_AGENT_EFFORThigh추론 노력 수준
OPENAI_API_KEYfallback chat / KPI4 augment
HF_TOKENgated HF 모델
PINECONE_API_KEY벡터DB
KPI_LOG_LEVELINFO로깅 수준
KPI_NDJSON_DUMP0NDJSON 기록
KPI4_STUB_LATENCY_MS3처리 지연 stub
KPI3_STUB_TARGET0.90reference 반환 확률
KPI3_STUB_KEEP_RATIO0.3mangling 보존 비율
PUBLIC_ORIGINCORS 운영 도메인
SEED20260514전역 시드 prefix
KPI{1..7}_STUB_SEED같음KPI별 시드
DEPLOY_IDlocal배포 ID (github.sha)
ADMIN_LOG_TOKEN/admin/logs 보호
VERCELVercel 런타임 감지

7.3 운영 헬스체크 응답 실측 (2026-05-19 04:51 UTC)

{
  "status": "ok",
  "kpi_count": 7,
  "results_dir": "/app/results",
  "results_dir_writable": false,
  "enable_real_pipeline": "true",
  "enable_api_pipeline": "false",
  "enable_finetuned_pipeline": "true",
  "finetuned_kpi2_url_set": true,
  "finetuned_kpi3_url_set": true,
  "deploy_id": "f531aa5a2e3715c81406e8b1c4f340e74f1644b0",
  "agent_available": true,
  "agent_model": "claude-sonnet-4-5"
}