Files
auto-trade/common-docs/features/autotrade-usage-security-guide.md

14 KiB

자동매매 사용/검증/보안 가이드 (3계층 구조)

이 문서는 자동매매를 아래 3개 영역으로 나눠서 설명합니다.

  1. 사용자 브라우저
  2. Next.js 서버(API)
  3. 워커(Node)

프롬프트 입력값이 실제로 어디 함수/어디 API로 흘러가는지 추적하려면 아래 문서를 같이 보세요.

  • common-docs/features/autotrade-prompt-flow-guide.md

1) 한눈에 구조

┌───────────────────────────── 사용자 브라우저 ─────────────────────────────┐
│ /trade 자동매매 UI                                                       │
│  - 설정 입력(전략/투자금/손실한도/임계치)                                │
│  - start/stop/heartbeat/signals 호출                                     │
└───────────────────────────────────────────────────────────────────────────┘
                                   │
                                   ▼
┌──────────────────────────── Next.js 서버 (API) ──────────────────────────┐
│ /api/autotrade/strategies/*                                              │
│ /api/autotrade/sessions/*                                                │
│ /api/autotrade/signals/generate                                          │
│ /api/autotrade/worker/tick                                               │
└───────────────────────────────────────────────────────────────────────────┘
                                   ▲
                                   │ x-autotrade-worker-token
                                   │
┌────────────────────────────── Worker (Node) ─────────────────────────────┐
│ scripts/autotrade-worker.mjs                                              │
│  - 주기적으로 /api/autotrade/worker/tick 호출                            │
│  - heartbeat 만료 세션 정리                                               │
└───────────────────────────────────────────────────────────────────────────┘

1-1) 개발 실행 시 (내 PC 기준)

  1. 브라우저: React 화면 사용
  2. Next 개발 서버(npm run dev): 화면 + API를 함께 처리
  3. 워커(node scripts/autotrade-worker.mjs): tick 호출 담당

즉, 개발에서는 보통 Next 1개 + Worker 1개 프로세스를 실행합니다.

1-2) 운영 배포 시

운영은 보통 아래 2가지 중 하나입니다.

  1. 같은 Linux 서버에 Next + Worker 같이 운영
  2. Next는 배포 플랫폼, Worker는 별도 Linux 서버에서 운영

공통 원칙:

  1. 브라우저는 Next API를 호출
  2. 워커도 Next API(/api/autotrade/worker/tick)를 호출
  3. 워커 인증은 x-autotrade-worker-token으로 처리

2) 레이어별 역할

2-1) 사용자 브라우저

하는 일:

  1. 자동매매 설정 입력
  2. 전략 컴파일/검증 요청
  3. 세션 시작 후 10초마다 heartbeat 전송
  4. 신호 요청 후 주문 가능 여부 판단
  5. 브라우저 종료/외부 이동 시 중지 처리

핵심 소스:

  1. UI: AutotradeControlPanel
  2. 엔진: useAutotradeEngine
  3. heartbeat 루프: useAutotradeEngine
  4. 주문 직전 게이트+주문 호출: useAutotradeEngine

2-2) Next.js 서버(API)

하는 일:

  1. 사용자 인증 검사
  2. 전략 compile/validate 처리
  3. 세션 start/heartbeat/stop/active 관리
  4. AI 호출 실패 시 폴백 전략/신호로 대응
  5. 워커 토큰 인증 후 만료 세션 정리

핵심 소스:

  1. 공통 유틸: _shared.ts
  2. compile: POST /strategies/compile
  3. validate: POST /strategies/validate
  4. sessions: /sessions/start, /sessions/heartbeat, /sessions/stop, /sessions/active
  5. 신호 생성: POST /signals/generate

2-3) 워커(Node)

하는 일:

  1. 주기적으로 Next API /api/autotrade/worker/tick 호출
  2. heartbeat 끊긴 세션을 timeout 종료
  3. 정리 결과 로그 출력

핵심 소스:

  1. 워커 스크립트: autotrade-worker.mjs
  2. 워커 API: POST /worker/tick
  3. 만료 정리 함수: sweepExpiredAutotradeSessions()

3) 가장 헷갈리는 개념 3개

3-1) 폴백 전략(fallback)

뜻:

  1. AI를 못 쓰는 상황에서 쓰는 대체 규칙
  2. 자동매매를 완전 중지하지 않고 보수적으로 유지
  3. 애매하면 hold를 더 자주 반환

관련 소스:

  1. 전략 폴백: createFallbackCompiledStrategy()
  2. 신호 폴백: createFallbackSignalCandidate()
  3. AI 호출: callOpenAiJson()

3-2) heartbeat

뜻:

  1. 브라우저가 Next 서버로 보내는 "세션 살아있음" 신호
  2. 워커가 보내는 신호가 아님

3-3) worker tick

뜻:

  1. 워커가 Next 서버로 보내는 "만료 세션 정리 요청"
  2. heartbeat가 끊긴 세션을 timeout 종료

3-4) 구독형 CLI 자동판단(신규)

뜻:

  1. OpenAI API 키 대신 서버에 설치된 gemini 또는 codex CLI를 호출해 자동판단
  2. 자동판단 결과(JSON)를 파싱해 전략/신호에 반영
  3. CLI 호출 실패 또는 파싱 실패 시 규칙 기반으로 자동 폴백

UI에서 선택:

  1. 자동매매 설정창에서 구독형 CLI 엔진auto/codex/gemini 중 선택
  2. codex 또는 gemini 선택 시 공식 문서 기반 추천 모델 목록을 드롭다운으로 선택
  3. 목록에 없는 최신 모델은 직접 입력으로 설정

모델 우선순위:

  1. UI에서 선택한 모델(있을 때)
  2. AUTOTRADE_CODEX_MODEL / AUTOTRADE_GEMINI_MODEL
  3. AUTOTRADE_SUBSCRIPTION_CLI_MODEL
  4. 각 CLI 기본 모델

환경변수:

AUTOTRADE_AI_MODE=subscription_cli
AUTOTRADE_SUBSCRIPTION_CLI=auto
AUTOTRADE_SUBSCRIPTION_CLI_MODEL=
AUTOTRADE_CODEX_MODEL=
AUTOTRADE_GEMINI_MODEL=
AUTOTRADE_SUBSCRIPTION_CLI_TIMEOUT_MS=60000
AUTOTRADE_SUBSCRIPTION_CLI_DEBUG=0
AUTOTRADE_CODEX_COMMAND=
AUTOTRADE_GEMINI_COMMAND=

동작 우선순위:

  1. AUTOTRADE_SUBSCRIPTION_CLI=auto면 codex -> gemini 순서로 시도
  2. 모델 선택 우선순위는 vendor 전용 모델 -> AUTOTRADE_SUBSCRIPTION_CLI_MODEL -> CLI 기본 모델
  3. 둘 다 실패하면 fallback 규칙 신호 사용
  4. 로그에 attempts=codex:default:timeout가 나오면 CLI 타임아웃이므로 AUTOTRADE_SUBSCRIPTION_CLI_TIMEOUT_MS를 더 크게 설정
  5. 로그에 attempts=codex:gpt-5-codex:error(...)처럼 괄호가 붙으면 실제 실패 원인(stderr/spawn 에러)입니다.

어떤 CLI를 썼는지 확인:

  1. 자동매매 로그에서 신호 수신 [subscription_cli:codex:gpt-5-codex] 또는 신호 수신 [subscription_cli:gemini:flash] 확인
  2. Network 응답에서 providerVendor 확인
    • /api/autotrade/strategies/compile 응답: compiledStrategy.providerVendor
    • /api/autotrade/signals/generate 응답: signal.providerVendor
  3. Network 응답에서 providerModel 확인
    • /api/autotrade/strategies/compile 응답: compiledStrategy.providerModel
    • /api/autotrade/signals/generate 응답: signal.providerModel
  4. 파싱 실패 시 reason/summary에 selected=vendor:model; attempts=... 형태로 시도 결과 포함

selected=none:default; attempts=codex:gpt-5-codex:error(...)가 보이면:

  1. AUTOTRADE_SUBSCRIPTION_CLI_DEBUG=1로 켜고 npm run dev를 재시작합니다.
  2. Next 서버 콘솔에서 [autotrade-cli] 로그를 확인합니다.
  3. spawn:ENOENT가 보이면 AUTOTRADE_CODEX_COMMAND 또는 AUTOTRADE_GEMINI_COMMAND에 CLI 절대경로를 넣습니다.
  4. 예: AUTOTRADE_CODEX_COMMAND=C:\\Users\\<계정>\\AppData\\Roaming\\npm\\codex.cmd

모델 지정 예시:

# Codex만 쓸 때
AUTOTRADE_SUBSCRIPTION_CLI=codex
AUTOTRADE_CODEX_MODEL=gpt-5-codex

# Gemini만 쓸 때
AUTOTRADE_SUBSCRIPTION_CLI=gemini
AUTOTRADE_GEMINI_MODEL=flash

# auto 모드에서 공통 모델 fallback만 쓸 때
AUTOTRADE_SUBSCRIPTION_CLI=auto
AUTOTRADE_SUBSCRIPTION_CLI_MODEL=auto

공식 문서:

  1. Codex CLI 옵션(--model): https://developers.openai.com/codex/cli
  2. OpenAI 모델 목록(gpt-5-codex 포함): https://platform.openai.com/docs/models
  3. Gemini CLI 모델 선택: https://github.com/google-gemini/gemini-cli/blob/main/docs/cli/model.md
  4. Gemini CLI 모델 우선순위(--model > GEMINI_MODEL): https://github.com/google-gemini/gemini-cli/blob/main/docs/cli/model-routing.md

모델 갱신 운영 런북:

  1. 새 모델 출시 대응 절차: autotrade-model-catalog-runbook.md

관련 소스:

  1. CLI 공급자: lib/autotrade/cli-provider.ts
  2. 전략 compile 라우트: /strategies/compile
  3. 신호 generate 라우트: /signals/generate

4) 환경변수: 어디에 넣는지

4-1) 앱(Next.js 서버)

위치:

  1. 로컬: .env.local
  2. 운영: 배포 환경변수

필수:

AUTOTRADE_WORKER_TOKEN=<랜덤시크릿>
OPENAI_API_KEY=<옵션, 없으면 폴백 동작>

4-2) 워커(Node/PM2)

위치:

  1. PM2 실행 셸 환경변수
  2. 서버 시스템 환경변수

필수:

AUTOTRADE_WORKER_TOKEN=<앱과동일값>
AUTOTRADE_APP_URL=<Next서버URL>
AUTOTRADE_WORKER_POLL_MS=5000

중요:

  1. AUTOTRADE_WORKER_TOKEN은 사용자별이 아니라 서비스별 시크릿
  2. 앱과 워커가 같은 값을 써야 인증 통과

5) 실행 순서 (앱/워커 분리)

5-1) 로컬 개발

터미널 A:

npm run dev

터미널 B:

AUTOTRADE_WORKER_TOKEN="<앱과같은값>" \
AUTOTRADE_APP_URL="http://127.0.0.1:3001" \
node scripts/autotrade-worker.mjs

Windows PowerShell:

npm run dev
# 새 터미널
$env:AUTOTRADE_WORKER_TOKEN="<앱과같은값>"
$env:AUTOTRADE_APP_URL="http://127.0.0.1:3001"
$env:AUTOTRADE_WORKER_POLL_MS="5000"
npm run worker:autotrade

또는 .env.local 기반:

npm run worker:autotrade:dev

5-2) 운영(PM2)

export AUTOTRADE_WORKER_TOKEN="<앱과같은값>"
export AUTOTRADE_APP_URL="https://your-domain.com"
export AUTOTRADE_WORKER_POLL_MS="5000"
pm2 start scripts/pm2.autotrade-worker.config.cjs
pm2 logs autotrade-worker

6) end-to-end 흐름 (브라우저 -> 서버 -> 워커)

  1. 브라우저: 설정 입력
  2. 서버: /strategies/compile (AI 또는 폴백)
  3. 서버: /strategies/validate (리스크 계산)
  4. 서버: /sessions/start
  5. 브라우저: 10초마다 /sessions/heartbeat
  6. 브라우저: 주기적으로 /signals/generate
  7. 브라우저: 리스크 게이트 통과 시 주문 API 호출
  8. 브라우저: 중지 이벤트 시 /sessions/stop
  9. 워커: /worker/tick로 heartbeat 만료 세션 정리

6-1) AI가 실제로 받는 판단 데이터

자동매매는 "자연어 프롬프트만" 보내는 구조가 아닙니다. 실행 중에는 아래 구조화된 데이터가 같이 전달됩니다.

  1. 전략(compile 결과)
    • selectedTechniques
    • confidenceThreshold
    • maxDailyOrders
    • cooldownSec
    • maxOrderAmountRatio
  2. 시세 스냅샷(signal 요청 시)
    • symbol
    • currentPrice
    • changeRate
    • open/high/low
    • tradeVolume
    • accumulatedVolume
    • recentPrices(최근 체결가 배열)
  3. 서버 리스크 검증 결과
    • AI 신호가 buy/sell이어도 리스크 게이트 미통과 시 주문 차단

즉, AI는 "현재 종목 + 현재가 + 가격 흐름 + 전략 제약"을 같이 받아 판단하고, 최종 주문은 리스크 게이트를 통과해야 실행됩니다.

관련 소스:

  1. 스냅샷 구성: useAutotradeEngine.ts
  2. 신호 route 검증: signals/generate/route.ts
  3. 리스크 게이트: risk.ts

7) 보안: 레이어별 핵심

7-1) 브라우저

  1. KIS 민감정보는 세션 저장소(sessionStorage) 사용
  2. 브라우저 종료 시 세션 저장소 제거

7-2) Next 서버

  1. 자동매매 API는 사용자 인증 필요
  2. 워커 API는 x-autotrade-worker-token 인증 필요
  3. 민감정보 문자열 마스킹 처리

7-3) 워커

  1. 토큰이 틀리면 401
  2. 토큰은 코드 하드코딩 금지

8) 역할별로 어디 보면 되는지

  1. 기획/대표: 1, 2, 6, 7장
  2. QA: 5, 6, 7장 + worker 문서 6, 7장
  3. 개발: 2장 소스링크 + worker 문서 전체

9) 추가 문서

  1. 워커 상세 운영: autotrade-worker-pm2.md