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
/v1API(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/v1API :: 슬롯 코어 데몬이 노출, 매수·매도 전략 데몬이 호출".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 daemon 은 FastAPI/uvicorn 기반 HTTP
- 기대 상태
- 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
/v1API 는 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
/v1API 를 RabbitMQ 로 대체(병행 없음, OQ-1)하고healthz포함 모든 HTTP 라우트와adapters/apiHTTP 어댑터를 제거(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/messagingRabbitMQ(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/apiHTTP 어댑터·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 exchangetrex.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
/v1API 를 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/domainimport 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
/v1API 를 완전 대체하는가, 둘을 병행(이중 transport)하는가?- 상태: Answered (2026-06-05)
- 결정: RabbitMQ 가 HTTP
/v1API 를 대체한다. 이중 transport 병행은 채택하지 않는다. 전략-facing 통신(intents/buy|sell,intents/{id},slots,capacity, dcy-005 스냅샷 read)은 전부 메시지 기반(command / request-reply / event)으로 옮긴다. - 반영 위치:
# 3기대 상태,# 4변경 항목,# 5FR-5,# 6R-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(요청은 라우팅 대상이 아니고 이벤트는 대상).
- ① 스냅샷 RPC(request-reply): 요청 queue
- 반영 위치:
# 5FR-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 로 회복) 적용.
- 반영 위치:
# 5FR-4·NFR-2,# 6R-2. - 근거: 멱등키(dcy-003)와 스냅샷 권위 reconcile 이 이미 있어 exactly-once 인프라 비용 없이 안전. 순서는 단일 consumer FIFO + 상태 운반 이벤트로 충분.
- OQ-4: 가용성 degrade 정책 — RabbitMQ 불가 시 행동 규약.
- 상태: Answered (2026-06-05)
- 결정:
- 버퍼링 금지 — broker 불가 시 intent 를 로컬에 쌓아 복구 후 재생하지 않는다(지나간 결정의 지연 실행 위험 차단). HTTP fallback 은 OQ-1(HTTP 0)으로 선택지에서 제외.
- 보수적 중단 — broker 불가 시 신규 전략 매매 유입은 중단하고, 전략은 복구 후 신선 데이터로 재판단한다. 스냅샷 RPC 타임아웃 시 전략은 매매를 보류한다.
- 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). - 반영 위치:
# 5NFR-3,# 6R-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.Threadexecution/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(보수적 중단) 정책과 묶는다.
- consumer: intent RPC consumer 스레드(단일, prefetch=1, Postgres commit 후 ack → OQ-3 FIFO/멱등 충족) + snapshot RPC consumer 스레드. pika connection 은 thread-safe 가 아니므로 스레드별 connection/channel 또는
- 반영 위치:
# 4변경 항목·영향 범위,# 5FR-3. - 종료 조건(충족): 클라이언트·런타임 통합이 FR-3/영향 범위에 반영됨.
- OQ-6: 자격증명/설정 주입 —
.envAMQP URL 등 접속 정보 주입 패턴.- 상태: Answered (2026-06-05)
- 결정: 기존
TREX_*env 주입 패턴을 재사용한다. AMQP 접속은 단일 URL envTREX_RABBITMQ_URL(예:amqp://user:pass@host:5672/vhost)로 받아DaemonConfig.from_env()에서 로드한다 — 기존TREX_KIS_REDIS_URL(URL+자격증명을 한 env 로) 패턴과 동형. 자격증명은 URL 에 포함(redis 와 동일 방식). - 반영 위치:
# 4영향 범위(config),# 5FR-3,# 10DATA. - 참고: uvicorn 제거(OQ-5)로 기존
TREX_API_HOST/TREX_API_PORTenv 는 폐기 대상이 된다. - 종료 조건(충족): 주입 방식이 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변경 항목,# 5FR-5,# 6R-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/domainimport 목록. - 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-1
OQ-7 이 전부 Answered/Deferred 처리(현재 OQ-1OQ-7 전부 Answered).
- 기준: OQ-1
- 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/v1API 를 대체(병행 없음) (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 exchangetrex.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_URLenv 로 확정(OQ-6). 실제 broker 인스턴스/계정 제공은 delivery 단계 운영 작업이며 FR/NFR·범위·성공 기준·검증 시나리오가 충분해 REQ 초안 작성을 막지 않는다.
11. Discovery Freeze
REQ 초안 작성 인계 시점의 확정 플래그와 섹션 참조만 기록한다. 내용 재작성 없이 원본 섹션을 링크로 대신한다.
섹션 참조
- 범위: # 5. 요구사항 목록 > 범위 경계
- 리스크/오픈 질문: # 6. 리스크/가정 목록
- 성공 기준: # 7. 초기 성공 기준
- 인계 전 확인: # 8. REQ로 넘기기 전 확인 체크
- 사용자 결정 필요: # 10. 사용자 결정 필요 항목 요약
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