ADR-002 실행 주체 위치 선택
상태
결정 (확정)
맥락
현재 4개 서버가 역할을 나눠 갖는다.
| 서버 | 역할 | 근거 ADR |
|---|---|---|
backend (:50000) | 도메인·영속화 소유 | — |
aggregator (:50001) | FE 진입점 BFF | 로드맵 외 |
worker (:50002) | stateless 오케스트레이션 전담 | ADR-008·ADR-010 |
ml (:50003) | 신호 산출·백테스트 (stateless) | ADR-001 |
자동매매 사이클은 주기 실행 + 여러 데이터 조합 + 외부 API 호출이라 표면적으로 worker의 역할(오케스트레이션)과 닮았다. 어디에 둘지 정해야 한다.
결정
backend 단독에 둔다. autotrading 도메인을 신설하고 스케줄러·리스크 게이트·집행을 모두 여기서 수행한다. worker·ml은 사용하지 않는다.
근거
- 집행은 stateless가 아니다. ADR-010이 정한 worker의 책임은 “입력=BE, 계산=ml, 영속화=BE”인 무상태 조율이다. 자동매매는 리스크 한도 소진량·포지션·거래일 상태를 읽고 쓰면서 판단한다. worker에 두면 상태가 두 곳으로 갈린다.
- 필요한 데이터가 전부 backend에 있다.
signal_snapshots·stock_price_cache·accounts·orders와 토스 주문 Gateway(TossOrderGatewayImpl)·레이트리미터(TossRateLimiterFacade)가 모두 backend 소유다. worker에 두면 이 전부를 HTTP로 다시 노출해야 한다. - 킬 스위치가 1초 안에 반영돼야 한다 (PRD NFR). 같은 프로세스면 트랜잭션 내 재확인으로 끝나지만, 홉이 끼면 전파 지연·경합·부분 적용이 생긴다.
- 강한 일관성이 필요하다. “한도 소진량 확인 → 주문 집행 → 소진량 갱신”이 원자적이지 않으면 한도를 넘긴 집행이 가능해진다. 단일 트랜잭션 경계가 가장 단순한 해법이다.
- 지금 규모에 과한 방안을 피한다. 사용자 1명·종목 117개·최대 5포지션이다. 분산 오케스트레이션이 해결할 문제가 존재하지 않는다.
고려한 대안
| 대안 | 미채택 사유 |
|---|---|
worker 오케스트레이션 | 집행은 상태를 가진다. 홉이 늘면 킬 스위치 전파·주문 멱등·부분 실패가 전부 분산 문제로 승격된다. ADR-008/010의 worker 정의에도 어긋난다 |
ml에 사이징·리스크 판정 위임 | 사이징·게이트는 산술 몇 줄이지 ML이 아니다. 체결 경로에 네트워크 장애점만 추가된다 |
| 신규 전용 서버 | 5번째 서버의 운영·배포·모니터링 비용이 이득을 넘는다. 장애 자동 복구(STK12) 대상도 하나 늘어난다 |
영향
backend에autotrading패키지(domain/application/infrastructure/presentation)가 신설된다.worker·aggregator·frontend·ml은 변경 없다.- 크로스 컨텍스트 조회(
signal·stock·order·account)는 backend 내부 application 레이어에서 조합한다 — 소유 도메인의 DomainService를 거치고 application 매퍼가autotrading값 객체로 변환한다 (no-crosscontext-raw-read 준수). - backend 프로세스 부하가 늘어난다. 사이클 주기(TDD Open Question T-1)로 조절한다.