-
Notifications
You must be signed in to change notification settings - Fork 0
Final Architecture
이 문서는 플랫폼의 통합 아키텍처 개요이다. 인프라, 애플리케이션, 실행 모델, 관측성, 배포 파이프라인을 하나의 흐름으로 연결한다.
각 주제의 상세 설명은 개별 문서에 있으며, 이 문서는 요약과 링크 허브 역할을 한다.
이 시스템의 핵심 개념:
1 Backtest = 1 Kubernetes Job
검증 완료된 레거시 백테스트 엔진을 한 줄도 수정하지 않고, Docker 컨테이너로 감싸 Kubernetes Job으로 실행하는 클라우드 네이티브 플랫폼이다.
| 구성 요소 | 역할 | 설계 원칙 |
|---|---|---|
| Immutable Engine | 백테스트 로직 실행 (수정 금지) | Engine Immutability (Design Principles) |
| Stateless Web | 요청 검증, run_id 발급, Job 생성, 상태 조회 | Stateless Architecture (Design Principles) |
| K8s Worker Job | 엔진 실행, 결과 저장 후 종료 (ephemeral) | Web↔Worker 책임 분리 (App Architecture) |
| MySQL | 모든 결과의 단일 진실 공급원 | Source of Truth (Design Principles) |
| GitOps (Argo CD) | 선언형 배포, drift 자동 복구 | Git = Infrastructure (CI_CD_GitOps) |
| Layer | 구성 요소 | 역할 |
|---|---|---|
| Developer / GitOps | GitHub Actions (CI), Argo CD (CD) | Test → Build → Push → Auto-sync 배포 |
| Edge & Config | Ingress, ConfigMap, Secret | 트래픽 라우팅, 환경 설정 주입 |
| Web Service | Flask Deployment (Stateless) | 요청 검증, run_id 발급, Job 오케스트레이션 |
| Worker Jobs | K8s Job (Ephemeral Pod) | 엔진 실행, Adapter 파생 데이터 생성 |
| Persistence | MySQL StatefulSet + PVC | Canonical data 영구 저장 |
| Observability | Structured Logs, Prometheus, Grafana | run_id 추적 + 메트릭 기반 모니터링 |
User Request
→ Flask Web (Stateless)
→ Input validation
→ run_id (UUID4) 발급
→ MySQL INSERT (status=PENDING)
→ K8s Job 생성 (worker-<run_id_short>)
→ Worker Pod 시작
→ status=RUNNING 전이
→ data_hash 계산 (SHA-256)
→ Immutable Engine 실행
→ Adapter 파생 데이터 생성
→ MySQL UPDATE (status=SUCCEEDED, metrics, equity_curve, trades)
→ Worker Pod 종료
→ Client polls GET /status/<run_id>
→ MySQL SELECT → 결과 반환
상태 머신: PENDING → RUNNING → SUCCEEDED / FAILED (단방향, 되돌릴 수 없음)
-
user_error(잘못된 입력) → Web이PENDING → FAILED처리, Job 미생성 (HTTP 400) -
system_error(런타임 장애) → Worker 또는 Web이FAILED처리 (HTTP 500)
상태 머신, sequence diagram, Job 규격 상세 → Execution Lifecycle
Kubernetes 클러스터 위에 namespace stock-backtest로 격리된 환경을 구성한다.
- Web Deployment (Flask + Gunicorn, Stateless)
- MySQL StatefulSet + PersistentVolumeClaim
- Worker Job (ephemeral,
backoffLimit: 1,ttlSecondsAfterFinished: 86400) - RBAC: namespace-scoped Role (
jobs.batch에 대해create/get/list/delete만 허용) - Ingress (NGINX): 외부 트래픽 라우팅
K8s 리소스 토폴로지, 계층 구조, 보안/스케일링 전략 → Infra Architecture
Web (app.py) Worker (worker.py)
├── 요청 검증 + run_id 발급 ├── 엔진 실행 (backtest/engine.py)
├── PENDING INSERT ├── Adapter 파생 데이터 생성
├── JobLauncher → K8s Job 생성 ├── MySQL 결과 저장
└── /status/<run_id> 상태 조회 └── SUCCEEDED/FAILED 전이 후 종료
JobLauncher 추상화: JOB_LAUNCHER_MODE 환경변수로 Local(subprocess) / K8s(BatchV1Api) 전환.
Adapter Layer: 엔진 출력에서 drawdown, portfolio chart, win_rate 등을 파생. 엔진 수정 없이 UI 데이터를 확장한다.
모듈 구조, 의존 방향, Adapter 범위 → App Architecture
MySQL이 모든 백테스트 결과의 단일 진실 공급원이다.
- MUST persist: run_id, metrics, equity_curve, trades, data_hash, image_tag, timestamps
-
SHOULD persist:
chart_base64(backward compatibility / performance optimization) - MUST NOT persist: drawdown_curve, portfolio charts (Adapter에서 on-demand 생성)
K8s Job 객체의 수명과 MySQL 감사 이력은 완전히 독립적이다. Job이 삭제되어도 run_id로 전체 실행 이력을 조회할 수 있다.
- ERD, 저장 경계 → ERD-Data Model
- 저장 경계 상세 (MUST/SHOULD/MUST NOT) → Reproducibility
두 계층으로 구성된다.
| 계층 | 구현 | 목적 |
|---|---|---|
| Structured Logging | stdout/stderr + [run_id=<UUID>]
|
요청 단위 전 구간 추적 (Rule 8 필수) |
| Metrics | Prometheus + Grafana | 시스템 건강 지표, SLO 모니터링 |
- Web Pod의
/metrics엔드포인트를 ServiceMonitor가 15초 간격으로 scrape -
run_id는 Prometheus label로 사용하지 않음 (cardinality 제한)
메트릭 정의, PromQL, Grafana 대시보드 → Observability
git push → GitHub Actions (CI)
1. pytest
2. docker build + push :<git-sha-short>
3. k8s/web-deployment.yaml image tag 업데이트 → commit
↓
Argo CD (CD): k8s/ 디렉터리 감시 → auto-sync → Rolling Update
-
Immutable image tags:
:<git-sha-short>(Rule 10) -
롤백: git revert → main 반영 → Argo CD 자동 sync
-
CI 파이프라인, GitOps 전략, 롤백 절차 → CI_CD_GitOps
-
상세 롤백 절차 → Rollback Runbook
| 원칙 | 핵심 | 위반 시 결과 |
|---|---|---|
| Engine Immutability |
engine.py 수정 금지. 새 기능은 Adapter 패턴. |
재현성 파괴, 테스트 무효화 |
| Stateless Web | 파일 I/O 금지, stdout/stderr 로깅만 | HPA 수평 확장 불가 |
| Worker-only Execution | Web은 오케스트레이션만, 실행은 Worker | Web OOM, 실행 격리 실패 |
| GitOps Deployment |
k8s/ = Source of Truth, 수동 kubectl 금지 |
배포 이력 추적 불가 |
| run_id Tracing | 모든 로그에 [run_id=<UUID>] 포함 |
분산 환경 디버깅 불가 |
| Reproducibility | 동일 입력 → 동일 출력 (4개 식별자) | 결과 신뢰성 상실 |
- 8가지 설계 원칙 상세 → Design Principles
- 8개 ADR (의사결정 기록) → ADR-Design Decisions
모든 컴포넌트(Web, Worker)가 stdout/stderr로 로그를 출력하며,
모든 로그 라인에 [run_id=<RUN_ID>]를 포함한다.
kubectl logs와 grep으로 전 구간 추적이 가능하다.
5개 애플리케이션 메트릭을 /metrics 엔드포인트로 노출한다.
| Metric | Type | 설명 |
|---|---|---|
http_requests_total |
Counter | HTTP 요청 수 (method, endpoint, status) |
http_request_duration_seconds |
Histogram | 요청 처리 시간 |
backtest_requests_total |
Counter | 백테스트 제출 수 (rule_type, outcome) |
job_launch_success_total |
Counter | Job 생성 성공 |
job_launch_failure_total |
Counter | Job 생성 실패 |
4개 Row, 17개 Panel로 구성된 대시보드가 Web API Health, Backtest Pipeline, Job Orchestration, Infrastructure Health를 시각화한다.
메트릭 상세, PromQL, scrape 설정, 대시보드 구조 → Observability
동일한 4개 식별자가 주어지면 엔진은 동일한 결과를 생성해야 한다.
| Identifier | 역할 | 저장 위치 |
|---|---|---|
data_hash |
동일한 시장 데이터 보장 (SHA-256) | backtest_results.data_hash |
rule_type + params
|
동일한 전략 로직/파라미터 보장 |
backtest_results.rule_type, params_json
|
engine_version |
동일한 엔진 코드 버전 보장 |
image_tag로 표현됨 |
image_tag |
동일한 컨테이너 이미지 및 런타임 환경 보장 | backtest_results.image_tag |
-
data_hash는 Worker가 엔진 실행 전에 계산한다. -
engine.py가 불변이므로engine_version은 실제 저장 시image_tag로 표현된다. - 입력 데이터는 Docker 이미지에 내장되며 read-only로 사용된다.
재현성 식별자, 검증 절차, 저장 경계 → Reproducibility
| 문서 | 내용 |
|---|---|
| Infra Architecture | K8s 리소스 토폴로지, 계층 구조, 보안/스케일링 전략 |
| App Architecture | 모듈 구조, Web↔Worker 책임 경계, JobLauncher, Adapter Layer |
| Execution Lifecycle | 상태 머신, Failure 분류, Job 규격, 생명주기 정책 |
| Observability | Prometheus 메트릭, Grafana 대시보드, /metrics 엔드포인트 |
| CI_CD_GitOps | CI 파이프라인, GitOps 전략, Image Tag 전략, 롤백 |
| Security Model | RBAC, Secret 관리, Network Egress, Input Validation |
| ERD-Data Model | backtest_results 테이블 스키마, 인덱스 전략 |
| Reproducibility | 재현성 식별자, 데이터 공급 전략, 저장 경계 |
| Design Principles | 8가지 아키텍처 원칙 |
| ADR-Design Decisions | 8개 ADR (K8s Job, JSON, Stateless, API, Image Tags 등) |
| ← Previous | Archive | Next → |
|---|---|---|
| ADR-Design Decisions | Home | Infra Architecture |

