galaxis-po/docs/plans/2026-02-03-phase6-finishing.md
zephyrdark 63ffe2439e docs: add Phase 6 finishing design document
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 12:20:39 +09:00

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 구현 방식

  1. DB에 저장된 prices 테이블의 최신 데이터 사용
  2. DB에 없으면 pykrx로 조회 후 캐시
  3. 추후 OpenAPI 연동 시 구현체만 교체 (인터페이스 유지)

4.3 기존 코드 리팩토링

  • RebalanceService.get_current_prices()PriceService 사용으로 변경
  • BacktestEnginePriceService 사용으로 변경

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 테스트 시나리오

  1. 인증 플로우: 로그인 → 토큰 발급 → 인증된 요청
  2. 포트폴리오 플로우: 생성 → 목표비율 설정 → 보유자산 입력 → 리밸런싱 계산
  3. 전략 플로우: 전략 선택 → 파라미터 입력 → 결과 조회
  4. 백테스트 플로우: 백테스트 생성 → 완료 대기 → 결과 조회
  5. 스냅샷 플로우: 스냅샷 생성 → 히스토리 조회 → 수익률 확인

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: 기반 서비스

  1. PriceService 구현 (Mock)
  2. 스냅샷 Pydantic 스키마 추가
  3. 스냅샷 API 엔드포인트 구현

Batch 2: 배치 및 프론트엔드

  1. APScheduler 설정 및 스냅샷 배치 작업
  2. 수익률 계산 서비스
  3. 스냅샷 히스토리 프론트엔드 페이지

Batch 3: Docker

  1. Backend Dockerfile 정리
  2. Frontend Dockerfile 정리
  3. docker-compose.yml 업데이트

Batch 4: E2E 테스트

  1. Backend E2E 테스트 (pytest + httpx)
  2. Frontend E2E 테스트 (Playwright)

문서 버전: 1.0 작성일: 2026-02-03