피처 플래그
quant-ai의 자산군 / LLM / 라이브 라우팅은 모두 FEATURE_* 환경변수로
게이팅됩니다. 단일 출처는 server/services/feature_flags.py::_FLAG_DEFAULTS 이며,
신규 플래그는 그 dict에만 등록하면 자동으로 get_flags()에 노출됩니다.
동작 방식
- 모든 플래그는 기본 OFF. 명시적으로
true/1/yes/on으로 켭니다. - 라우터에
@require_flag("FEATURE_EQUITY_PAPER")데코레이터를 붙이면 플래그 OFF 상태에서 503 Service Unavailable로 차단됩니다. - 정의되지 않은 플래그 이름은
is_enabled()가False를 반환 (오타 방지).
플래그 카탈로그
| 플래그 | 기본값 | 의미 / 가드 라우트 |
|---|---|---|
FEATURE_EQUITY_PAPER | false | 미국/한국 주식 페이퍼 모드 — /api/equity/orders 등 |
FEATURE_EQUITY_LIVE | false | 미국/한국 주식 라이브 모드 — 실제 자금 거래 |
FEATURE_LLM_ANALYSIS | false | /api/equity/analyze LLM 분석 큐잉 활성 |
FEATURE_KIS_BROKER | false | KIS 브로커 어댑터 |
FEATURE_ALPACA_BROKER | false | Alpaca 브로커 어댑터 |
FEATURE_EQUITY_ANALYSIS | false | Equity 페이지 분석 탭 / 보고서 페이지 활성 |
의존성 그래프
flowchart TD
PAPER[FEATURE_EQUITY_PAPER] --> ANALYSIS[FEATURE_EQUITY_ANALYSIS]
PAPER --> LIVE_F[FEATURE_EQUITY_LIVE]
LIVE_F -.기술적 의존.-> ALLOW[ALLOW_LIVE=1]
LIVE_F -.운영 의존.-> READY[paper 90d / 50 trades]
ANALYSIS --> LLM[FEATURE_LLM_ANALYSIS]
LIVE_F --> ALPACA[FEATURE_ALPACA_BROKER]
LIVE_F --> KIS[FEATURE_KIS_BROKER]
FEATURE_EQUITY_LIVE만true로 두고 paper / 브로커 플래그가 OFF면 대부분의 라이브 라우트가 503입니다.FEATURE_EQUITY_ANALYSIS가 ON이어도FEATURE_LLM_ANALYSIS가 OFF면 분석 큐가 503이 됩니다 — 사용자에게는 "분석 기능 일시 비활성" UI 메시지로 노출.
사용 시나리오
시나리오 A: 신규 인스턴스를 페이퍼만으로 운영
FEATURE_EQUITY_PAPER=true
FEATURE_EQUITY_LIVE=false
FEATURE_LLM_ANALYSIS=true # 분석은 페이퍼에서도 의미 있음
FEATURE_EQUITY_ANALYSIS=true
FEATURE_ALPACA_BROKER=true
FEATURE_KIS_BROKER=true
ALLOW_LIVE= # 빈값 (prod 라이브 차단)
이 조합은 가장 안전한 운영 시작점입니다. 90일 / 50 거래 임계를 넘기면 사용자가 paper-to-live 승급 절차로 라이브 전환합니다.
시나리오 B: 라이브 활성
승급 절차를 통과한 사용자에게만 라이브를 열려면, 운영자가 다음을 모두 true로 설정해야 합니다.
# VM .env
FEATURE_EQUITY_LIVE=true
FEATURE_ALPACA_BROKER=true # 또는 KIS
ALLOW_LIVE=1 # VM 호스트 환경변수
이중 잠금 (prod)
프로덕션 compose 파일은 다음과 같이 작성되어 있어, ALLOW_LIVE=1이
없으면 FEATURE_EQUITY_LIVE=true가 빈값으로 강제됩니다.
FEATURE_EQUITY_LIVE: ${ALLOW_LIVE:+${FEATURE_EQUITY_LIVE:-false}}
이는 페이퍼용 .env를 실수로 prod VM에 복사해도 라이브가 켜지지 않도록
하는 안전장치입니다.
시나리오 C: LLM만 임시 비활성
LLM 비용이 임박했거나 LiteLLM proxy가 다운됐을 때:
docker compose exec api sh -c 'echo "FEATURE_LLM_ANALYSIS=false" >> /tmp/override'
# 더 안전한 절차:
sed -i 's/^FEATURE_LLM_ANALYSIS=.*/FEATURE_LLM_ANALYSIS=false/' .env
docker compose restart api analysis-worker
/api/equity/analyze는 503을 반환하고, UI는 "AI 분석 일시 비활성"
메시지를 표시합니다. 거래 / 페이퍼 모드는 영향 없음.
시나리오 D: 인시던트 시 라이브만 차단
이미 활성화된 라이브를 즉시 차단하려면, 가장 빠른 방법은 ALLOW_LIVE만
끄고 컨테이너를 재시작하는 것입니다.
sed -i 's/^ALLOW_LIVE=.*/ALLOW_LIVE=0/' .env
docker compose restart api analysis-worker position-reconciler
자세한 절차는 비상 정지 참조.
검증
# 현재 활성 플래그 확인 (내부 헬스 엔드포인트)
curl -s http://localhost:8000/health/flags
# {
# "FEATURE_EQUITY_PAPER": true,
# "FEATURE_EQUITY_LIVE": false,
# ...
# }
get_flags()가 직접 환경변수를 다시 읽으므로, .env 변경 후 컨테이너
재시작 없이 즉시 반영됩니다 (단, 데코레이터가 적용된 라우터는 프로세스
재시작이 필요).
트러블슈팅
| 증상 | 원인 / 조치 |
|---|---|
| 라우트가 503인데 플래그를 true로 설정함 | 컨테이너 재시작 누락. docker compose restart api |
FEATURE_EQUITY_LIVE=true인데 라이브가 안 켜짐 | prod에서 ALLOW_LIVE가 빈값 — VM 호스트에 export ALLOW_LIVE=1 후 재시작 |
Unknown feature flag: FEATURE_FOO 에러 | _FLAG_DEFAULTS에 등록 안 됨. 신규 플래그는 코드 PR 동반 필요 |
| 토글 후에도 UI가 옛 상태 | 프론트엔드가 캐시된 /health/flags 사용. 하드 리프레시 또는 로그아웃→로그인 |