Zenith (manifast-platform) 아키텍처
갱신 2026-08-12동접 ~3000 기준. UI·REST·SSE·Solana 구독을 분리하고, 부하가 큰 서비스만 Railway replica로 늘린다.
레포 manifast-platform · Railway revolution-platform
scripts/load-orders.ts 원샷입니다.전체 구조
강조 테두리: ingest / realtime (스케일 병목 해결 지점)
Railway replica (수평 확장)
replica = 같은 서비스를 복사본 여러 대로 띄우는 것. 코드가 아니라 인스턴스 개수를 늘린다. 1 = 서버 1대, 3 = 같은 프로세스 3대.
복제해도 되는 것
realtime — SSE 연결 부하 분산 (Redis 구독만)
trade-api — REST 주문·잔고 (무상태)
web — Next UI
함부로 복제하면 안 되는 것
ingest — 인스턴스마다 Solana WS가 또 열려 마켓당 구독이 N배. RPC가 먼저 터짐. 기본은 1대, 늘리려면 마켓 샤딩 등 설계가 필요.
서비스 역할 · replica
| 서비스 | 포트 | 하는 일 | replica | 메모 |
|---|---|---|---|---|
| apps/web | 4000 | Trade UI만 (Solana/SSE 로직 없음). 메인 `/` | 복제 OK | Next 인스턴스 늘려도 됨 |
| trade-api | 4001 | prepare / send / verify / balances / candles / fills · 서버 서명 주문 | 복제 OK | 무상태에 가깝다. REST 부하 시 복제 |
| realtime | 4002 | SSE fan-out · presence · Online · daily_visitors | 복제 OK | SSE 연결 부하를 나눔. Redis만 공유 |
| ingest | 4003 | 마켓당 Solana WS 1개 → Redis publish · fills/candles 쓰기 | 복제 금지 | 복제하면 같은 마켓 구독이 N배 → RPC가 먼저 터짐 |
| load-test | — | 원샷: scripts/load-orders.ts (HTTP 서버 아님) | 원샷 | 기동 시 동시 주문 후 종료. replica 의미 없음 |
데이터 계층
Redis
실시간역할
메인 DB가 아님. 중계·캐시·짧은 상태.
book:{market}pub/subfill:{market}pub/sub- presence / 최신 호가 스냅샷
MongoDB
영속역할
진짜 저장소. DB revolution.
candle_bars— 차트fills— 체결daily_visitors— 방문- 마켓 목록·Open Orders는 코드/온체인 (Mongo 아님)
MongoDB 컬렉션
candle_bars
차트봉 1개 = 문서 1개. 레거시 candle_series는 조회 시 1회 마이그레이션.
쓰기: ingest · scripts/backfill-fills
읽기: trade-api GET /api/markets/candles
fills
체결FillLog 1건 = 문서 1개. 테이프·내역·24h Volume.
쓰기: ingest (기동 이후) · backfill
읽기: trade-api fills / volume24h / history
daily_visitors
방문날짜(KST)별 presence SSE 연결 누적. Online(실시간)과 별개.
쓰기: realtime /presence/stream 연결 시 +1
읽기: GET /stats/daily-visitors
두 가지 주요 흐름
1. 실시간 호가/체결
- Solana → ingest (구독 1개)
- ↓ publish
- Redis channels
- ↓ subscribe
- realtime → SSE → Browser
- ↘ fills / candle_bars → Mongo
2. 주문 / 잔고
- Browser → trade-api prepare
- 지갑 서명 (Phantom / MetaMask)
- trade-api tx/send → Solana
- verify / balance 조회
- 부하 실측: Railway load-test → scripts/load-orders.ts (서버 지갑)
왜 이렇게 쪼개나
Next 한 프로세스에 UI + REST + SSE + Solana 구독 → 동접 3000이면 SSE 수천 + 동일 마켓 구독 수천 중복
Solana는 ingest만, 유저 연결은 realtime이 Redis로 분산. trade-api·realtime·web은 replica로 늘리고, ingest는 마켓당 1 유지.
Railway 배포 단위
모노레포 1개 Git → 앱 서비스 + Redis/Mongo 플러그인. Config: railway.*.toml