Files
trex-core/docs/discovery/dcy-006_20260605_strategy-module-rabbitmq-transport.md
T

33 KiB

0. 문서 상태

이 문서의 현재 상태와 식별 정보를 기록한다. 문서 추적과 승인 흐름에 필요한 최소 메타데이터를 적는다.

  • 상태: confirmed
  • 문서 ID: dcy-006_20260605_strategy-module-rabbitmq-transport
  • 이슈명: trex-core ↔ 전략 모듈 통신 transport — RabbitMQ 도입 (스냅샷 read + intent 제출 + 이벤트)
  • 작성 시각(KST): 2026-06-05 21:23
  • 마지막 갱신 시각(KST): 2026-06-05 22:45
  • 대체됨: 없음
  • 후속 Discovery 참조: 없음
  • 생성된 REQ 참조: REQ-021, REQ-022, REQ-023, REQ-024, REQ-025, REQ-026

1. 계획 상태 요약

현재 Discovery가 어떤 배경에서 작성되고 있는지, 연계 문서가 있는지, 지금 시점의 해석이 무엇인지 짧게 요약한다.

  • 연계 문서 현황:
    • 관련 점수 파일: 미생성
    • 관련 TODO/메모: dcy-005(portfolio-hub 종목 스냅샷 read API — FR-1/A-3 가 HTTP pull 가정), dcy-002(slot-core 데몬 + HTTP intent API), dcy-003(주문 집행 + durable outbox/idempotency), trex-core#1(매수/매도/position 전략 taxonomy)
  • 해석:
    • dcy-002(intent API)와 dcy-005(스냅샷 read)는 전략 모듈과의 통신을 HTTP API로 가정했는데, 사용자가 전략 모듈 통신을 API endpoint 대신 RabbitMQ(AMQP) 로 하고자 한다. transport 선택은 스냅샷 read·intent 제출·이벤트 전반에 걸친 cross-cutting 통합 아키텍처 결정이라, read 슬라이스(dcy-005) 안에 두지 않고 독립 Discovery로 분리한다.
    • 핵심 분리 원칙: logical 계약("무엇을 주고받나" — 스냅샷 필드/마스킹/view 모드/strategy_id 필터, intent 스키마)은 dcy-005/002/003 소관으로 transport-무관하게 유지하고, 본 Discovery 는 "어떻게 전달하나"(전달 방식·메시지 매핑·delivery 보증·운영)만 다룬다.

2. 요구사항 판정 결과

이번 요청이 기존 요구사항과 비교해 신규인지, 유사한지, 중복인지 판단하고 그 근거를 남긴다.

  • 판정: 신규
  • 근거
    • transport/messaging/RabbitMQ 를 다루는 기존 Discovery 가 없다(dcy-001~005 탐색 결과, repo 내 amqp/rabbitmq/pika 구현 0건).
    • 가장 가까운 dcy-002 는 HTTP API "수립"이 주제이지 transport "선택"이 아니며, MQ 전환은 dcy-002/005 의 미세 조정이 아니라 통신 모델 자체를 바꾸는 새 통합 아키텍처 문제다.

3. 문제점의 요약

문제의 현재 상태, 기대 상태, 관련 이해관계자, 제약사항을 정리한다. Discovery의 핵심 맥락을 가장 먼저 이해할 수 있어야 한다.

  • 현재 상태
    • trex-core daemon 은 FastAPI/uvicorn 기반 HTTP /v1 API(trex_core/adapters/api/app.py)로 전략/소비자와 통신한다(/v1/intents/buy|sell, /v1/slots, /v1/capacity; dcy-005 스냅샷 read 는 draft). messaging/AMQP 인프라는 없다(repo grep: rabbitmq/amqp/pika 0건).
    • baseline 문서가 HTTP 를 명시적 transport 로 기술한다 — interface-contract.md: "HTTP /v1 API :: 슬롯 코어 데몬이 노출, 매수·매도 전략 데몬이 호출". runtime-flows.md 도 HTTP request/response 흐름 기준.
    • 전략 모듈은 외부 소비자로서 HTTP pull 로 스냅샷을 받고 HTTP POST 로 intent 를 제출한다고 가정한다(dcy-005 A-3, dcy-002).
    • adapters 레이어는 api / broker / ledger / persistence 로 구성되며 messaging 어댑터는 없다.
  • 기대 상태
    • trex-core ↔ 전략 모듈 통신을 RabbitMQ(AMQP) 메시지 기반으로 제공한다. 스냅샷 요청과 intent admission 은 request-reply(reply-to/correlation-id), 체결/슬롯 상태 변화는 이벤트(pub/sub)로 전달한다(intent 체결 결과는 이벤트로, OQ-2).
    • view 모드(dcy-005 OQ-11)·strategy_id(dcy-005 FR-8) 같은 요청 속성이 메시지 속성/routing key 로 매핑된다.
    • logical 계약은 불변이고 transport 만 교체된다. HTTP /v1 API 는 RabbitMQ 로 완전 대체되어 HTTP 표면이 0 이 된다(병행 없음, OQ-1; healthz 포함 제거, OQ-7). liveness 는 프로세스 감독이 담당.
  • 이해관계자
    • 문서 작성자/구현자(AI agent)
    • 리뷰어/승인자(운영자, genichin@gmail.com)
    • 전략 모듈(trex-core 외부 소비자) 및 trex-core daemon
    • 운영자(RabbitMQ 인프라 도입·운영)
  • 제약사항
    • 도메인 순수성 — trex_core.domain 은 transport/AMQP 의존 0(어댑터 격리).
    • logical 계약 보존 — 스냅샷/intent 의 의미·필드·마스킹·view 모드·스키마는 transport 와 독립이며 본 Discovery 가 바꾸지 않는다.
    • core 권위 불변식 유지 — 슬롯/capacity 단일 writer(불변식 A) 는 transport 교체와 무관하게 보존된다.

주요 사용자 시나리오

사용자 또는 운영자가 실제로 어떤 상황에서 이 변경을 필요로 하는지 대표 시나리오를 적는다.

  • 전략 모듈이 portfolio 스냅샷을 요청 → trex-core 가 RabbitMQ reply 큐로 전략 실행 대상 자산 리스트를 응답한다(HTTP GET 대체).
  • 전략 모듈이 매수/매도(향후 target) intent 를 메시지로 발행 → trex-core 가 소비해 슬롯 전이를 수행한다.
  • 체결/슬롯 상태가 바뀌면 → trex-core 가 이벤트를 발행하고 전략 모듈이 구독해 즉시 반영한다(HTTP polling 불요).
  • RabbitMQ 가 일시 불가 → degrade 정책(버퍼링 금지·신규 매매 보수적 중단, OQ-4)에 따라 신규 전략 매매는 멈추고, 열린 포지션은 core 자율 안전 매도가 보호한다(미구현, A-5).

4. 이번에 정의할 변경

이번 Discovery에서 다루는 핵심 변경 항목을 목록으로 적는다. 기능, 구조, 규칙 변경을 함께 포함해도 된다.

  • transport 추상화 + RabbitMQ 어댑터(pika 동기): trex-core ↔ 전략 통신을 메시지 기반으로 제공. 스냅샷·intent admission = request-reply, 이벤트 = pub/sub 패턴 정의. 어댑터는 adapters/messaging(신규) 레이어로 격리하고 결정론 stub 제공. 런타임은 uvicorn 제거 후 sync+thread daemon 재구성(OQ-5).
  • 메시지 계약 매핑: 기존 logical 계약(스냅샷 필드/마스킹/view 모드/strategy_id, intent 스키마)을 메시지 payload/속성/routing key 로 1:1 의미 보존 매핑.
  • delivery 신뢰성: ack/재처리, idempotency(dcy-003 의 intent correlation_id 재사용), dead-letter, 내구성 큐. 순서는 intent 단일 consumer FIFO 로 보존하고 이벤트는 순서 보증 불요(상태 운반·last-wins, OQ-3).
  • HTTP 완전 제거: HTTP /v1 API 를 RabbitMQ 로 대체(병행 없음, OQ-1)하고 healthz 포함 모든 HTTP 라우트와 adapters/api HTTP 어댑터를 제거(HTTP 표면 0, OQ-7). dcy-005 FR-1/A-3·dcy-002 의 HTTP 가정을 갱신. liveness 는 프로세스 감독, 앱 헬스/관측성은 로그·메트릭.
  • baseline 갱신: interface-contract.md(메시지 계약)·runtime-flows.md(MQ 흐름)·project-structure.md(messaging 어댑터) 갱신.

영향 범위

변경이 미칠 코드/문서/운영 범위를 명시해 REQ 정제와 batch planning에서 추정 누락을 줄인다.

  • 코드 영향:
    • 신규: trex_core/adapters/messaging RabbitMQ(pika) 어댑터 + stub, 스레드별 connection/channel 관리, 직렬화, request-reply correlation(reply-to/correlation-id), intent RPC consumer 스레드, snapshot RPC consumer 스레드, 이벤트 publisher, 재연결/백오프, config 에 TREX_RABBITMQ_URL(.env) 주입(기존 TREX_* 패턴, OQ-6). uvicorn 제거로 TREX_API_HOST/TREX_API_PORT 폐기.
    • 기존: adapters/api HTTP 어댑터·uvicorn 제거, daemon entrypoint 를 sync+thread 런타임으로 교체(OQ-5), application 레이어의 intent/스냅샷 진입점을 transport-무관 포트로 재배선(직접 변경 최소화).
  • 문서 영향:
    • interface-contract/runtime-flows/project-structure 갱신, dcy-005 FR-1/A-3·dcy-002 HTTP 가정 완화 cross-reference.
  • 운영 영향:
    • RabbitMQ 브로커 인프라 추가(현 스택의 redis/timescale 처럼 docker 추가 가능). exchange/queue 토폴로지, 모니터링, 자격증명/접속 운영.

5. 요구사항 목록

실제로 구현과 검증으로 이어질 요구사항을 기능/비기능으로 나누어 정리하고, 범위 경계를 명확히 적는다.

기능 요구사항

  • FR-1: trex-core ↔ 전략 모듈 통신을 RabbitMQ(AMQP) 메시지 기반으로 제공한다(토폴로지 OQ-2). 스냅샷 요청과 intent admission 은 request-reply(trex.snapshot.req/trex.intent.req + RabbitMQ direct reply-to + correlation_id), 체결/슬롯 상태 변화는 이벤트(topic exchange trex.events, pub/sub) 로 전달한다. intent 의 체결 결과는 admission 응답이 아니라 이벤트로 전달해 현 2단계 시맨틱(admission 동기 + fill 비동기)을 보존한다.
  • FR-2: 기존 logical 계약(스냅샷 필드/마스킹/view 모드(dcy-005 OQ-11)/strategy_id 필터(dcy-005 FR-8), intent 스키마(dcy-002/003))을 transport-무관으로 보존하고, 메시지 payload/속성/routing key 로 의미 손실 없이 매핑한다. 매핑 규칙(OQ-2): 요청(스냅샷·intent)의 view 모드·strategy_id 는 payload, 이벤트의 strategy_id·symbol 은 routing key({event_type}.{strategy_id}.{symbol})로 싣는다.
  • FR-3: messaging 접근을 transport 포트 추상화 + RabbitMQ 어댑터(pika 동기 클라이언트) + 결정론 stub 로 제공한다. 런타임은 uvicorn 제거 후 순수 sync+thread daemon(consumer/execution/ledger 스레드)으로 재구성한다(OQ-5). trex_core/domain 은 transport/AMQP 의존 0 을 유지한다.
  • FR-4: delivery 신뢰성 — at-least-once + idempotency 로 effectively-once 를 제공한다(OQ-3). intent 는 슬롯 durable commit 후 ack + correlation_id(dcy-003 멱등키) dedup, durable/persistent + 단일 consumer FIFO. 이벤트는 durable exchange + per-strategy durable queue(catch-up) + 현재 상태·단조 시퀀스 운반(last-wins, 순서 보증 불요) + TTL/max-length. 발행은 publisher confirms, 실패는 dead-letter. 중복 전달에도 슬롯 단일 writer 불변식을 유지하고, 미수신/중복은 스냅샷 RPC 로 reconcile 한다.
  • FR-5: HTTP /v1 API 를 RabbitMQ 로 완전 대체한다(병행 없음, OQ-1; HTTP 표면 0, OQ-7). 전략-facing 통신(intents/buy|sell·intents/{id}·slots·capacity·dcy-005 스냅샷 read)을 메시지 기반으로 이전하고, healthz 포함 모든 HTTP 라우트와 HTTP 어댑터를 제거한다. liveness 는 프로세스 감독이 담당(앱 헬스/관측성은 로그·메트릭). dcy-005 FR-1/A-3·dcy-002 의 HTTP 가정을 갱신한다.
  • FR-6: baseline 문서(interface-contract.md/runtime-flows.md/project-structure.md)를 메시지 계약·MQ 흐름·messaging 어댑터에 맞게 갱신한다.

비기능 요구사항

성능, 운영성, 일관성, 자동화 안정성 등 기능 외 요구사항을 적는다.

  • NFR-1: 도메인 순수성 — transport/AMQP 의존은 adapters 레이어에 격리하고 trex_core/domain import 0(import 스윕).
  • NFR-2: 신뢰성/일관성 — at-least-once 전달 + idempotency 로 effectively-once 효과를 보장한다(OQ-3, 진짜 exactly-once 는 미추구). 슬롯/capacity 권위 불변식을 보존하고, 이벤트는 advisory(push 최적화)이며 스냅샷 RPC 가 권위 reconcile 경로다.
  • NFR-3: 가용성 degrade — RabbitMQ 불가 시 버퍼링 금지 + 신규 매매 보수적 중단(OQ-4). 단 core 자율 안전 매도(손절·시간 만기)는 MQ·전략과 독립으로 계속해 열린 포지션을 보호한다(이 capability 는 별도 core 기능, 현재 미구현 — A-5). dcy-005 OQ-5 와 공통 '보수적 안전' 철학을 따른다.

범위 경계

이번 반복에서 반드시 포함할 범위와 명시적으로 제외할 범위를 구분한다.

  • In Scope
    • transport 포트 + RabbitMQ 어댑터 + stub, 스냅샷·intent admission request-reply, 이벤트 pub/sub, 메시지 계약 매핑, delivery 신뢰성, HTTP 완전 제거, baseline 갱신.
  • Out of Scope (다른 Discovery 소관)
    • 스냅샷/intent 의 logical 계약 자체 변경(dcy-005/002/003), 전략 의사결정 로직(전략 모듈 책임, trex-core#1), RabbitMQ 클러스터/HA 운영 세부, portfolio-hub 등 다른 외부 연동의 transport.

6. 리스크/가정 목록

불확실성과 전제 조건을 분리해서 적는다. 리스크는 영향과 완화 방안을, 가정은 현재 판단의 전제를 기록한다.

리스크

  • R-1 (Low, 완화됨): 이중 transport 복잡도 — OQ-1 에서 HTTP 병행 없이 대체로 결정되어 계약 표류·중복 유지 비용은 대부분 해소. 단 전환기 동안 HTTP 어댑터 제거 시점과 전략 모듈 MQ 전환의 동기화가 필요(big-bang 마이그레이션 리스크는 R-5 로 분리).
    • 완화 방안: 단일 logical 계약을 transport-무관으로 정의(FR-2/FR-3), HTTP 어댑터 제거를 전략 모듈 전환과 함께 단계적 계획.
  • R-2 (Medium): delivery 의미 불일치 — at-least-once 재전달이 intent 를 중복 실행할 수 있다.
    • 완화 방안(OQ-3 Answered): dcy-003 correlation_id idempotency dedup + 슬롯 durable commit 후 ack + dead-letter(FR-4), 슬롯 단일 writer 불변식(NFR-2). 미수신/중복 이벤트는 스냅샷 RPC reconcile.
  • R-3 (Medium→High, 대체 결정으로 상향): 가용성 결합 — RabbitMQ 장애가 전략 통신을 전면 차단한다. HTTP 병행을 두지 않기로(OQ-1) 했으므로 HTTP fallback 이 없어 단일 장애점 성격이 강해진다.
    • 완화 방안(OQ-4 Answered): 버퍼링 금지 + 신규 매매 보수적 중단. 열린 포지션은 core 자율 안전 매도(손절·시간 만기)가 MQ·전략과 독립으로 보호 → SPOF 영향이 '신규 매매 중단'으로 한정되고 포지션 방치 위험은 제거된다. 단 이 보호는 아직 미구현 safety 기능에 의존(A-5, 추후 구현). RabbitMQ durable/HA 운영도 고려.
  • R-4 (Low): request-reply over MQ 복잡도 — 동기 HTTP pull 보다 reply 상관·타임아웃 처리가 필요하다.
    • 완화 방안: correlation-id + reply-to 규약(OQ-2). RPC per-request 타임아웃·재요청 규약은 설계 시 표준화(전략 클라이언트 측).
  • R-5 (Medium): big-bang transport 마이그레이션 — HTTP 제거와 전략 모듈 MQ 전환이 어긋나면 통신 단절.
    • 완화 방안: 전환 순서/롤백 계획 수립, stub 기반 사전 검증(FR-3), 전환 중 관측성은 로그·메트릭으로 확보(OQ-7 에서 HTTP healthz 제거 결정 — probe 대체 안 함).

가정

아직 확정되지 않았지만 현재 문서 작성의 기반이 되는 전제를 적는다.

  • A-1: 전략 모듈은 RabbitMQ 클라이언트로 메시지를 발행/구독할 수 있는 외부 소비자다.
  • A-2: trex-core 는 슬롯/capacity 권위 단일 소스이며 transport 교체와 무관하게 그 불변식을 유지한다.
  • A-3: 스냅샷/intent 의 logical 계약(필드/마스킹/view 모드/strategy_id/스키마)은 dcy-005/002/003 에서 정의되고, 본 Discovery 는 전달 방식만 다룬다.
  • A-4: RabbitMQ 브로커는 운영 환경에 도입 가능하다(현 스택에 redis/timescale 처럼 docker 로 추가 가능).
  • A-5: trex-core 는 transport·전략과 독립으로 동작하는 기본 안전 매도(손절 stop-loss, 시간 만기 forced_close) capability 를 갖는다(또는 추후 구현). degrade 시(RabbitMQ 불가·전략 슬롯 방치) 열린 포지션 보호의 전제다(OQ-4). 현재 미구현(forced_close_at 필드만 존재, stop-loss 없음)이며 구현은 별도 작업으로 추적(transport 범위 밖 core 매매 안전 기능).

오픈 질문

답을 아직 모르는 항목을 적는다. 추정으로 덮지 말고 REQ 초안 작성 이전에 확인할 질문으로 남긴다.

  • OQ-1: HTTP 대체 vs 병행 — RabbitMQ 가 HTTP /v1 API 를 완전 대체하는가, 둘을 병행(이중 transport)하는가?
    • 상태: Answered (2026-06-05)
    • 결정: RabbitMQ 가 HTTP /v1 API 를 대체한다. 이중 transport 병행은 채택하지 않는다. 전략-facing 통신(intents/buy|sell, intents/{id}, slots, capacity, dcy-005 스냅샷 read)은 전부 메시지 기반(command / request-reply / event)으로 옮긴다.
    • 반영 위치: # 3 기대 상태, # 4 변경 항목, # 5 FR-5, # 6 R-1·R-3.
    • 잔여(해소): 운영 probe/admin 표면의 '대체' 범위는 OQ-7 에서 Answered(앱 레벨 헬스 표면 제거, HTTP 표면 0).
  • OQ-2: 통신 패턴별 토폴로지 — exchange/queue/routing key + reply 상관 + view 모드/strategy_id 매핑.
    • 상태: Answered (2026-06-05)
    • 결정: 3 패턴 토폴로지 확정.
      • ① 스냅샷 RPC(request-reply): 요청 queue trex.snapshot.req(direct/default exchange) → trex-core 소비, 응답은 RabbitMQ direct reply-to(amq.rabbitmq.reply-to) + correlation_id. 요청 payload 에 strategy_id·view 모드.
      • ② intent admission RPC(request-reply): 요청 queue trex.intent.req → trex-core 소비, 응답 = admission(status, slot_id, reason). correlation_id = intent 멱등키(dcy-003 {asset_id}:{order_id}:{execution_id})로 RPC 상관 + dedup 일원화. 체결/종료(fill/close) 결과는 ② 응답이 아니라 ③ 이벤트로 전달 — 현 2단계 시맨틱(admission 동기 + fill 비동기) 무손실 보존.
      • ③ 이벤트 pub/sub: trex-core 가 체결·슬롯 상태 변화를 topic exchange trex.events 에 발행, routing key = {event_type}.{strategy_id}.{symbol}. 전략은 자기 queue 를 *.{strategy_id}.# 패턴으로 바인딩해 자기 자산 이벤트만 수신(broker단 필터).
      • 매핑 원칙: view 모드·strategy_id 는 요청(①②)에서는 payload, 이벤트(③)에서는 routing key(요청은 라우팅 대상이 아니고 이벤트는 대상).
    • 반영 위치: # 5 FR-1·FR-2·FR-4.
    • 잔여(→ 타 OQ): 이벤트 queue durability(전략 down 중 유실)·at-least-once/exactly-once → OQ-3; RPC reply 대기 클라이언트(pika/aio-pika) → OQ-5; RPC 타임아웃/degrade → OQ-4.
  • OQ-3: delivery 보증 수준 — at-least-once + idempotency 로 충분한가, 추가 ordering/exactly-once 가 필요한가?
    • 상태: Answered (2026-06-05, 위임 결정)
    • 결정: at-least-once + idempotency = effectively-once 를 기준으로 한다. 분산 메시징에서 진짜 exactly-once 는 불가하므로 추구하지 않고 멱등 소비로 '사실상 한 번' 효과를 낸다. 패턴별:
      • ① 스냅샷 RPC: read-only → 멱등. at-least-once, 별도 dedup 불요. 요청/응답은 transient(클라이언트 timeout 후 재요청). manual ack.
      • ② intent admission RPC: at-least-once + correlation_id(= dcy-003 멱등키) dedup. 슬롯 전이를 Postgres 에 durable commit 한 뒤 ack → crash 로 재전달돼도 idempotency 가 중복 실행을 차단. intent 요청 queue·메시지는 durable/persistent, 단일 consumer FIFO 로 순서 보존(trex-core 단일 writer 불변식 A 와 정합). 전역 total order 는 불요.
      • ③ 이벤트 pub/sub: at-least-once + 멱등 소비. durable exchange + per-strategy durable queue 로 전략 down 중 이벤트 catch-up. 이벤트는 delta 가 아니라 현재 상태 + 단조 증가 시퀀스(슬롯 version/timestamp) 를 실어 last-wins 적용 → 순서 보증 불요. 미수신/중복은 스냅샷 RPC(권위 reconcile 경로) 로 항상 복구(이벤트는 push 최적화이지 단일 진실원이 아님).
      • 공통: trex-core 발행은 publisher confirms 로 broker 수락 확인. per-strategy 이벤트 queue 는 무한 적체 방지를 위해 TTL/max-length(초과분 drop-oldest, 스냅샷 reconcile 로 회복) 적용.
    • 반영 위치: # 5 FR-4·NFR-2, # 6 R-2.
    • 근거: 멱등키(dcy-003)와 스냅샷 권위 reconcile 이 이미 있어 exactly-once 인프라 비용 없이 안전. 순서는 단일 consumer FIFO + 상태 운반 이벤트로 충분.
  • OQ-4: 가용성 degrade 정책 — RabbitMQ 불가 시 행동 규약.
    • 상태: Answered (2026-06-05)
    • 결정:
      1. 버퍼링 금지 — broker 불가 시 intent 를 로컬에 쌓아 복구 후 재생하지 않는다(지나간 결정의 지연 실행 위험 차단). HTTP fallback 은 OQ-1(HTTP 0)으로 선택지에서 제외.
      2. 보수적 중단 — broker 불가 시 신규 전략 매매 유입은 중단하고, 전략은 복구 후 신선 데이터로 재판단한다. 스냅샷 RPC 타임아웃 시 전략은 매매를 보류한다.
      3. core 자율 안전 매도는 transport·전략과 독립으로 계속 — trex-core 의 기본 안전 매도(손절 stop-loss, 시간 만기 forced_close)는 RabbitMQ 가용성과 무관하게, 그리고 전략이 특정 슬롯을 더 이상 패치/관리하지 않아도(dead-man's-switch) 동작해야 한다. broker 장애나 전략 방치 시에도 열린 포지션은 core 가 보호한다.
    • 참고(현행 코드, 정직 기록): 이 안전 매도 기능은 아직 미구현이다 — forced_close_at 은 필드만 존재(BAT-014/REQ-066 lineage)하고 자동 트리거 로직이 execution 루프에 없으며, stop-loss(손절)는 코드에 전혀 없다. 나중에 구현 예정이며 본 문서에는 degrade 정책의 전제로 참조만 기입한다(별도 구현 Discovery 는 추후, A-5).
    • 반영 위치: # 5 NFR-3, # 6 R-3·A-5(신규).
    • 종료 조건(충족): degrade 동작·core 안전 매도 독립성 전제가 NFR-3/R-3/A-5 에 반영됨.
  • OQ-5: 클라이언트/런타임 통합.
    • 상태: Answered (2026-06-05)
    • 결정: pika(동기) + 스레드 기반 런타임. HTTP 제거(OQ-1)로 uvicorn/FastAPI 를 들어내고, 현 sync stack(psycopg 동기·동기 서비스·threading.Thread execution/ledger 루프)에 정합하는 순수 sync+thread daemon 으로 재구성한다.
      • consumer: intent RPC consumer 스레드(단일, prefetch=1, Postgres commit 후 ack → OQ-3 FIFO/멱등 충족) + snapshot RPC consumer 스레드. pika connection 은 thread-safe 가 아니므로 스레드별 connection/channel 또는 add_callback_threadsafe 규약을 따른다.
      • 이벤트 publisher: execution 루프 스레드가 체결/종료 시 자기 channel 로 trex.events 에 발행(OQ-2/OQ-3).
      • entrypoint: uvicorn.run(app) → connection 셋업 + consumer/execution/ledger 스레드 기동 + graceful shutdown(기존 stop 이벤트 패턴 확장 + connection close).
      • 재연결/백오프: pika 는 자동 재연결이 없으므로 직접 구현하며 OQ-4 degrade(보수적 중단) 정책과 묶는다.
    • 반영 위치: # 4 변경 항목·영향 범위, # 5 FR-3.
    • 종료 조건(충족): 클라이언트·런타임 통합이 FR-3/영향 범위에 반영됨.
  • OQ-6: 자격증명/설정 주입 — .env AMQP URL 등 접속 정보 주입 패턴.
    • 상태: Answered (2026-06-05)
    • 결정: 기존 TREX_* env 주입 패턴을 재사용한다. AMQP 접속은 단일 URL env TREX_RABBITMQ_URL(예: amqp://user:pass@host:5672/vhost)로 받아 DaemonConfig.from_env() 에서 로드한다 — 기존 TREX_KIS_REDIS_URL(URL+자격증명을 한 env 로) 패턴과 동형. 자격증명은 URL 에 포함(redis 와 동일 방식).
    • 반영 위치: # 4 영향 범위(config), # 5 FR-3, # 10 DATA.
    • 참고: uvicorn 제거(OQ-5)로 기존 TREX_API_HOST/TREX_API_PORT env 는 폐기 대상이 된다.
    • 종료 조건(충족): 주입 방식이 config/영향 범위에 반영됨.
  • OQ-7: 운영 probe/admin 표면의 '대체' 범위 — OQ-1 의 HTTP 대체 결정이 전략-facing 통신에 한정인가, GET /v1/healthz 같은 앱 레벨 헬스 표면까지 제거하는가? (현 배포 환경: 오케스트레이터 없음 — daemon 은 맨 프로세스(uvicorn)로 실행, repo 에 k8s/compose/Dockerfile 없음. 따라서 '프로세스 살아있음' liveness 는 프로세스 감독(systemd/supervisor/docker restart)이 담당하며 transport 와 무관. HTTP 대체로 잃는 것은 앱 레벨 HTTP 헬스 표면뿐.)
    • 상태: Answered (2026-06-05)
    • 결정: (a) 앱 레벨 헬스 표면 제거 — HTTP 표면 0. GET /v1/healthz 포함 모든 HTTP 엔드포인트를 제거한다. liveness("프로세스 살아있음")는 프로세스 감독(systemd/supervisor/docker restart)이 담당하며 transport·broker 와 무관하다(broker 장애가 재시작 루프를 유발하지 않음). 앱 레벨 헬스/관측성은 로그·메트릭으로 대체한다.
    • 반영 위치: # 3 기대 상태, # 4 변경 항목, # 5 FR-5, # 6 R-5.
    • 영향: 현재 trex_core/adapters/api/app.py 의 healthz 라우트도 제거 대상에 포함된다.

오픈 질문 처리 기준

  • Open: 아직 답이 없고 다음 단계 진행에 영향이 있는 상태다. 문서에 유지한다.
  • Answered: 답이 확정된 상태다. 관련 본문/요구사항에 반영한 뒤 오픈 질문 목록에서는 제거하거나 resolved 기록으로 이동한다.
  • Deferred: 지금 단계에서 결정하지 않고 다음 단계 또는 후속 이슈로 넘기는 상태다. 넘길 대상과 이유를 반드시 적는다.
  • Dropped: 더 이상 유효하지 않은 질문이다. 삭제 사유를 짧게 남기고 목록에서 제거한다.
  • 처리 원칙 1: 질문만 남기지 말고 반드시 상태, 처리 방안, 종료 조건을 함께 적는다.
  • 처리 원칙 2: 답이 나온 질문은 본문 반영 없이 단순 삭제하지 않는다. 반영 위치를 먼저 갱신한다.
  • 처리 원칙 3: High 영향 질문은 Deferred 처리 후 처리 방안에 REQ 인계 추적 방식을 명시한다.

7. 초기 성공 기준

이 변경이 성공했다고 판단할 기준을 측정 가능하게 정의한다. 가능하면 데이터 출처까지 연결한다.

  • S-1: stub messaging 어댑터로 스냅샷 request-reply 가 HTTP 와 동일한 logical 응답(필드/마스킹/view 모드)을 반환한다.
  • S-2: intent admission RPC 메시지가 슬롯 전이를 일으키고, 중복 전달에도 correlation_id idempotency 로 단일 실행된다.
  • S-3: 체결/슬롯 상태 이벤트가 발행되고 구독자가 수신한다.
  • S-4: 도메인 import 스윕에서 transport/AMQP 의존이 0 으로 유지된다.
  • S-5: interface-contract/runtime-flows/project-structure 가 메시지 계약·MQ 흐름과 정합한다.
  • S-6: daemon 기동 후 HTTP 표면이 0 이다(healthz 포함 HTTP 포트/엔드포인트 없음, OQ-1/OQ-7).
  • S-7: RabbitMQ 불가 시 신규 intent 가 버퍼링되지 않고 보수적으로 중단되며, broker 복구 후에도 옛 intent 가 자동 재생되지 않는다(OQ-4).
  • S-8: strategy_id 를 routing key 로 한 이벤트가 해당 전략 queue 에만 전달되고 다른 전략 queue 에는 전달되지 않는다(FR-2/OQ-2).

측정 방식 및 데이터 출처

각 성공 기준을 어떻게 측정할지와 어떤 데이터나 문서를 근거로 쓸지 적는다.

  • S-1 측정 방식: stub request-reply 통합테스트 / 데이터 출처: 응답 메시지 본문 vs HTTP 응답.
  • S-2 측정 방식: 중복 intent 메시지 주입 테스트 / 데이터 출처: 슬롯 상태·실행 횟수.
  • S-3 측정 방식: 이벤트 발행-구독 테스트 / 데이터 출처: 구독자 수신 메시지.
  • S-4 측정 방식: 정적 import 스윕 / 데이터 출처: trex_core/domain import 목록.
  • S-5 측정 방식: 문서-코드 정합 리뷰 / 데이터 출처: baseline 문서 vs 실제 토폴로지/어댑터.
  • S-6 측정 방식: 기동 후 포트/라우트 스캔 / 데이터 출처: daemon 런타임(HTTP 리스너 부재).
  • S-7 측정 방식: broker 중단 주입 후 intent 발행 테스트 / 데이터 출처: 신규 슬롯 전이 없음·복구 후 재생 없음.
  • S-8 측정 방식: 2개 전략 queue 바인딩 후 이벤트 발행 테스트 / 데이터 출처: 각 queue 수신 메시지.

8. REQ로 넘기기 전 확인 체크

REQ 초안 작성 단계로 넘기기 전에 무엇이 확정되어야 하는지 확인한다. 미완료 항목은 후속 결정이 필요함을 뜻한다.

  • 범위(In Scope/Out of Scope) 확정 — 특히 logical 계약 불변·전략 로직 제외
    • 기준: 운영자가 transport 범위 경계(logical 계약은 dcy-005/002/003 소관)를 확인했다.
  • 성공 지표의 측정 방식/데이터 출처 확정
    • 기준: S-1~S-8 측정 방식·출처 명시(본 문서 # 7).
  • High 영향 리스크 우선순위 및 해소 책임자 지정
    • 기준: HTTP 대체 결정(OQ-1)으로 가용성 결합(R-3)이 High 로 상향(HTTP fallback 부재). delivery(R-2)·가용성(R-3)·big-bang 마이그레이션(R-5) 처리 방침을 운영자가 확인.
  • 모든 오픈 질문(OQ) Open 상태 없음 확인
    • 기준: OQ-1OQ-7 이 전부 Answered/Deferred 처리(현재 OQ-1OQ-7 전부 Answered).
  • Freeze 확정 담당자(CONFIRMED_BY) 지정
    • 기준: 운영자가 confirm-discovery 시점에 CONFIRMED_BY 를 지정한다.

9. 파일 처리 결과

이 Discovery 문서 생성/갱신 결과와 참조 문서를 기록한다. 이후 추적과 리뷰 시 근거로 사용한다.

  • 처리 결과: 생성
  • 생성 경로: docs/discovery/dcy-006_20260605_strategy-module-rabbitmq-transport.md
  • 참조 문서:
    • docs/discovery/dcy-005_20260604_portfolio-hub-asset-snapshot-api.md (스냅샷 read — HTTP 가정 FR-1/A-3, view 모드/strategy_id logical 계약)
    • docs/discovery/dcy-002_20260603_slot-core-daemon-http-api.md (HTTP intent API — transport 가정 출처)
    • docs/discovery/dcy-003_20260604_broker-execution-and-outbox.md (correlation_id idempotency/outbox — delivery 신뢰성 재사용)
    • docs/interface-contract.md, docs/runtime-flows.md, docs/project-structure.md (baseline — 본 Discovery 가 갱신 요구)
    • stage-pilot/templates/project-structure.md, stage-pilot/templates/runtime-flows.md (baseline 갱신 논리 템플릿)
    • https://github.com/fourblocks2020/trex-core/issues/1 (전략 taxonomy — intent 종류와 연계)

10. 사용자 결정 필요 항목 요약

사용자나 승인자가 결정해야 하는 항목만 모아 정리한다. 결정, 확인, 데이터 요청을 구분해서 적는다.

DECIDE

  • HTTP 대체 vs 병행 → 결정됨: RabbitMQ 가 HTTP /v1 API 를 대체(병행 없음) (OQ-1, 2026-06-05). 운영 probe 잔존 범위는 OQ-7.
  • 운영 probe/admin 범위 → 결정됨: 앱 레벨 헬스 표면 제거, HTTP 표면 0(healthz 포함). liveness=프로세스 감독 (OQ-7, 2026-06-05)
  • delivery 보증 수준 → 결정됨: at-least-once + idempotency = effectively-once. intent=durable commit 후 ack+dedup·단일 consumer FIFO, 이벤트=durable per-strategy queue+상태/시퀀스 운반(순서 불요)+스냅샷 reconcile, exactly-once 미추구 (OQ-3, 2026-06-05)
  • 클라이언트/런타임 통합 → 결정됨: pika(동기) + 스레드 런타임, uvicorn 제거, consumer 스레드(intent prefetch=1 FIFO·snapshot), 재연결 직접 구현 (OQ-5, 2026-06-05)

CONFIRM

  • transport 범위 경계 → 확정됨(2026-06-05, Justin): In Scope(RabbitMQ 전환·HTTP 완전 제거·delivery 신뢰성·baseline 갱신) / Out of Scope(logical 계약 변경·전략 로직·core 안전 매도 구현·RabbitMQ HA 운영) 확인
  • degrade 정책 → 결정됨: 버퍼링 금지 + 신규 매매 보수적 중단 + core 자율 안전 매도(손절·시간 만기)는 MQ·전략 독립 동작(미구현, 추후, A-5). dcy-005 OQ-5 와 공통 보수적 안전 (OQ-4, 2026-06-05)
  • 통신 패턴별 토폴로지 → 결정됨: 스냅샷·intent admission = request-reply(direct reply-to), 이벤트 = topic exchange trex.events(rk {event_type}.{strategy_id}.{symbol}), 요청은 payload·이벤트는 routing key 매핑, intent fill 은 이벤트로 (OQ-2, 2026-06-05)

DATA

  • DATA(비차단, REQ/delivery 단계 계측·provision): RabbitMQ 브로커 인프라 provision + 접속 자격증명 — 주입 방식은 TREX_RABBITMQ_URL env 로 확정(OQ-6). 실제 broker 인스턴스/계정 제공은 delivery 단계 운영 작업이며 FR/NFR·범위·성공 기준·검증 시나리오가 충분해 REQ 초안 작성을 막지 않는다.

11. Discovery Freeze

REQ 초안 작성 인계 시점의 확정 플래그와 섹션 참조만 기록한다. 내용 재작성 없이 원본 섹션을 링크로 대신한다.

섹션 참조

Freeze 플래그

  • Handoff Decision: 승인
  • Handoff Rationale: OQ-1~OQ-7 전부 Answered — HTTP 대체(표면 0)·통신 토폴로지(RPC 스냅샷/intent + topic 이벤트)·delivery(effectively-once)·degrade(버퍼링 금지·보수적 중단·core 자율 안전 매도 독립)·클라이언트(pika 동기 + 스레드, uvicorn 제거)·자격증명(TREX_RABBITMQ_URL)까지 transport 골격 확정. 남은 인계 전 항목은 transport 범위 경계 확인(운영자)과 CONFIRMED_BY 지정뿐이다. DATA(RabbitMQ 인프라 provision)는 delivery 단계 운영 작업으로 비차단. confirm-discovery 에서 확정 후 REQ Drafting 으로 인계한다.
  • Ready for REQ Drafting: true
  • Confirmed By: Justin
  • Confirmed At (KST): 2026-06-05 22:30