docs: add Phase 6 finishing design document

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
zephyrdark 2026-02-03 12:20:39 +09:00
parent 3a9e5513f9
commit 63ffe2439e

View File

@ -0,0 +1,222 @@
# Phase 6: 마무리 단계 설계
## 1. 개요
**범위:**
| 항목 | 구현 방식 |
|------|----------|
| 스냅샷/수익률 추적 | 수동 + 자동 (배치) |
| ETF 시세 연동 | Mock API (추후 실제 연동) |
| 테스트 | E2E 테스트 (전체 플로우) |
| 배포 | Docker 완성 (로컬 배포 가능) |
---
## 2. 파일 구조
```
backend/
├── app/api/snapshot.py # 스냅샷 API
├── app/services/price_service.py # Mock 시세 서비스
├── jobs/
│ ├── scheduler.py # APScheduler 설정
│ └── snapshot_job.py # 자동 스냅샷 배치
├── tests/ # pytest 테스트
│ └── e2e/
├── Dockerfile # 정리
frontend/
├── src/app/portfolio/[id]/history/page.tsx # 스냅샷 히스토리 페이지
├── e2e/ # Playwright E2E 테스트
├── Dockerfile # 정리
```
---
## 3. 스냅샷 API
### 3.1 엔드포인트
| Method | Endpoint | 설명 |
|--------|----------|------|
| GET | /api/portfolios/{id}/snapshots | 스냅샷 목록 조회 |
| POST | /api/portfolios/{id}/snapshots | 스냅샷 수동 생성 |
| GET | /api/portfolios/{id}/snapshots/{snapshot_id} | 스냅샷 상세 조회 |
| DELETE | /api/portfolios/{id}/snapshots/{snapshot_id} | 스냅샷 삭제 |
| GET | /api/portfolios/{id}/returns | 수익률 추이 조회 |
### 3.2 스냅샷 생성 로직
```python
def create_snapshot(portfolio_id):
# 1. 현재 보유 종목 조회
# 2. 각 종목 현재가 조회 (PriceService)
# 3. 총 평가금액 계산
# 4. PortfolioSnapshot 저장
# 5. SnapshotHolding 저장 (종목별 상세)
```
### 3.3 수익률 계산
- 일간/주간/월간/연간 수익률
- 첫 스냅샷 대비 누적 수익률
- 시간 가중 수익률 (TWR)
---
## 4. Mock 시세 서비스
### 4.1 PriceService 인터페이스
```python
class PriceService:
def get_current_price(self, ticker: str) -> Decimal:
"""단일 종목 현재가 조회"""
def get_current_prices(self, tickers: List[str]) -> Dict[str, Decimal]:
"""복수 종목 현재가 조회"""
def get_price_history(self, ticker: str, start_date, end_date) -> List[PriceData]:
"""과거 시세 조회"""
```
### 4.2 Mock 구현 방식
1. DB에 저장된 prices 테이블의 최신 데이터 사용
2. DB에 없으면 pykrx로 조회 후 캐시
3. 추후 OpenAPI 연동 시 구현체만 교체 (인터페이스 유지)
### 4.3 기존 코드 리팩토링
- `RebalanceService.get_current_prices()``PriceService` 사용으로 변경
- `BacktestEngine``PriceService` 사용으로 변경
---
## 5. 자동 스냅샷 배치
### 5.1 APScheduler 설정
```python
# jobs/scheduler.py
from apscheduler.schedulers.background import BackgroundScheduler
scheduler = BackgroundScheduler()
# 매일 18:30 (장 마감 후) 자동 스냅샷
scheduler.add_job(
create_daily_snapshots,
trigger='cron',
hour=18, minute=30,
day_of_week='mon-fri',
id='daily_snapshots'
)
```
### 5.2 배치 작업 로직
```python
def create_daily_snapshots():
# 1. 모든 포트폴리오 조회
# 2. 각 포트폴리오에 대해 스냅샷 생성
# 3. job_logs 테이블에 실행 결과 기록
```
### 5.3 스케줄러 시작
- FastAPI lifespan 이벤트에서 스케줄러 시작/종료
- Docker 환경에서 백엔드 컨테이너와 함께 실행
---
## 6. E2E 테스트
### 6.1 테스트 도구
| 영역 | 도구 |
|------|------|
| Backend | pytest + httpx (async client) |
| Frontend | Playwright |
| 통합 | docker-compose로 전체 환경 실행 |
### 6.2 테스트 시나리오
1. **인증 플로우**: 로그인 → 토큰 발급 → 인증된 요청
2. **포트폴리오 플로우**: 생성 → 목표비율 설정 → 보유자산 입력 → 리밸런싱 계산
3. **전략 플로우**: 전략 선택 → 파라미터 입력 → 결과 조회
4. **백테스트 플로우**: 백테스트 생성 → 완료 대기 → 결과 조회
5. **스냅샷 플로우**: 스냅샷 생성 → 히스토리 조회 → 수익률 확인
### 6.3 테스트 데이터
- pytest fixtures로 테스트용 사용자/포트폴리오 생성
- 테스트 완료 후 자동 정리 (rollback)
---
## 7. Docker 설정
### 7.1 Dockerfile
```dockerfile
# backend/Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
# frontend/Dockerfile
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
CMD ["npm", "start"]
```
### 7.2 docker-compose.yml 업데이트
- healthcheck 추가 (postgres, backend)
- depends_on 조건 추가 (service_healthy)
- 환경변수 .env 파일 분리
- volumes 설정 (데이터 영속성)
### 7.3 실행 명령
```bash
docker-compose up -d # 전체 실행
docker-compose logs -f # 로그 확인
docker-compose down # 종료
```
---
## 8. 구현 순서
### Batch 1: 기반 서비스
1. PriceService 구현 (Mock)
2. 스냅샷 Pydantic 스키마 추가
3. 스냅샷 API 엔드포인트 구현
### Batch 2: 배치 및 프론트엔드
4. APScheduler 설정 및 스냅샷 배치 작업
5. 수익률 계산 서비스
6. 스냅샷 히스토리 프론트엔드 페이지
### Batch 3: Docker
7. Backend Dockerfile 정리
8. Frontend Dockerfile 정리
9. docker-compose.yml 업데이트
### Batch 4: E2E 테스트
10. Backend E2E 테스트 (pytest + httpx)
11. Frontend E2E 테스트 (Playwright)
---
**문서 버전:** 1.0
**작성일:** 2026-02-03