# GoldenAnalysis - MySQL DB 구조 문서 ## 기본 연결 정보 | 항목 | 값 | |------|-----| | DB명 | `stockAnalyzer` | | 사용자 | `stock` / 비밀번호 `analyzer` | | Root 비밀번호 | `rootpassword` | | 포트 | `3306` (호스트 ↔ 컨테이너) | | 문자셋 | `utf8mb4 / utf8mb4_unicode_ci` | | 엔진 | MySQL 8.0 | | JDBC URL (백엔드) | `jdbc:mysql://mysql:3306/stockAnalyzer` | --- ## 전체 테이블 목록 (44개) > **v2 신규 (GoldenChart 전용)**: `gc_chart_workspace`, `gc_chart_slot`, `gc_watchlist`, `gc_holdings`, `gc_indicator_cache` — 5개 추가 | # | 테이블명 | 분류 | 주요 용도 | |---|----------|------|-----------| | 1 | `users` | 인증 | 사용자 계정 | | 2 | `upbit_candles` | 시세 | 업비트 캔들 마스터 | | 3 | `upbit_trades` | 시세 | 업비트 체결 아카이브 | | 4 | `upbit_ingestion_state` | 시세 | 아카이브 인제스트 상태 | | 5 | `upbit_ws_subscription` | 시세 | WebSocket 수집 대상 | | 6 | `analysis_candle_data` | 분석 | 분석 파이프라인용 캔들 | | 7 | `data_update_history` | 분석 | 데이터 수집 이력 | | 8 | `analysis_settings` | 설정 | 분석 전체 설정 | | 9 | `indicator_metadata` | 설정 | 지표 메타 (표시명·범위 등) | | 10 | `indicator_period_setting` | 설정 | 지표별 사용 가능 기간 | | 11 | `indicator_calculation_setting` | 설정 | 지표 계산 시 가격 타입 | | 12 | `user_indicator_settings` | 설정 | 사용자별 지표·색상 설정 | | 13 | `guest_indicator_settings` | 설정 | 비회원 기기별 지표 설정 | | 14 | `user_ui_theme_settings` | 설정 | 사용자 UI 테마 (PC/탭/모바일) | | 15 | `system_settings` | 설정 | 시스템 전역 키-값 설정 | | 16 | `trading_strategy` | 전략 | 매매 전략 파라미터 | | 17 | `strategy_rule` | 전략 | DSL 기반 전략 규칙 | | 18 | `condition_group` | 전략 | 전략 조건 그룹 (중첩 AND/OR) | | 19 | `strategy_condition` | 전략 | 개별 지표 조건 | | 20 | `ma_condition` | 전략 | MA 크로스 조건 | | 21 | `strategy_performance` | 전략 | 백테스트 성과 기록 | | 22 | `crypto_alert` | 알림 | 종목별 알림 설정 | | 23 | `alert_condition` | 알림 | 알림 발동 조건 | | 24 | `alert_notification` | 알림 | 알림 발송 이력 | | 25 | `alert_strategy` | 알림 | 알림에 연결된 전략 규칙 | | 26 | `alert_schedule_config` | 알림 | 알림 실행 스케줄 설정 | | 27 | `fcm_tokens` | 알림 | FCM 푸시 토큰 | | 28 | `crypto_favorites` | 종목 | 즐겨찾기 종목 | | 29 | `crypto_holdings` | 종목 | 보유/관리 종목 목록 | | 30 | `dashboard_snapshot` | 대시보드 | 대시보드 캐시 스냅샷 | | 31 | `stock_price` | 주식 | 주식 OHLCV | | 32 | `stock_indicator` | 주식 | 주식 기술 지표 | | 33 | `stock_flow` | 주식 | 외인/기관 수급 | | 34 | `stock_trend_score` | 주식 | 상승 추세 점수·랭킹 | | 35 | `market_status` | 주식 | 시장 전체 상태 | | 36 | `rising_stock_schedule_config` | 주식 | 상승종목 스캔 스케줄 | | 37 | `chatbot_config` | 챗봇 | 챗봇 설정 | | 38 | `chatbot_message` | 챗봇 | 챗봇 메시지 이력 | | 39 | `chatbot_schedule_log` | 챗봇 | 챗봇 실행 로그 | | 40 | `gc_chart_workspace` | **GoldenChart** | 멀티차트 워크스페이스 (레이아웃·동기화 옵션) | | 41 | `gc_chart_slot` | **GoldenChart** | 슬롯별 차트 설정 (종목·지표·드로잉·스타일 등) | | 42 | `gc_watchlist` | **GoldenChart** | 관심종목 목록 | | 43 | `gc_holdings` | **GoldenChart** | 보유종목 목록 (매입가·수량 포함) | | 44 | `gc_indicator_cache` | **GoldenChart** | Ta4j 지표 계산 결과 캐시 | --- ## 테이블 상세 ### 1. `users` — 사용자 계정 **용도**: 로그인·인증·역할 관리 | 컬럼 | 타입 | 제약 | 설명 | |------|------|------|------| | `id` | BIGINT | PK, AUTO | 사용자 ID | | `username` | VARCHAR(50) | NOT NULL, UNIQUE | 로그인 ID | | `password` | VARCHAR(255) | NOT NULL | BCrypt 해시 | | `email` | VARCHAR(100) | NOT NULL, UNIQUE | 이메일 | | `name` | VARCHAR(50) | | 표시 이름 | | `enabled` | BOOLEAN | NOT NULL | 계정 활성 여부 | | `role` | VARCHAR(20) | NOT NULL | ROLE_USER / ROLE_ADMIN | | `created_at` | DATETIME | | 생성일 | | `updated_at` | DATETIME | | 수정일 | | `last_login_at` | DATETIME | | 최근 로그인 | **인덱스**: `idx_user_username`(unique), `idx_user_email`(unique) --- ### 2. `upbit_candles` — 업비트 캔들 데이터 **용도**: 업비트 시세 마스터. REST API / WebSocket / Python 서비스가 UPSERT. 지표 계산·차트·알림 모두 이 테이블을 기반으로 조회. | 컬럼 | 타입 | 제약 | 설명 | |------|------|------|------| | `id` | BIGINT | PK, AUTO | | | `market` | VARCHAR(50) | NOT NULL | KRW-BTC 형식 | | `candle_type` | VARCHAR(20) | NOT NULL | minutes / days / weeks / months | | `unit` | INT | | 분봉 단위 (1,3,5,10,15,30,60,240) | | `candle_date_time_utc` | DATETIME | NOT NULL | UTC 기준 봉 시각 | | `candle_date_time_kst` | DATETIME | NOT NULL | KST 기준 봉 시각 | | `opening_price` | DECIMAL(30,8) | NOT NULL | 시가 | | `high_price` | DECIMAL(30,8) | NOT NULL | 고가 | | `low_price` | DECIMAL(30,8) | NOT NULL | 저가 | | `trade_price` | DECIMAL(30,8) | NOT NULL | 종가 | | `timestamp` | BIGINT | NOT NULL | 밀리초 타임스탬프 | | `candle_acc_trade_price` | DECIMAL(30,8) | | 봉 누적 거래대금 | | `candle_acc_trade_volume` | DECIMAL(30,8) | | 봉 누적 거래량 | | `prev_closing_price` | DECIMAL(30,8) | | 전일 종가 | | `change_price` | DECIMAL(30,8) | | 변동 금액 | | `change_rate` | DECIMAL(20,8) | | 변동률 | | `created_at` | DATETIME | | | | `updated_at` | DATETIME | | | **유니크**: `uk_market_candle` `(market, candle_type, unit, candle_date_time_utc)` **인덱스**: `idx_upbit_candles_lookup_kst` `(market, candle_type, unit, candle_date_time_kst)` > **데이터 보존 정책**: 최근 3일만 유지. 매일 03:00~03:30 자동 삭제 (Java 스케줄러 + Python cleanup 서비스). --- ### 3. `upbit_trades` — 업비트 체결 아카이브 **용도**: 대용량 체결 내역 적재 (Python `upbit_data_service`) | 컬럼 | 타입 | 제약 | 설명 | |------|------|------|------| | `id` | BIGINT | PK, AUTO | | | `market` | VARCHAR(20) | NOT NULL | | | `sequential_id` | BIGINT | NOT NULL | 업비트 순번 | | `trade_timestamp_ms` | BIGINT | | 체결 시각(ms) | | `trade_price` | DECIMAL(30,8) | | 체결가 | | `trade_volume` | DECIMAL(30,8) | | 체결량 | | `ask_bid` | VARCHAR(4) | | ASK / BID | | `trade_date_utc` | VARCHAR(20) | | YYYY-MM-DD | | `source` | VARCHAR(30) | 기본 'archive' | 수집 출처 | | `created_at` | DATETIME | | | **유니크**: `uk_trade` `(market, sequential_id)` --- ### 4. `upbit_ingestion_state` — 아카이브 인제스트 상태 **용도**: ZIP/날짜별 아카이브 적재 진행 상태 추적 (중복 스킵) | 컬럼 | 타입 | 설명 | |------|------|------| | `id` | BIGINT PK | | | `source_key` | VARCHAR | 파일/배치 키 | | `market` | VARCHAR | | | `unit_path` | VARCHAR | 시간봉 경로 | | `target_date` | DATE | | | `file_hash` | VARCHAR | MD5 등 | | `status` | VARCHAR | PENDING/DONE/ERROR | | `last_error` | LONGTEXT | 오류 메시지 | | `created_at` / `updated_at` | DATETIME | | **유니크**: `uk_ingest` `(source_key, market, unit_path, target_date)` --- ### 5. `upbit_ws_subscription` — WebSocket 수집 대상 **용도**: Python WebSocket 서비스가 `is_active=1` 행을 읽어 수집할 종목·시간봉을 결정. 백엔드 API로 `acquire/release` 관리. | 컬럼 | 타입 | 설명 | |------|------|------| | `id` | BIGINT PK | | | `market` | VARCHAR | KRW-BTC 등 | | `interval_code` | VARCHAR | 1m / 5m / 1h 등 | | `is_active` | BOOLEAN | 수집 활성 여부 | | `ref_count` | INT | 참조 카운트 | | `created_at` / `updated_at` | DATETIME | | **유니크**: `uk_ws` `(market, interval_code)` --- ### 6. `analysis_candle_data` — 분석용 캔들 **용도**: 분석 파이프라인·대시보드용 캔들 저장소 (백엔드 native upsert 지원) `upbit_candles`와 구조 유사하나 `time_unit`(1m/5m/1d 등 문자열) 컬럼 사용. **유니크**: `uk_market_time_unit_date` `(market, time_unit, candle_date_time_kst)` **인덱스**: `idx_market`, `idx_market_time_unit_date` --- ### 7. `data_update_history` — 데이터 수집 이력 **용도**: 파일별 수집 진행 상태 이력 | 컬럼 | 타입 | 설명 | |------|------|------| | `id` | BIGINT PK | | | `file_path` | VARCHAR | UNIQUE | | `file_name` | VARCHAR | | | `market` | VARCHAR | | | `time_unit` | VARCHAR | | | `data_date` | DATE | | | `year` | INT | | | `record_count` | INT | | | `file_size` | BIGINT | | | `status` | ENUM | PENDING/PROCESSING/DONE/ERROR | | `error_message` | TEXT | | | `processed_at` | DATETIME | | | `processing_duration_ms` | BIGINT | | | `created_at` | DATETIME | | --- ### 8. `analysis_settings` — 분석 설정 **용도**: 분석 관련 전체 설정을 key-value로 저장 | 컬럼 | 설명 | |------|------| | `setting_key` | UNIQUE, 설정 키 | | `setting_value` | TEXT, 설정 값 | | `setting_type` | ENUM (STRING/NUMBER/BOOLEAN/JSON) | | `category` | ENUM (분류) | | `is_active` | 활성 여부 | --- ### 9. `indicator_metadata` — 지표 메타정보 **용도**: 전략 조건 UI에서 지표 표시명·허용 범위·허용 조건타입 정의 | 컬럼 | 설명 | |------|------| | `indicator_type` | UNIQUE, 지표 코드 (RSI/MACD/CCI…) | | `display_name` | 화면 표시명 | | `category` | 분류 | | `description` | 설명 | | `min_value` / `max_value` / `default_value` / `step` | 범위 | | `target_value_required` | 목표값 필요 여부 | | `helper_text` | 입력 도움말 | | `allowed_conditions` | 사용 가능한 조건 타입 목록 | | `display_order` | 정렬 순서 | | `enabled` | 활성 여부 | --- ### 10. `indicator_period_setting` — 지표 기간 설정 **용도**: 각 지표별 선택 가능한 기간 목록 (기본값 포함) **유니크**: `(indicator_type, period)` --- ### 11. `indicator_calculation_setting` — 지표 계산 가격 타입 **용도**: MACD·RSI·볼린저 등의 계산 시 종가/시가/고가/중간값 중 어느 가격을 쓸지 설정 **유니크**: `indicator_type` 주요 컬럼: `price_type`(enum `MAPriceType`), `enabled` --- ### 12. `user_indicator_settings` — 사용자 지표 설정 **용도**: 로그인 사용자의 지표 표시 여부·기간·차트 색상 설정 저장 **유니크**: `user_id` | 컬럼 | 설명 | |------|------| | `user_id` | UNIQUE | | `settings` | JSON 문자열 (지표 on/off) | | `indicator_periods` | JSON 문자열 (기간 설정) | | `chart_color_settings` | JSON 문자열 (색상 설정) | | `created_at` / `updated_at` | | --- ### 13. `guest_indicator_settings` — 비회원 지표 설정 **용도**: 비로그인 사용자를 기기ID로 식별하여 설정 저장 **유니크**: `device_id` `user_indicator_settings`와 동일 구조 (user_id 대신 device_id 사용) --- ### 14. `user_ui_theme_settings` — UI 테마 설정 **용도**: 사용자별 PC/태블릿/모바일 테마 ID 저장 **유니크**: `user_id` | 컬럼 | 설명 | |------|------| | `user_id` | UNIQUE | | `pc_theme` | PC 테마 ID | | `tablet_theme` | 태블릿 테마 ID | | `mobile_theme` | 모바일 테마 ID | --- ### 15. `system_settings` — 시스템 설정 **용도**: 시스템 전역 키-값 설정 **유니크**: `setting_key` 주요 컬럼: `setting_key`, `setting_value`(500), `description` --- ### 16. `trading_strategy` — 매매 전략 파라미터 **용도**: 백테스트·신호 분석에 사용하는 지표 임계값·가중치 등 파라미터 집합. 전략 유형(`strategy_type`)에 따라 컬럼 활용 방식이 달라짐. **주요 컬럼** | 컬럼 그룹 | 설명 | |-----------|------| | `name`, `strategy_type`, `description`, `enabled` | 기본 정보 | | `stochastic_*`, `cci_*`, `macd_*` | 지표별 임계값·가중치 | | `grenvil_*`, `obv_*`, `volume_multiplier` | 신호 필터 | | `int_buy_condition`, `int_sell_condition` | `INTEGRATED` 타입 조건 문자열 | | `min_signal_score`, `composite_*` | `COMPOSITE` 타입 가중치 | | `int_ma_*`, `int_macd_*`, `int_stoch_*` 등 | 통합 지표 on/off·기간 | --- ### 17. `strategy_rule` — DSL 전략 규칙 **용도**: 조건 그룹 트리 + DSL JSON으로 매수/매도 규칙을 정의 **관계**: `@OneToMany` → `condition_group`, `ma_condition` (cascade ALL, orphanRemoval) | 컬럼 그룹 | 설명 | |-----------|------| | `name`, `signal_type`(BUY/SELL), `trend_type`, `enabled` | 기본 정보 | | `dsl_json` | JSON 타입 — UI에서 직접 편집된 DSL | | `strategy_type`, `created_by_ui`, `use_fsm` | DSL 타입 메타 | | `inter_group_operator_buy/sell` | 그룹 간 AND/OR | | MA·일목·거래량 필터 다수 | 추가 필터 조건 | --- ### 18. `condition_group` — 전략 조건 그룹 **용도**: 중첩 AND/OR 트리 구조로 전략 조건을 그룹핑 **관계**: `@ManyToOne` → `strategy_rule`(NOT NULL), self-join `parent_group_id`(nullable) `@OneToMany` → `strategy_condition` | 컬럼 | 설명 | |------|------| | `strategy_rule_id` | FK → strategy_rule | | `parent_group_id` | 자기참조 (nullable) | | `logical_operator` | AND / OR | | `group_type` | BUY / SELL | | `order_index` | 정렬 | --- ### 19. `strategy_condition` — 개별 지표 조건 **용도**: 각 그룹 내 단일 지표 조건 (RSI > 70, MACD 크로스 등) **관계**: `@ManyToOne` → `condition_group`(NOT NULL) | 컬럼 | 설명 | |------|------| | `condition_group_id` | FK | | `indicator_type` | RSI / MACD / CCI … | | `condition_type` | ABOVE / BELOW / CROSS_UP … | | `target_value` | 기준값 | | `secondary_value` | 보조값 | | `period` | 기간 | | `compare_period` | 비교 기간 | | `candle_range` | 캔들 범위 | | `logical_operator` | 이전 조건과의 AND/OR | --- ### 20. `ma_condition` — MA 크로스 조건 **용도**: 전략 규칙의 이동평균 크로스 매수/매도 조건 **관계**: `@ManyToOne` → `strategy_rule`(NOT NULL) | 컬럼 | 설명 | |------|------| | `strategy_rule_id` | FK | | `signal_type` | BUY / SELL | | `ma_short_period` | 단기 MA 기간 | | `ma_long_period` | 장기 MA 기간 | | `ma_cross_type` | GOLDEN_CROSS / DEAD_CROSS 등 | | `logical_operator` | AND / OR | --- ### 21. `strategy_performance` — 백테스트 성과 **용도**: 전략별 백테스트 결과 누적 기록 | 컬럼 그룹 | 설명 | |-----------|------| | `strategy_id`, `strategy_name`, `strategy_type` | 전략 참조 (논리적 FK) | | `market`, `time_unit` | 테스트 대상 | | `analysis_period_start/end` | 테스트 기간 | | `initial_capital`, `final_capital`, `total_return`, `return_rate` | 수익 지표 | | `total_trades`, `winning_trades`, `win_rate` | 거래 통계 | | `max_drawdown`, `sharpe_ratio` | 위험 지표 | | `analysis_date` | 분석 날짜 | --- ### 22. `crypto_alert` — 종목 알림 설정 **용도**: 사용자가 특정 종목에 대해 설정한 알림 (연결 조건 포함) **관계**: `@OneToMany` → `alert_condition` (cascade ALL, orphanRemoval) | 컬럼 | 설명 | |------|------| | `symbol` | KRW-BTC 등 | | `korean_name` / `english_name` | 종목명 | | `enabled` | 활성 여부 | | `user_id` | 사용자 참조 (논리적 FK) | | `strategy_rule_id` | 연결된 전략 규칙 (nullable) | --- ### 23. `alert_condition` — 알림 조건 **용도**: 알림 발동 조건 (지표값·임계값 등). 전역 조건(`is_global=true`) 지원. **관계**: `@ManyToOne` → `crypto_alert` (nullable) | 컬럼 | 설명 | |------|------| | `crypto_alert_id` | FK (nullable) | | `is_global` | 전역 조건 여부 | | `indicator_type` | 지표 종류 | | `condition_type` | 조건 타입 | | `target_value` | 기준값 | | `period` | 기간 | --- ### 24. `alert_notification` — 알림 발송 이력 **용도**: 알림 발동 기록·읽음 상태 **관계**: `@ManyToOne` → `crypto_alert`(NOT NULL) | 컬럼 | 설명 | |------|------| | `crypto_alert_id` | FK | | `message` | TEXT 알림 메시지 | | `condition_description` | 발동 조건 설명 | | `is_read` | 읽음 여부 | | `triggered_at` | 발동 시각 | | `notified_at` | 발송 시각 | | `candle_time` | 발동 캔들 시각 | | `time_interval` | 시간봉 | --- ### 25. `alert_strategy` — 알림 연결 전략 **용도**: 알림 시스템과 전략 규칙 연결 | 컬럼 | 설명 | |------|------| | `strategy_rule_id` | 논리적 FK → strategy_rule | | `enabled` | 활성 여부 | --- ### 26. `alert_schedule_config` — 알림 스케줄 설정 **용도**: 알림 체크 주기·cron 설정 | 컬럼 | 설명 | |------|------| | `user_id` | 사용자별 설정 (nullable = 글로벌) | | `cron_expression` | Cron 표현식 | | `time_interval` | 시간봉 단위 | | `strategy_check_interval_seconds` | 전략 체크 주기(초) | | `enabled` | 활성 여부 | | `last_run_time` / `next_run_time` | 실행 시각 | --- ### 27. `fcm_tokens` — FCM 푸시 토큰 **용도**: Firebase Cloud Messaging 토큰 관리 **유니크**: `token` | 컬럼 | 설명 | |------|------| | `token` | FCM 토큰 (UNIQUE) | | `user_id` | 사용자 ID (논리적 FK) | | `device_id` | 기기 식별자 | | `active` | 활성 여부 | | `last_used_at` | 최근 사용 시각 | --- ### 28. `crypto_favorites` — 즐겨찾기 종목 **용도**: 드롭다운 목록에서 즐겨찾기로 표시할 종목 **유니크**: `symbol` | 컬럼 | 설명 | |------|------| | `symbol` | KRW-BTC 등 (UNIQUE) | | `korean_name` / `english_name` | 종목명 | | `display_order` | 정렬 순서 | | `created_at` | | --- ### 29. `crypto_holdings` — 보유/관리 종목 **용도**: 모니터링 대상으로 등록한 종목 **유니크**: `symbol` 구조는 `crypto_favorites`와 동일 --- ### 30. `dashboard_snapshot` — 대시보드 스냅샷 **용도**: 대시보드 전체 데이터를 JSON으로 캐시 (단일 행, PK=1) | 컬럼 | 설명 | |------|------| | `id` | 고정 1 | | `summary_json` | MEDIUMTEXT, 요약 JSON | | `market_data_status_json` | MEDIUMTEXT, 시장 상태 JSON | | `computed_at` | 생성 시각 | --- ### 31~36. 주식 관련 테이블 > 업비트 암호화폐와 별도로 국내 주식 데이터 분석용 | 테이블 | 용도 | 주요 컬럼 | |--------|------|-----------| | `stock_price` | 주식 OHLCV | `code`, `date`, OHLCV, `high_120d` | | `stock_indicator` | 기술지표 | `code`(UNIQUE), MA/RSI/MACD/ADX/BB | | `stock_flow` | 수급 | `code`(UNIQUE), 외인·기관·프로그램 순매수, 체결강도 | | `stock_trend_score` | 추세 점수 | `code`(UNIQUE), 점수·랭킹·매수신호·강도 | | `market_status` | 시장 전체 | `market_type`(UNIQUE), 지수·VIX·매수가능 여부 | | `rising_stock_schedule_config` | 스캔 스케줄 | `scan_interval`, `max_results`, `enabled` | --- ### 37. `chatbot_config` — 챗봇 설정 **용도**: 사용자별 챗봇 동작 설정 (대상 종목·분석 조건·알림 설정) | 컬럼 | 설명 | |------|------| | `user_id` | 사용자 | | `enabled` | 활성 여부 | | `schedule_interval` | 실행 주기 | | `target_symbols` | TEXT, 대상 종목 JSON | | `candle_interval` | 분석 시간봉 | | `strategy_conditions` | TEXT, 전략 조건 JSON | | `notification_settings` | TEXT, 알림 설정 JSON | --- ### 38. `chatbot_message` — 챗봇 메시지 이력 **용도**: 챗봇이 생성한 분석 메시지 저장 | 컬럼 | 설명 | |------|------| | `config_id` | 챗봇 설정 ID (논리적 FK) | | `symbol` / `symbol_name` | 종목 | | `message_type` | 메시지 유형 | | `title` / `content` | TEXT 내용 | | `analysis_data` | 분석 원본 데이터 | | `price` | 분석 시점 가격 | | `indicators` | 지표값 JSON | | `read_status` | 읽음 여부 | --- ### 39. `chatbot_schedule_log` — 챗봇 실행 로그 **용도**: 챗봇 스케줄 실행 이력·성능 추적 | 컬럼 | 설명 | |------|------| | `config_id` | 챗봇 설정 ID (논리적 FK) | | `execution_time` | 실행 시각 | | `symbols_processed` | 처리 종목 수 | | `messages_generated` | 생성 메시지 수 | | `errors` | TEXT, 오류 내용 | | `duration_ms` | 소요 시간 | | `status` | SUCCESS / ERROR | --- ## 테이블 간 관계 (ERD 요약) ``` users (1) ───────────────────────────────────────────────────────────── │ ├── (논리) user_indicator_settings.user_id (1:1) │ ├── (논리) guest_indicator_settings.device_id (기기 구분) │ ├── (논리) user_ui_theme_settings.user_id (1:1) │ ├── (논리) crypto_alert.user_id │ ├── (논리) alert_schedule_config.user_id │ ├── (논리) fcm_tokens.user_id │ └── (논리) chatbot_config.user_id strategy_rule (1) ─┬── (JPA) condition_group (*) ─── strategy_condition (*) ├── (JPA) ma_condition (*) └── (논리) alert_strategy.strategy_rule_id condition_group ── 자기참조 (parent_group_id, 중첩 AND/OR 트리) crypto_alert (1) ─┬── (JPA) alert_condition (*) └── (JPA) alert_notification (*) trading_strategy ─── (논리) strategy_performance.strategy_id upbit_candles ─── 지표 계산의 입력 원본 ├── IndicatorCalculationService ├── BacktestService ├── AlertSchedulerService └── Python upbit_data_service / upbit_websock_data_service (WRITE) ``` > **(논리)**: JPA `@ManyToOne` 없이 ID 값으로만 연결 (FK 제약 없음) > **(JPA)**: `@ManyToOne` / `@OneToMany` 실제 ORM 연관 존재 --- ## Frontend ↔ Backend ↔ DB 연결 매핑 | 프론트 서비스 파일 | API 경로 | 관련 테이블 | |------------------|----------|------------| | `authApi.ts` | `/api/auth/*` | `users` | | `cryptoFavoriteApi.ts` | `/api/favorites/*` | `crypto_favorites` | | `cryptoHoldingApi.ts` | `/api/holdings/*` | `crypto_holdings` | | `alertApi.ts` | `/api/alerts/*` | `crypto_alert`, `alert_condition`, `alert_notification` | | `alertStrategyApi.ts` | `/api/alert-strategies` | `alert_strategy` | | `strategyRuleApi.ts` | `/api/strategy-rules/*` | `strategy_rule`, `condition_group`, `strategy_condition`, `ma_condition` | | `tradingStrategyApi.ts` | `/api/strategies/*` | `trading_strategy` | | `backtestApi.ts` | `/api/backtest/*` | `trading_strategy`, `upbit_candles` | | `dashboardApi.ts` | `/api/dashboard/*` | `dashboard_snapshot`, `strategy_performance` | | `settingsApi.ts` | `/api/settings/*` | `analysis_settings` | | `indicatorSettingsApi.ts` | `/api/user/settings/*` | `user_indicator_settings`, `guest_indicator_settings` | | `upbitApi.ts` `getCurrentPrice` | `/api/upbit/ticker` | (업비트 외부 API) | | `upbitApi.ts` `analyzeMacd` | `/api/upbit/analyze` | `upbit_candles` → 지표 계산 | | `upbitWsSubscriptionApi.ts` | `/api/upbit/ws-subscriptions/*` | `upbit_ws_subscription` | | `upbitDbStatusApi.ts` | `/api/upbit/db-status` | `upbit_candles` 통계 | | `dataCollectionApi.ts` | `/api/data-collection/*` | `data_update_history`, `upbit_ingestion_state`, `upbit_trades` | | `chatbotApi.ts` | `/api/chatbot/*` | `chatbot_config`, `chatbot_message`, `chatbot_schedule_log` | | `risingStockApi.ts` | `/api/rising-stocks/*` | `stock_trend_score`, `market_status`, `rising_stock_schedule_config` | | `CryptoNameComboBox` | `/api/upbit/ticker`, `/api/crypto/list` | `crypto_holdings` (목록), 외부 API (시세) | --- ## Python 서비스 → DB 쓰기 매핑 | 서비스 | 파일 | 테이블 | 작업 | |--------|------|--------|------| | `upbit_data_service` | `db_upsert.py` | `upbit_candles` | INSERT ON DUPLICATE KEY UPDATE | | `upbit_data_service` | `db_upsert.py` | `upbit_trades` | INSERT ON DUPLICATE KEY UPDATE | | `upbit_data_service` | `db_upsert.py` | `upbit_ingestion_state` | SELECT + INSERT UPSERT | | `upbit_data_service` | `data_cleanup.py` | `upbit_candles` | DELETE (3일 이전), OPTIMIZE TABLE | | `upbit_websock_data_service` | `db_upsert.py` | `upbit_candles` | WebSocket 수신 시 upsert (고저가 GREATEST/LEAST) | | `upbit_websock_data_service` | `db_upsert.py` | `upbit_ws_subscription` | SELECT (is_active=1 구독 목록 읽기) | --- ## 데이터 보존 정책 | 테이블 | 보존 기간 | 삭제 방식 | |--------|-----------|-----------| | `upbit_candles` | **3일** | Java `CandleDataSyncScheduler` 매일 03:30 배치 삭제
Python `upbit-data-cleanup` 서비스 매일 03:00 배치 삭제 | | `alert_notification` | 무제한 | 수동 관리 | | `chatbot_message` | 설정가능 | `ChatbotMessageRepository.deleteOldMessages()` | | `chatbot_schedule_log` | 설정가능 | `ChatbotScheduleLogRepository.deleteOldLogs()` | | `stock_trend_score` | 최신 유지 | `StockTrendScoreRepository` bulk UPDATE | | binlog | **1일** | `binlog_expire_logs_seconds=86400` (MySQL 설정) | --- --- ## GoldenChart 전용 테이블 상세 (v2 신규) ### 40. `gc_chart_workspace` — 멀티차트 워크스페이스 **용도**: 사용자(또는 기기)별 차트 워크스페이스 상태 저장. 레이아웃 ID 및 동기화 옵션을 관리. **관계**: `@OneToMany` → `gc_chart_slot` (cascade ALL, orphanRemoval) | 컬럼 | 타입 | 설명 | |------|------|------| | `id` | BIGINT PK | | | `user_id` | BIGINT | `users.id` 논리 참조 (로그인 사용자) | | `device_id` | VARCHAR(100) | 비회원 기기 식별자 | | `layout_id` | VARCHAR(20) NOT NULL | 레이아웃 코드 (1x1 / 2x1 / 1x2 / 2x2 / 3x1 등) | | `sync_options_json` | JSON | 차트 간 동기화 옵션 `{symbol, timeframe, crosshair}` | | `created_at` / `updated_at` | DATETIME | | **인덱스**: `idx_gc_ws_user(user_id)`, `idx_gc_ws_device(device_id)` --- ### 41. `gc_chart_slot` — 슬롯별 차트 설정 **용도**: 멀티차트 레이아웃의 각 슬롯에 대한 모든 설정값 저장. **관계**: `@ManyToOne` → `gc_chart_workspace` (FK, CASCADE DELETE) | 컬럼 | 타입 | 설명 | |------|------|------| | `id` | BIGINT PK | | | `workspace_id` | BIGINT NOT NULL | FK → `gc_chart_workspace` | | `slot_index` | INT NOT NULL | 슬롯 인덱스 (0-based) | | `symbol` | VARCHAR(50) | 종목 코드 (`KRW-BTC`, `AAPL` 등) | | `timeframe` | VARCHAR(10) | 타임프레임 (1m/5m/15m/30m/1h/4h/1D/1W/1M) | | `chart_type` | VARCHAR(20) | candlestick / bar / line / area / baseline | | `theme` | VARCHAR(20) | dark / light / blue | | `mode` | VARCHAR(20) | chart / trading | | `log_scale` | TINYINT(1) | 로그 스케일 여부 | | `indicators_json` | JSON | `IndicatorConfig[]` — 보조지표 설정 배열 | | `drawings_json` | JSON | `Drawing[]` — 드로잉 객체 배열 (fibtzSettings 포함) | | `drawings_locked` | TINYINT(1) | 드로잉 잠금 여부 | | `drawings_visible` | TINYINT(1) | 드로잉 표시 여부 | | `pane_layout_json` | JSON | 보조지표 창 높이 배열 `[{paneIndex, height}]` | | `main_chart_style_json` | JSON | 캔들 색상 등 메인 차트 스타일 | | `created_at` / `updated_at` | DATETIME | | **유니크**: `uk_slot_workspace_index(workspace_id, slot_index)` > **indicators_json 구조** (frontend `IndicatorConfig[]` 동일): > ```json > [ > { "id": "EMA_1", "type": "EMA", "params": {"length":21,"src":"close"}, > "hidden": false, "plotVisibility": {} } > ] > ``` > **drawings_json 구조** (frontend `Drawing[]` 동일): > ```json > [ > { "id": "uuid", "type": "fibtz", "points": [{"time":1700000000,"price":50000},...], > "color": "#2196F3", "lineWidth": 1, "style": "dashed", > "fibtzSettings": {"baseline":{...}, "levels":[...]} } > ] > ``` --- ### 42. `gc_watchlist` — 관심종목 **용도**: GoldenChart 관심종목 목록 (기존 `crypto_favorites` 와 별도 관리). | 컬럼 | 타입 | 설명 | |------|------|------| | `id` | BIGINT PK | | | `user_id` | BIGINT | 로그인 사용자 (nullable) | | `device_id` | VARCHAR(100) | 비회원 기기 ID (nullable) | | `symbol` | VARCHAR(50) NOT NULL | 종목 코드 | | `korean_name` / `english_name` | VARCHAR(100) | 종목명 | | `display_order` | INT | 표시 순서 | | `created_at` | DATETIME | | **유니크**: `uk_watchlist_user_symbol(user_id, symbol)`, `uk_watchlist_device_symbol(device_id, symbol)` --- ### 43. `gc_holdings` — 보유종목 **용도**: GoldenChart 보유종목 목록. 평균 매입가·수량 포함. | 컬럼 | 타입 | 설명 | |------|------|------| | `id` | BIGINT PK | | | `user_id` | BIGINT | 로그인 사용자 (nullable) | | `device_id` | VARCHAR(100) | 비회원 기기 ID (nullable) | | `symbol` | VARCHAR(50) NOT NULL | 종목 코드 | | `korean_name` / `english_name` | VARCHAR(100) | 종목명 | | `avg_price` | DECIMAL(30,8) | 평균 매입가 | | `quantity` | DECIMAL(30,8) | 보유 수량 | | `display_order` | INT | 표시 순서 | | `created_at` / `updated_at` | DATETIME | | **유니크**: `uk_holdings_user_symbol(user_id, symbol)`, `uk_holdings_device_symbol(device_id, symbol)` --- ### 44. `gc_indicator_cache` — 지표 계산 결과 캐시 **용도**: Ta4j 지표 계산 결과를 캐시하여 동일 요청 반복 계산 방지. | 컬럼 | 타입 | 설명 | |------|------|------| | `id` | BIGINT PK | | | `cache_key` | VARCHAR(200) UNIQUE | `symbol:timeframe:type:params_hash` | | `symbol` | VARCHAR(50) | 종목 코드 | | `timeframe` | VARCHAR(10) | 타임프레임 | | `indicator_type` | VARCHAR(50) | 지표 타입 (RSI, MACD 등) | | `params_json` | JSON | 계산 파라미터 | | `result_json` | MEDIUMTEXT | `IndicatorResponse` JSON | | `bar_count` | INT | 계산에 사용된 캔들 수 | | `last_bar_time` | BIGINT | 마지막 캔들 Unix 타임스탬프(초) | | `computed_at` | DATETIME | 계산 시각 | | `expired_at` | DATETIME | 만료 시각 (NULL = 영구) | --- ## GoldenChart Frontend ↔ Backend ↔ DB 연결 매핑 | 프론트 모듈 | API 경로 | 관련 테이블 | |-------------|----------|------------| | `backendApi.loadWorkspace()` | `GET /api/chart/workspace` | `gc_chart_workspace`, `gc_chart_slot` | | `backendApi.saveWorkspace()` | `POST /api/chart/workspace` | `gc_chart_workspace`, `gc_chart_slot` | | `backendApi.saveSlot()` | `PUT /api/chart/slot/{idx}` | `gc_chart_slot` | | `backendApi.loadWatchlist()` | `GET /api/watchlist` | `gc_watchlist` | | `backendApi.addWatchlistItem()` | `POST /api/watchlist` | `gc_watchlist` | | `backendApi.loadHoldings()` | `GET /api/holdings` | `gc_holdings` | | `backendApi.upsertHoldingsItem()` | `POST /api/holdings` | `gc_holdings` | | `backendApi.calculateIndicator()` | `POST /api/indicators/calculate` | `gc_indicator_cache` (캐시) | --- ## GoldenChart 프로젝트 구조 ``` goldenChart/ frontend/ ← React + Vite 프론트엔드 src/ utils/backendApi.ts ← 백엔드 API 클라이언트 hooks/useWorkspacePersist.ts ← DB 자동 저장·복원 훅 vite.config.ts ← /api → localhost:8080 프록시 추가 .env.example backend/ ← Spring Boot 백엔드 pom.xml ← Ta4j 0.16, Spring Boot 3.3 src/main/java/com/goldenchart/ GoldenChartApplication.java config/ ← CorsConfig, SecurityConfig entity/ ← GcChartWorkspace, GcChartSlot, GcWatchlist, GcHoldings repository/ ← JPA Repository 인터페이스 service/ ← ChartSettingsService, IndicatorService controller/ ← ChartSettingsController, IndicatorController, WatchlistController dto/ ← OhlcvBar, IndicatorRequest/Response src/main/resources/ application.yml db/migration/V2__create_gc_tables.sql ta4j-master/ ← Ta4j 소스 참조용 db_struct.md ← 이 파일 ``` --- ## 주의사항 1. **JPA FK vs 논리 참조**: `users`, `strategy_rule` 등을 참조하는 컬럼 다수가 JPA `@ManyToOne` 없이 Long ID만 보관하므로 DB 레벨 FK 제약이 없습니다. 참조 무결성은 애플리케이션 로직에 의존합니다. 2. **`trading_strategy` vs `strategy_rule`**: 두 테이블은 서로 다른 전략 관리 체계입니다. `trading_strategy`는 파라미터 기반, `strategy_rule`은 DSL/조건 트리 기반입니다. 3. **`upbit_candles` 인덱스**: `(market, candle_type, unit, candle_date_time_kst)` 복합 인덱스. `candle_date_time_kst` 단독 범위 쿼리는 인덱스 효율이 낮습니다. 4. **`autoTradingApi.ts`**: 프론트에서 `/api/auto-trading/*` 호출하나 현재 백엔드에 해당 컨트롤러 없음 (미구현). 5. **GoldenChart 인증**: `gc_*` 테이블은 `user_id` (로그인) 또는 `device_id` (비회원) 중 하나를 식별자로 사용. 헤더 `x-user-id` / `x-device-id` 로 전달. 6. **GoldenChart 지표 계산**: 프론트엔드는 `lightweight-charts-indicators` 로 차트 렌더링, 백엔드는 `Ta4j 0.16` 으로 동일 지표를 계산하여 전략 판단에 사용. EMA 초기화 방식 차이로 인해 초기 수십 봉은 값이 다를 수 있으므로 `warmup-bars: 200` 설정으로 충분한 워밍업 데이터를 확보해야 한다. 7. **`gc_backtest_result`** (V8 마이그레이션): 백테스팅 실행 이력. `analysis_json` 컬럼에 Ta4j `AnalysisCriterion` 전체 계산 결과(총수익률, 승률, MDD, 샤프비율 등)를 JSON으로 저장. `signals_json` 에는 BUY/SELL 시그널 배열, `settings_json` 에는 실행 당시 설정 스냅샷 보관.