5.6 KiB
5.6 KiB
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 스냅샷 생성 로직
def create_snapshot(portfolio_id):
# 1. 현재 보유 종목 조회
# 2. 각 종목 현재가 조회 (PriceService)
# 3. 총 평가금액 계산
# 4. PortfolioSnapshot 저장
# 5. SnapshotHolding 저장 (종목별 상세)
3.3 수익률 계산
- 일간/주간/월간/연간 수익률
- 첫 스냅샷 대비 누적 수익률
- 시간 가중 수익률 (TWR)
4. Mock 시세 서비스
4.1 PriceService 인터페이스
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 구현 방식
- DB에 저장된 prices 테이블의 최신 데이터 사용
- DB에 없으면 pykrx로 조회 후 캐시
- 추후 OpenAPI 연동 시 구현체만 교체 (인터페이스 유지)
4.3 기존 코드 리팩토링
RebalanceService.get_current_prices()→PriceService사용으로 변경BacktestEngine→PriceService사용으로 변경
5. 자동 스냅샷 배치
5.1 APScheduler 설정
# 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 배치 작업 로직
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 테스트 시나리오
- 인증 플로우: 로그인 → 토큰 발급 → 인증된 요청
- 포트폴리오 플로우: 생성 → 목표비율 설정 → 보유자산 입력 → 리밸런싱 계산
- 전략 플로우: 전략 선택 → 파라미터 입력 → 결과 조회
- 백테스트 플로우: 백테스트 생성 → 완료 대기 → 결과 조회
- 스냅샷 플로우: 스냅샷 생성 → 히스토리 조회 → 수익률 확인
6.3 테스트 데이터
- pytest fixtures로 테스트용 사용자/포트폴리오 생성
- 테스트 완료 후 자동 정리 (rollback)
7. Docker 설정
7.1 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 실행 명령
docker-compose up -d # 전체 실행
docker-compose logs -f # 로그 확인
docker-compose down # 종료
8. 구현 순서
Batch 1: 기반 서비스
- PriceService 구현 (Mock)
- 스냅샷 Pydantic 스키마 추가
- 스냅샷 API 엔드포인트 구현
Batch 2: 배치 및 프론트엔드
- APScheduler 설정 및 스냅샷 배치 작업
- 수익률 계산 서비스
- 스냅샷 히스토리 프론트엔드 페이지
Batch 3: Docker
- Backend Dockerfile 정리
- Frontend Dockerfile 정리
- docker-compose.yml 업데이트
Batch 4: E2E 테스트
- Backend E2E 테스트 (pytest + httpx)
- Frontend E2E 테스트 (Playwright)
문서 버전: 1.0 작성일: 2026-02-03