실시간 금융 데이터 파이프라인 + AI 감성 분석/RAG 리포트 + 조건부 자동매매 엔진
국내 대장주 10종목을 대상으로 실시간 시세를 수집하고, AI가 뉴스를 분석해 투자자에게 인사이트를 제공하며, 가격/손절/익절/트레일링 스탑/AI 호재 점수 조건에 따라 KIS 모의투자 계좌로 자동매매까지 수행하는 플랫폼입니다.
[KIS Websocket] ──(실시간 체결가 push)──> [KisWebsocketClient] ──SET──> [Redis]
│
[네이버 뉴스 API] ──(5분 주기 요약 수집)──> [스케줄러] ──publish──> [RabbitMQ] │
│ │
┌───────────────┘ │
▼ │
[뉴스 분석 Worker] │
① OpenAI 감성 분석(0~100점) │
② OpenAI 임베딩 생성 │
③ MySQL news_sentiments 저장 │
│ │
▼ ▼
[PriceUpdatedEvent / NewsSentimentSavedEvent]
│ (전용 스레드풀, @Async)
▼
[ConditionMatchingEngine 조건 매칭]
가격 / 손절·익절(%) / 트레일링 스탑 / AI 점수
트리거를 AND·OR로 결합해 평가
│
충족 시 ┌───────┴────────┐
▼ ▼
[KIS 모의투자 주문 실행] [WebSocket 실시간 알림]
│
▼
[지갑/보유종목 정산 (OrderSettlementService)]
[RAG 리포트] news_sentiments(VECTOR 1536) 코사인 유사도 Top-10 → GPT 프롬프트 조립 → 리포트 생성/캐싱
| 영역 | 기술 | 버전/비고 |
|---|---|---|
| Backend | Spring Boot | 3.5.x / Java 17 |
| Frontend | Next.js (App Router) + React | Next 16 / React 19 / TypeScript / Tailwind CSS v4 / Zustand |
| RDBMS | MySQL | 9.0+ (VECTOR(1536) 지원, ddl-auto: none 수동 스키마 관리) |
| Cache | Redis | 시세 캐시·토큰 캐시·동시성 락·레이트리미터 |
| Message Queue | RabbitMQ | 뉴스 분석 큐 / 리포트 생성 큐 |
| Authentication | OAuth 2.0(Kakao) + JWT | Access + Refresh Token Rotation. Google은 API 문서상 예약돼 있으나 미구현(명시적으로 차단) |
| Real-time Stock | KIS(한국투자증권) Open API | WebSocket 구독(push) 방식, REST는 인증/스냅샷/주문 전용 |
| News | 네이버 뉴스 검색 API | 요약(description) 기반, 본문 크롤링 없음 |
| AI | OpenAI API | 감성 분석(0~100점) + 임베딩 + 리포트 생성(RAG) |
| Vector Search | MySQL Native VECTOR(1536) |
별도 Vector DB 없이 코사인 유사도를 자바에서 직접 계산 |
AutoQuant.AI/
├── docs/ # 📚 프로젝트 문서 (루트에 위치)
│ ├── clinerules.md # AI Agent 개발 지침서
│ ├── database.md # DB 테이블 설계 + DDL
│ ├── workflow.md # 전체 워크플로우 + 아키텍처
│ ├── kisflow.md # KIS API 인증/시세 플로우
│ ├── redisflow.md # Redis Key 설계
│ ├── api.md # API 명세서
│ └── incident-trading-engine-blocking.md # 자동매매 엔진 장애 기록 (원인→수정→검증)
├── server/ # Spring Boot 백엔드
│ └── src/main/java/com/example/invest_ai/
│ ├── config/ # AsyncConfig, RabbitMqConfig 등
│ ├── domain/ # 도메인별 패키지
│ │ ├── auth/ # OAuth 로그인 + JWT
│ │ ├── user/ # 회원
│ │ ├── stock/ # 종목 마스터 + 시세 조회
│ │ ├── chart/ # 일봉/분봉 차트
│ │ ├── asset/ # 지갑(Wallet) + 보유종목(Holding) + 매매이력
│ │ ├── trade/ # 자동매매 조건(Condition) + 조건 매칭 엔진
│ │ ├── news/ # 뉴스 티커 + 감성분석 결과
│ │ └── report/ # AI 투자 리포트(RAG)
│ ├── global/ # 공통 유틸(예외, WebSocket 세션 매니저 등)
│ └── infra/ # 인프라 연동
│ ├── config/ # RedisKeys, RedisConfig, WebClientConfig
│ ├── kis/ # KIS 인증/시세/차트/주문 클라이언트
│ ├── openai/ # OpenAI 연동
│ ├── rabbitmq/ # 뉴스 분석 / 리포트 생성 Worker
│ └── scheduler/ # 네이버 뉴스 수집, KIS 시세 예열 스케줄러
├── front/ # Next.js 프론트엔드 (대시보드/조건/포트폴리오/리포트/로그인)
├── docker-compose.yaml # MySQL 9 + Redis + RabbitMQ
└── README.md
users ──1:1── user_wallets
users ──1:N── user_holdings ──N:1── stocks
users ──1:N── trading_conditions ──N:1── stocks
trading_conditions ──1:N── condition_triggers (액션/트리거 분리 — v4)
users ──1:N── trading_histories ──N:1── trading_conditions (nullable, 수동매매는 NULL)
stocks ──1:N── news_sentiments (VECTOR(1536))
users ──1:N── ai_investment_reports
trading_conditions(주문 액션) + condition_triggers(발동 조건, N:1)로 분리된 구조로, 가격 감시·손절(Stop-Loss)·
익절(Take-Profit)·트레일링 스탑·AI 호재 점수 조건을 base_type/compare_type/is_rate 조합 하나로 표현합니다.
execution_mode(AUTO 완전자동 / MANUAL 반자동 승인 제안)와 is_persistent(1회성/반복 감시)도 지원합니다.
| 영역 | 상태 | 비고 |
|---|---|---|
| DB 설계 및 구축 | ✅ | MySQL 9 + VECTOR(1536), ddl-auto: none 수동 관리 |
| OAuth 로그인 + JWT 인증 | ✅ | Kakao 구현 완료 (Google은 미구현·명시적 차단) |
| KIS 실시간 시세 수집 | ✅ | WebSocket 구독, 끊김 감지 헬스체크 + 재연결, 장마감 시간대 재연결 억제 |
| 장 시작 시세 예열 | ✅ | 09:00 KST 감시 종목 REST 스냅샷 예열 스케줄러 |
| 네이버 뉴스 수집 | ✅ | 5분 주기 스케줄러 → RabbitMQ 발행 |
| Redis 캐싱 계층 | ✅ | 시세/토큰/락/레이트리미터 |
| RabbitMQ 메시지 큐 | ✅ | 뉴스 분석 큐 + 리포트 생성 큐 |
| AI 감성 분석 + 임베딩 | ✅ | OpenAI 감성 0~100점 + 1536차원 임베딩 |
| 조건 매칭 엔진 + 자동매매 | ✅ | 가격/손절/익절/트레일링 스탑/AI 점수, AND·OR 결합, AUTO/MANUAL 실행모드 |
| 실시간 WebSocket 알림 | ✅ | 체결/실패/제안/리포트 완료 등 이벤트 브로드캐스트 |
| RAG 리포트 생성 | ✅ | 코사인 유사도 Top-10 + GPT 프롬프트 조립, Redis 캐싱(12h) |
| 프론트엔드 (대시보드/조건/포트폴리오/리포트) | ✅ | Next.js App Router 기반 |
자동매매 체결 경로(가격 틱 → 조건 매칭 → 주문 실행 → 정산)를 집중 점검해 실거래에 영향을 줄 수 있는 버그 5건(웹소켓 수신 스레드 블로킹, 동시성 락 TTL 레이스, 인덱스 누락, 트레일링 스탑 검증 누락, AND 단락평가 문제)을 발견·수정하고 회귀 테스트로 고정했습니다. 자세한 내용은 docs/incident-trading-engine-blocking.md 참고.
- KIS 모의투자 계좌는 모든 유저가 공유하는 단일 계좌입니다. 실제 잔고/보유량은 우리 DB(Wallet/Holding)가 기준이며, KIS는 주문이 현실적으로 체결 가능한지 검증하는 시뮬레이터 역할만 합니다.
- 장중 시간 판정(
KisMarketHours)은 주말만 제외하며 공휴일 캘린더는 아직 반영하지 않았습니다.
| Key | TTL | 용도 |
|---|---|---|
price:{stockCode}:current |
3분 | 실시간 체결가 (KIS Websocket → SET, 갱신 끊기면 REST 폴백) |
price:{stockCode}:changeRate |
24시간 | 전일대비 등락률 |
report:{stockCode}:text |
12시간 | AI 리포트 캐시 |
auth:{userId}:refreshToken |
14일 | JWT Refresh Token |
auth:{jti}:blacklist |
Access Token 잔여시간 | 로그아웃 블랙리스트 |
kis:auth:accessToken |
5시간 50분 | KIS Access Token (인메모리 캐시 병행) |
kis:auth:approvalKey |
5시간 50분 | KIS WebSocket 접속키 (인메모리 캐시 병행) |
rate:order:lock:{userId}:{stockCode} |
10초 | 자동매매 주문 동시성 락 (KIS 주문 최악 대기시간 8초보다 넉넉하게) |
rate:report:refresh:{stockCode} |
30초 | AI 리포트 중복 새로고침 방지 |
rate:condition:retryCount:{conditionId} |
5분 | 조건별 체결 실패 누적 횟수 |
rate:condition:backoff:{conditionId} |
10초 | 조건별 재시도 백오프 |
rate:kis:global:orderCount:{epochSecond} |
2초 | KIS 호출 레이트리미터 |
ws:session:{userId} |
- | (확장 포인트, 현재는 로컬 메모리 세션 맵 사용) |
docker compose up -d
# MySQL 9.0 (3306) + Redis (6379) + RabbitMQ (5672, 15672)# server/.env
OPENAI_API_KEY=sk-...
KIS_APP_KEY=...
KIS_APP_SECRET=...
KIS_ACCOUNT_NO=...
NAVER_CLIENT_ID=...
NAVER_CLIENT_SECRET=...
KAKAO_CLIENT_ID=...cd server
./gradlew bootRuncd front
npm install
npm run devcd server
./gradlew test # 전체 단위 테스트
./gradlew test --tests "com.example.invest_ai.domain.ConditionMatchingEngineTest" # 자동매매 엔진
./gradlew test --tests "com.example.invest_ai.kis.KisApiTest" # KIS 실계좌 통합 테스트(.env 필요)| Method | Path | Auth | 설명 |
|---|---|---|---|
| POST | /api/v1/auth/login |
❌ | OAuth 로그인 + JWT 발급 |
| POST | /api/v1/auth/refresh |
쿠키 | Access Token 재발급 |
| POST | /api/v1/auth/logout |
✅ | 로그아웃 |
| GET | /api/v1/assets |
✅ | 지갑+보유종목 종합 조회 |
| POST | /api/v1/assets/orders |
✅ | 수동 매매 주문 |
| GET | /api/v1/assets/histories |
✅ | 매매 체결 이력 조회 |
| POST | /api/v1/conditions |
✅ | 자동 매매 조건 등록 |
| GET | /api/v1/conditions |
✅ | 조건 목록 조회 |
| PATCH | /api/v1/conditions/{id}/active |
✅ | 조건 감시 ON/OFF 토글 |
| PUT | /api/v1/conditions/{id} |
✅ | 조건 수정 (액션+트리거 전체 교체) |
| DELETE | /api/v1/conditions/{id} |
✅ | 조건 삭제 |
| GET | /api/v1/reports/stocks/{code} |
✅ | 최신 AI 리포트 조회 |
| POST | /api/v1/reports/stocks/{code}/refresh |
✅ | 리포트 재생성 요청 |
| GET | /api/v1/news/ticker |
✅ | 대시보드 뉴스 티커 |
| GET | /api/v1/stocks |
✅ | 모니터링 종목 + 현재가 + 등락률 |
| GET | /api/v1/charts/{code}/daily |
✅ | 일봉/주봉/월봉 차트 |
| GET | /api/v1/charts/{code}/minute |
✅ | 분봉 차트 |
| WS | /ws |
✅ (쿼리 토큰) | 실시간 시세/체결/알림 구독 |
- 시세 수집: REST polling ❌ → KIS WebSocket 구독(push) ✅ (API 호출 제한 회피, 저지연)
- 조건 매칭 모델: 조건(액션) + 트리거(발동조건) 1:N 분리 ✅ — 가격/손절/익절/트레일링/AI 점수를 하나의 스키마로 통합 표현
- 조건 매칭 처리: 가격 이벤트/뉴스 이벤트를 수신 스레드에서 동기 처리 ❌ → 전용 스레드풀 +
@Async✅ (KIS 웹소켓·RabbitMQ 리스너 스레드가 주문 응답을 기다리며 블로킹되는 것을 방지) - KIS 인증: 매 호출마다 Redis 조회 → 인메모리 캐시 우선 조회 + Redis 폴백 ✅
- Vector DB: Chroma/Pinecone ❌ → MySQL VECTOR(1536) ✅ (단일화, 운영 단순화)
- 뉴스 데이터: 뉴스 본문 크롤링 ❌ → 네이버 API 요약(description) ✅ (IP 차단 리스크 회피)
- 자산 구조: 단일
user_assets❌ → Wallet + Holding 분리 ✅ (FK 정합성, 쿼리 단순화) - 주문 상태:
has_triggeredboolean ❌ → PENDING/FILLED/FAILED ✅ (재시도 가능) - 에러 처리: DB 제약조건명 기반 CustomException 1:1 매핑 ✅ (예외 추적 용이)
docs/ 디렉토리에서 모든 상세 문서를 확인할 수 있습니다:
| 문서 | 설명 |
|---|---|
| clinerules.md | AI Agent 개발 지침서 |
| database.md | DB 테이블 설계 + DDL |
| workflow.md | 전체 워크플로우 + 아키텍처 |
| kisflow.md | KIS API 인증/시세 플로우 |
| redisflow.md | Redis Key 설계 |
| api.md | API 명세서 |
| incident-trading-engine-blocking.md | 자동매매 엔진 장애 기록 (문제→원인→수정→검증) |
