Initial commit

This commit is contained in:
2025-11-14 11:05:31 +09:00
commit b147498c31
124 changed files with 17983 additions and 0 deletions

124
backend/app/main.py Normal file
View File

@@ -0,0 +1,124 @@
from fastapi import FastAPI, WebSocket, WebSocketDisconnect, Request
from fastapi.middleware.cors import CORSMiddleware
from contextlib import asynccontextmanager
import logging
import time
from app.core.config import settings
from app.api import api_router
from app.services.websocket_manager import websocket_manager
from app.core.database import engine, Base
from app.models import models # 모델 임포트
# 로깅 설정
logging.basicConfig(
level=getattr(logging, settings.LOG_LEVEL.upper(), logging.INFO),
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
@asynccontextmanager
async def lifespan(app: FastAPI):
"""애플리케이션 시작/종료 시 실행될 코드"""
logger.info("Starting Auto Stock Trading System...")
# DB 테이블 자동 생성
try:
logger.info(f"Connecting to database: {settings.DATABASE_URL.split('@')[1] if '@' in settings.DATABASE_URL else 'unknown'}")
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
logger.info("✅ Database tables created successfully")
except ConnectionRefusedError as e:
logger.error(f"❌ Database connection refused: {e}")
logger.error("Please check if PostgreSQL server is running and accessible")
raise
except Exception as e:
logger.error(f"❌ Failed to create database tables: {e}")
import traceback
logger.error(traceback.format_exc())
raise
yield
# 종료 시 정리 작업
logger.info("Shutting down Auto Stock Trading System...")
await engine.dispose()
app = FastAPI(
title=settings.APP_NAME,
description="Claude AI와 MCP를 활용한 자동 주식 매매 시스템",
version="1.0.0",
lifespan=lifespan,
debug=settings.DEBUG,
)
# CORS 설정 (반드시 라우터 등록 전에)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
expose_headers=["*"],
)
logger.info("CORS middleware configured")
# 요청 로깅 미들웨어
@app.middleware("http")
async def log_requests(request: Request, call_next):
start_time = time.time()
logger.info(f"🔵 Request: {request.method} {request.url}")
response = await call_next(request)
process_time = time.time() - start_time
logger.info(f"🟢 Response: {request.method} {request.url} - Status: {response.status_code} - Time: {process_time:.3f}s")
return response
# API 라우터 등록
app.include_router(api_router, prefix="/api/v1")
@app.get("/")
async def root():
return {
"message": "Auto Stock Trading System API",
"version": "1.0.0",
"status": "running"
}
@app.get("/health")
async def health_check():
return {"status": "healthy"}
@app.websocket("/ws/{client_id}")
async def websocket_endpoint(websocket: WebSocket, client_id: str):
"""WebSocket 연결 엔드포인트"""
await websocket_manager.connect(websocket, client_id)
try:
while True:
data = await websocket.receive_text()
# 메시지 처리
await websocket_manager.send_personal_message(
f"Echo: {data}", client_id
)
except WebSocketDisconnect:
websocket_manager.disconnect(client_id)
logger.info(f"Client {client_id} disconnected")
if __name__ == "__main__":
import uvicorn
uvicorn.run(
"app.main:app",
host=settings.BACKEND_HOST,
port=settings.BACKEND_PORT,
reload=settings.DEBUG,
)