본문 바로가기
✨ python/FastAPI

[FastApi, React] 업비트 WebSocket으로 실시간 시세 불러오기

by 환풍 2025. 12. 10.
728x90
반응형

결과화면

 

console에 보다시피, 메시지를 계속 받아와 화면에 뿌려지고 있다.


1. wscat 설치

npm install -g wscat

 

 

2-1.FastAPI , app.py ( 방법 1)

1) 필요한 라이브러리들 Import

  • FastAPI/WebSocket → 웹소켓 서버 만들 때 필요
  • websockets → FastAPI 내부에서 Upbit WebSocket과 연결할 때 필요
  • json → 구독 메시지를 JSON 문자열로 바꿀 때 사용
  • chart_router → 기존 REST API 라우터(chart/candle) 등록

2) CORS 설정

React 프론트엔드(3000포트)가 API를 호출할 때 CORS 오류가 생기지 않도록 허용.

3) 업비트 웹소켓 주소

FastAPI가 대신 Upbit WebSocket에 연결해서 데이터를 가져온 다음 React로 전달해 준다.

 

★ 4) 핵심: FastAPI → Upbit → React 로 중계(WebSocket Proxy)

@app.websocket("/ws/ticker")
async def ticker(ws: WebSocket):

클라이언트(React)가 접속하는 WebSocket URL

React는 ws://백엔드주소/ws/ticker 로 접속한다.

 

await ws.accept()

React(클라이언트)의 연결을 수락

 

async with websockets.connect(UPBIT_WS_URL) as upbit_ws:

FastAPI 서버가 업비트 웹소켓과 연결

서버는 React와 동시에 업비트와도 연결이 된다. 즉, FastAPI 중계(proxy) 서버가 된다.

 

subscribe = [
          {"ticket": "proxy"},
          {"type": "ticker", "codes": ["KRW-BTC"]},
]

await upbit_ws.send(json.dumps(subscribe))

업비트에게 "나 BTC 티커 데이터 보고싶어." 라고 구독 메시지를 보낸다.

 

while True:
      data = await upbit_ws.recv()
      await ws.send_text(data)
  • 업비트 → FastAPI 서버로 실시간 데이터 수신
  • FastAPI → React로 즉시 전달

즉, FastAPI는 중간에서 데이터만 전달하는 역할을 한다.

from fastapi.middleware.cors import CORSMiddleware
from fastapi import FastAPI, WebSocket
from controller.chart import router as chart_router
import websockets
import json

app = FastAPI()

app.include_router(chart_router)

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

UPBIT_WS_URL = "wss://api.upbit.com/websocket/v1"
# ------------------------------
#   WebSocket은 반드시 app.py에
# ------------------------------
@app.websocket("/ws/ticker")
async def ticker(ws: WebSocket):
    await ws.accept()

    async with websockets.connect(UPBIT_WS_URL) as upbit_ws:

        subscribe = [
            {"ticket": "proxy"},
            {"type": "ticker", "codes": ["KRW-BTC"]},
        ]

        await upbit_ws.send(json.dumps(subscribe))

        while True:
            data = await upbit_ws.recv()
            await ws.send_text(data)

 

{"ticket": "proxy"} — proxy는 아무 문자열이나 가능함

 - 보통 프로그램이름, 클라이언트 ID, 브라우저 구분 등으로 넣는다.
ex ) 
{"ticket": "react-dashboard"}
{"ticket": "fastapi-server"}
{"ticket": "client-01"}


{"type": "ticker"} — 이건 반드시 정해진 값 중 하나여야 함

1. ticker - 현재 시세 정보
2. trade - 체결 정보
3. orderbook - 호가 정보

2-1.FastAPI , ws > ticker_ws.py ( 방법 2)

 

from fastapi import APIRouter, WebSocket

import websockets
import json

router = APIRouter()

UPBIT_WS_URL = "wss://api.upbit.com/websocket/v1"


@router.websocket("/ws/ticker")
async def ticker(ws: WebSocket):
    await ws.accept()

    async with websockets.connect(UPBIT_WS_URL) as upbit_ws:

        subscribe = [
            {"ticket": "proxy"},
            {"type": "ticker", "codes": ["KRW-BTC"]},
        ]

        await upbit_ws.send(json.dumps(subscribe))

        while True:
            data = await upbit_ws.recv()
            await ws.send_text(data)

 

app.py

이렇게 관리하게 되면 , app.py에 WebSocket을 때려 박는 것보다 훨씬 유지보수가 쉽고 간편하게 된다.

 


3. React

 

1) FastAPI WebSocket 서버에 연결

useEffect(() => {
     const ws = new WebSocket("ws://127.0.0.1:8000/ws/ticker");

FastAPI의 /ws/ticker와 연결됨 → 조회할 때 바로 실시간 데이터 들어옴.

 

2) 메시지를 받을 때 실행되는 코드

ws.onmessage = async (event) => {
      const text = await event.data.text(); // Blob → text 변환
      const json = JSON.parse(text); // JSON 변환

      console.log("Ticker:", json);
      setData(json); // 화면 업데이트
};

여기서 중요한 포인트

  • FastAPI가 보내는 데이터는 Blob 타입으로 오기 때문에
    text()로 변환해야 JSON.parse 가능
  • 변환 후 React 화면에 보여주기 위해 setData(json) 저장

3) 컴포넌트 종료 시 WebSocket 닫기

return () => ws.close();

안 닫으면 메모리 누수 발생.

import { useEffect, useState } from "react";

function Wbsocket() {
    const [data, setData] = useState(null);
    useEffect(() => {
        const ws = new WebSocket("ws://127.0.0.1:8000/ws/ticker");

        ws.onmessage = async (event) => {
            const text = await event.data.text();   // 🔥 Blob → text 변환
            const json = JSON.parse(text);          // 이제 JSON.parse 가능

            console.log("Ticker:", json);

            setData(json); // 🔥 화면 업데이트
        };
        return () => ws.close();
    }, []);

    return (
        <div>
            <h1>WebSocket Data</h1>
            <pre>{JSON.stringify(data, null, 2)}</pre>
        </div>
    );
}
export default Wbsocket;

 


 

Upbit WS → FastAPI 서버 → React WebSocket

< 전체 동작 요약 >

 

  • React가 ws://localhost:8000/ws/ticker로 접속
  • FastAPI는 React 접속을 수락
  • FastAPI는 업비트 WebSocket에도 동시에 연결
  • FastAPI가 업비트에 ticker 구독 요청
  • 업비트 → FastAPI로 실시간 데이터 전송
  • FastAPI → React로 그대로 재전송(proxy)
  • React에서 Blob → text → JSON 변환
  • 실시간으로 화면 업데이트

 

 

728x90
반응형

댓글