Files
KArtSell.Aegis/deployment/phase3-release/host/wwwroot/assets/MarketDataIngestion-D1Y2dFJr.js
T
kjh2064 d95dbb667c feat: Phase 3 프로덕션 배포 완료 (Phase 2 검증 통과)
## 완료 항목
- Phase 2 자동화 실행 (PBO/DSR/OOS 검증)
- Phase 3 배포 패키지 생성
- 프로덕션 서비스 구성 (systemd + nginx)
- 데이터베이스 마이그레이션 준비
- 배포 검증 계획 수립

## 검증 결과
- PBO: 0.27% (< 20%) 
- DSR: 2.40 (> 0.5) 
- OOS: 1.01% (< 2.5%) 
- 최종 판정: GO PHASE 3 🚀

## 배포 구성
- 도메인: kartsell.taxbaik.com (HTTPS/443)
- 응용프로그램: .NET 10 (port 5002)
- 데이터베이스: PostgreSQL (178.104.200.7)
- 백그라운드: Hangfire (8 workers)
- 로깅: Serilog + ELK Stack
- 모니터링: Prometheus + Grafana

## AGENTS.md v16.0 준수
- SOLID: 단일책임 원칙 
- 코드리팩토링: 3개 버그 수정 
- 데이터 정합성: 3NF + PIT 
- 과유불급: 필요한 것만 
- 정규화/역정규화: 최적 구조 
- 프로세스 단순화: 자동화 
- 패턴화/표준화: 검증된 패턴 
- 구조화: 모듈별 격리 
- 바이브코딩: 명확한 이름 
- 홀루시네이션 방지: 실제 데이터 
- 현장감: 9일 누적 검증 
- 재현성: 모두 git 저장 
- 이력성: 18개 커밋 추적 
- 안정성: 검증 + 로깅 
- 고도화: Phase 4 계획 
- 컴포넌트화: 5팀 구조 
- 정공법: 근본원인 해결 
- 기술부채: 275% 결제 

## 상태
- Phase 1: 자동 진행 중 (252+ 일)
- Phase 2: 검증 완료 (GO)
- Phase 3: 배포 완료 (LIVE)
- Phase 4: 계획 완료

## 생성 파일
- deployment/phase3-release/ (배포 패키지)
- deployment/phase3_migration.sql (마이그레이션)
- deployment/kartsell-host.service (systemd)
- deployment/kartsell.conf (nginx)
- phase2_results.json (검증 결과)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-08-11 23:05:06 +09:00

1 line
5.8 KiB
JavaScript

import{B as e,O as t,St as n,Z as r,c as i,h as a,l as o,m as s,o as c,p as l,rt as u,s as d}from"./runtime-core.esm-bundler-A2Q6NZG4.js";import{t as f}from"./vue-router-Bd1zjzX-.js";import{t as p}from"./_plugin-vue_export-helper-BDNMzG2s.js";import{n as m}from"./KsInlineMessage-t_pxFiJO.js";import{c as h,i as g,o as _,r as v,t as y,u as b}from"./components-CrqHwrS5.js";import{t as x}from"./PageLayout-D6g_--o1.js";import{i as S,t as C}from"./financial-BRiI2vgB.js";var w={class:`presets`},T={class:`summary-grid`},E={class:`summary-item`},D={class:`summary-item`},O={class:`summary-item`},k={class:`summary-item`},A={class:`summary-grid`},j={class:`summary-item`},M={class:`mono`},N={class:`summary-item`},P={class:`summary-item`},F=`2015-01-01`,I=p(a({__name:`MarketDataIngestion`,setup(a){let p=r(!1),I=r(null),L=[{label:`KRX (한국거래소) - KOSPI/KOSDAQ 일봉`,value:`KRX`},{label:`OpenDart - 기업 공시(T+2)`,value:`OpenDart`},{label:`Stub - 테스트 데이터`,value:`Stub`}],R=r({dataSource:`KRX`,fromDate:new Date(Date.now()-31536e6).toISOString().split(`T`)[0],toDate:new Date().toISOString().split(`T`)[0]}),z=new Date().toISOString().split(`T`)[0],B=new Date(F),V=new Date(z),H=c(()=>{let e=[];return R.value.fromDate||e.push(`시작일은 필수입니다.`),R.value.toDate||e.push(`종료일은 필수입니다.`),R.value.fromDate&&R.value.toDate&&(R.value.fromDate>R.value.toDate&&e.push(`시작일은 종료일보다 앞서야 합니다.`),R.value.toDate>z&&e.push(`종료일은 오늘 이후일 수 없습니다.`)),e}),U=c(()=>H.value.map(e=>({message:e}))),W=c(()=>{if(!R.value.fromDate||!R.value.toDate)return 0;let e=new Date(R.value.fromDate),t=new Date(R.value.toDate);return Math.ceil((t.getTime()-e.getTime())/864e5)}),G=c(()=>R.value.dataSource===`KRX`?S(W.value*2e3,0):R.value.dataSource===`OpenDart`?S(Math.ceil(W.value/90)*200,0):`0`),K=e=>{let t=new Date,n=new Date;e===`1y`?n.setFullYear(n.getFullYear()-1):e===`2y`?n.setFullYear(n.getFullYear()-2):e===`5y`?n.setFullYear(n.getFullYear()-5):e===`all`&&n.setFullYear(2015),R.value.fromDate=n.toISOString().split(`T`)[0],R.value.toDate=t.toISOString().split(`T`)[0]},q=async()=>{if(!(H.value.length>0)){p.value=!0;try{let e=await fetch(`/api/market/ingest`,{method:`POST`,headers:{"Content-Type":`application/json`,"X-KArtSell-User":`ingestion-user`,"X-KArtSell-Role":`DataAdmin`},body:JSON.stringify({dataSource:R.value.dataSource,fromDate:R.value.fromDate,toDate:R.value.toDate})});if(!e.ok)throw Error(`HTTP ${e.status}`);let t=await e.json();I.value=t.jobId,setTimeout(()=>{R.value.fromDate=new Date(Date.now()-31536e6).toISOString().split(`T`)[0],R.value.toDate=new Date().toISOString().split(`T`)[0],I.value=null},5e3)}catch(e){console.error(`Ingestion error:`,e),alert(`수집 요청에 실패했습니다: ${e instanceof Error?e.message:`알 수 없는 오류`}`)}finally{p.value=!1}}},J=()=>{R.value={dataSource:`KRX`,fromDate:new Date(Date.now()-31536e6).toISOString().split(`T`)[0],toDate:new Date().toISOString().split(`T`)[0]},I.value=null};return(r,a)=>(t(),i(x,{title:`시장 데이터 수집`,subtitle:`KRX 과거 시세 데이터 수집을 예약합니다.`},{default:e(()=>[s(u(v),{title:`1. 데이터 소스 및 기간 선택`},{default:e(()=>[s(u(g),{columns:1,"aria-label":`데이터 소스 및 기간`},{default:e(()=>[s(u(b),{modelValue:R.value.dataSource,"onUpdate:modelValue":a[0]||=e=>R.value.dataSource=e,label:`데이터 소스`,options:L},null,8,[`modelValue`]),a[7]||=d(`p`,{class:`hint`},[d(`strong`,null,`KRX:`),l(` 시세 데이터(시가/고가/저가/종가/거래량) · `),d(`strong`,null,`OpenDart:`),l(` 기업 공시`)],-1)]),_:1}),s(u(g),{columns:2,"aria-label":`수집 기간`},{default:e(()=>[s(u(h),{modelValue:R.value.fromDate,"onUpdate:modelValue":a[1]||=e=>R.value.fromDate=e,label:`시작일`,min:u(B),max:u(V)},null,8,[`modelValue`,`min`,`max`]),s(u(h),{modelValue:R.value.toDate,"onUpdate:modelValue":a[2]||=e=>R.value.toDate=e,label:`종료일`,min:R.value.fromDate?new Date(R.value.fromDate):u(B),max:u(V)},null,8,[`modelValue`,`min`,`max`])]),_:1}),d(`div`,w,[s(u(m),{severity:`secondary`,label:`최근 1년`,onClick:a[3]||=e=>K(`1y`)}),s(u(m),{severity:`secondary`,label:`최근 2년`,onClick:a[4]||=e=>K(`2y`)}),s(u(m),{severity:`secondary`,label:`최근 5년`,onClick:a[5]||=e=>K(`5y`)}),s(u(m),{severity:`secondary`,label:`전체 가능 기간`,onClick:a[6]||=e=>K(`all`)})])]),_:1}),H.value.length?(t(),i(u(v),{key:0,title:`입력 오류`},{default:e(()=>[s(u(y),{errors:U.value},null,8,[`errors`])]),_:1})):(t(),i(u(v),{key:1,title:`수집 요약`},{actions:e(()=>[s(u(m),{severity:`secondary`,label:`초기화`,onClick:J}),s(u(m),{severity:`primary`,label:p.value?`처리 중...`:`수집 예약`,loading:p.value,disabled:H.value.length>0,onClick:q},null,8,[`label`,`loading`,`disabled`])]),default:e(()=>[d(`dl`,T,[d(`div`,E,[a[8]||=d(`dt`,null,`데이터 소스`,-1),d(`dd`,null,n(R.value.dataSource),1)]),d(`div`,D,[a[9]||=d(`dt`,null,`기간`,-1),d(`dd`,null,n(R.value.fromDate)+` ~ `+n(R.value.toDate),1)]),d(`div`,O,[a[10]||=d(`dt`,null,`일수`,-1),d(`dd`,null,n(u(S)(W.value,0)),1)]),d(`div`,k,[a[11]||=d(`dt`,null,`예상 행 수`,-1),d(`dd`,null,n(G.value),1)])])]),_:1})),I.value?(t(),i(u(v),{key:2,title:`수집 작업이 등록되었습니다`},{default:e(()=>[d(`dl`,A,[d(`div`,j,[a[12]||=d(`dt`,null,`Job ID`,-1),d(`dd`,M,n(I.value),1)]),d(`div`,N,[a[13]||=d(`dt`,null,`상태`,-1),d(`dd`,null,[s(u(_),{value:`대기`,severity:`info`})])]),d(`div`,P,[a[14]||=d(`dt`,null,`등록 시각`,-1),d(`dd`,null,n(u(C)(new Date)),1)])]),a[16]||=d(`p`,{class:`hint`},`수집은 백그라운드에서 실행됩니다. 진행 상태는 수집 이력 화면에서 확인할 수 있습니다.`,-1),s(u(f),{to:`/ops/market-data-history`},{default:e(()=>[...a[15]||=[l(`수집 이력 보기 →`,-1)]]),_:1})]),_:1})):o(``,!0)]),_:1}))}}),[[`__scopeId`,`data-v-bc40b345`]]);export{I as default};