본문 바로가기
C.W.K.
Stream
Lesson 05 of 08 · published

거래와 시장 데이터

~12 min · app, trading, binary

Level 0Poller
0 XP0/60 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

높은 빈도에는 바이너리가 필요해

암호화폐 거래소 정보 흐름은 종목마다 초당 100회가 넘는 시세를 보낼 수 있어. 이 속도에서 JSON 은 대역폭과 CPU 를 크게 잡아먹어. MessagePack, 사용자 지정 DataView, Protobuf 같은 바이너리 프로토콜은 프레임 크기를 60~80% 줄이고 해석 시간은 더 크게 줄여. 공개 홈페이지의 시세 표시에는 JSON 이면 충분하지만 종목 500개를 구독하는 거래 데스크에는 바이너리가 필수야.

혼합 패턴

거래 플랫폼은 관심사를 나눠. 빈도가 높은 가격과 호가 흐름은 바이너리 WebSocket 으로 보내고, 주문 제출·취소·계정 정보처럼 빈도가 낮은 명령은 REST 로 처리해. 같은 인증 토큰을 둘 다에 쓸 수 있어. 사용자는 가끔 주문을 보내지만 시장은 끊임없이 데이터를 밀어 주니까.

Code

서버: 바이너리로 인코딩한 가격 흐름·python
import struct
import asyncio

async def stream_prices(websocket):
    while True:
        prices = await get_latest_prices()
        # 18 bytes per record:
        # symbol_id(uint16) + price(float64) + volume(float64)
        if not prices:
            await asyncio.sleep(0.1)
            continue
        out = bytearray()
        for sym_id, price, vol in prices:
            out += struct.pack('<Hdd', sym_id, price, vol)
        await websocket.send_bytes(bytes(out))
        await asyncio.sleep(0.1)  # 10 Hz
클라이언트: 바이너리 흐름 해석하기·javascript
ws.binaryType = 'arraybuffer';

ws.onmessage = (e) => {
  const view = new DataView(e.data);
  const recordSize = 18;
  const count = e.data.byteLength / recordSize;
  for (let i = 0; i < count; i++) {
    const o = i * recordSize;
    const sym    = view.getUint16( o,      true);
    const price  = view.getFloat64(o + 2,  true);
    const volume = view.getFloat64(o + 10, true);
    updateTicker(sym, price, volume);
  }
};

External links

Exercise

가짜 종목 집합으로 위 바이너리 가격 흐름을 구현해. 시세 1,000개의 전송 바이트 수와 해석 시간을 같은 내용의 JSON 과 비교하고 비율을 적어. REST /orders 엔드포인트를 추가하고 같은 WebSocket 으로 체결 알림을 보내되 주문의 진실의 원천은 REST 로 유지해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.