업비트 웹소켓 — 시세 데이터 vs 상장 공지
업비트 웹소켓(WebSocket)을 검색하셨다면 원하는 것은 대개 둘 중 하나입니다. 이미 거래 중인 종목의 실시간 시세 데이터(현재가, 호가, 체결)이거나, 업비트가 신규 상장을 공지하는 순간의 알림입니다. 업비트의 기본 웹소켓은 첫 번째만 제공합니다. 두 번째는 제공하지 않습니다. 이 가이드는 두 가지를 모두, 실제로 동작하는 코드와 함께 다룹니다.
두 개의 소켓, 두 가지 역할
| 피드 | 스트리밍 내용 | 용도 |
|---|---|---|
| 업비트 기본 웹소켓 | 이미 상장된 KRW / BTC / USDT 마켓의 실시간 현재가·호가·체결 | 차트, 주문 집행, 마켓 메이킹 |
| 공지 웹소켓 | 신규 상장, 유의종목 지정 해제, 거래지원 종료(상장폐지)가 공지되는 순간의 이벤트 | 유동성이 붙기 전에 상장에 대응 |
업비트 기본 시세 웹소켓
업비트는 공개 시세 웹소켓을 wss://api.upbit.com/websocket/v1에서 제공합니다. 구독은 JSON 배열을 보내서 합니다. 티켓 객체, 하나 이상의 타입 객체(ticker, trade, orderbook), 그리고 선택 사항인 포맷 객체로 구성됩니다. 마켓 코드는 KRW-BTC 같은 형태입니다. 응답은 바이너리 프레임에 담긴 UTF-8 JSON으로 옵니다.
# pip install "websockets>=14" import asyncio, json, websockets async def main(): url = "wss://api.upbit.com/websocket/v1" sub = [ {"ticket": "demo"}, {"type": "ticker", "codes": ["KRW-BTC", "KRW-ETH"]}, {"format": "DEFAULT"}, ] async with websockets.connect(url) as ws: await ws.send(json.dumps(sub)) async for raw in ws: msg = json.loads(raw) # 프레임은 UTF-8 JSON print(msg["code"], msg["trade_price"]) asyncio.run(main())
이미 상장된 코인을 추적할 때는 이것이 맞는 도구입니다. 하지만 눈에 잘 띄지 않는 제약이 하나 있습니다. 마켓 코드를 미리 지정해야 한다는 점입니다.
기본 피드로 신규 상장을 알 수 없는 이유
업비트의 신규 상장 종목은 거래가 시작되는 순간까지 마켓 코드로 존재하지 않습니다. 미리 구독할 대상이 없는 셈입니다. 상장 결정은 업비트 공지사항에 공지로 게시되며, 이는 시세 웹소켓과 별개의 채널입니다. KRW-XYZ가 ticker 스트림에 나타날 때쯤이면 가격 움직임의 첫 번째이자 가장 큰 구간은 이미 지나간 경우가 많습니다. 기본 웹소켓은 상장의 결과이지, 상장의 신호가 아닙니다.
공지 웹소켓: 공지가 게시되는 순간 상장을 포착
CryptoListing.ws는 전용 공지 웹소켓을 운영합니다. 업비트가 신규 상장, 유의종목 지정 해제, 거래지원 종료(상장폐지)를 공지하는 즉시 구조화된 JSON 이벤트를 실시간으로 전송합니다. 공지를 대신 감지해 결과를 푸시해 드리므로, 공지 페이지를 직접 확인할 필요가 없습니다.
| 항목 | 값 |
|---|---|
| 엔드포인트 — 서울 (업비트 + 빗썸) | wss://kr.cryptolisting.ws — AWS 서울(ap-northeast-2c). 한국에서 업비트·빗썸을 거래하는 봇에 엔드투엔드로 가장 빠릅니다. |
| 엔드포인트 — 도쿄 (바이낸스 + 업비트 + 빗썸) | wss://jp.cryptolisting.ws — AWS 도쿄(ap-northeast-1a). |
| 인증 | 업그레이드 요청의 X-API-Key 헤더 (모든 엔드포인트에서 같은 키) |
| 포맷 | 바이너리 프레임, UTF-8 JSON, 마이크로초 정밀도 타임스탬프 |
| 업비트 이벤트 | spot_listing, caution_released, spot_delisting |
# pip install "websockets>=14" — 헤더 파라미터는 additional_headers # (extra_headers는 websockets v14부터 제거됨) import asyncio, json, websockets API_KEY = "dsk_your_key_here" WS_URL = "wss://kr.cryptolisting.ws" # 서울, 업비트 + 빗썸 async def run(): headers = {"X-API-Key": API_KEY} async with websockets.connect(WS_URL, additional_headers=headers) as ws: async for raw in ws: msg = json.loads(raw) if msg["type"] == "announcement" and msg["publisher"] == "upbit": for ticker in msg["ticker"].split(","): print(msg["listingType"], ticker, msg["title"]) asyncio.run(run())
메시지 포맷
모든 공지는 하나의 JSON 객체입니다. 한 공지가 여러 코인을 다룰 때 ticker는 쉼표로 구분될 수 있으므로 항상 분리해서 처리하세요.
{
"type": "announcement",
"title": "[Trade] New Listing of TOKEN (TOKEN) KRW Market",
"ticker": "TOKEN",
"publisher": "upbit",
"listingType": "spot_listing",
"detectedTimestampUs": 1710345000005000,
"dispatchTimestampUs": 1710345000006000
}
두 피드를 함께 사용하기
두 소켓은 서로 보완합니다. 공지 웹소켓을 구독해 원화(KRW) 마켓 상장 사실을 먼저 알고, 이벤트가 도착하는 즉시 새 마켓 코드로 업비트 기본 ticker 스트림을 열어 가격을 따라가면 됩니다. 한쪽은 트리거, 다른 한쪽은 텔레메트리입니다.
클라이언트를 직접 만드시나요? 파이썬으로 업비트·빗썸 상장 봇 만들기 튜토리얼이 markets 필드, 유의종목 지정 해제, 상장폐지, 드라이런까지 전체 과정을 다룹니다. 전체 API 레퍼런스(영문): WebSocket API 레퍼런스, 메시지 스키마, Python / Node.js 코드 예제.
자주 묻는 질문 (FAQ)
업비트 웹소켓 엔드포인트는 무엇인가요?
공개 시세 소켓은 wss://api.upbit.com/websocket/v1입니다. JSON 배열(ticket + type + codes)을 보내면 이미 존재하는 마켓에 대한 UTF-8 JSON 프레임을 받습니다.
업비트 기본 웹소켓으로 신규 상장 알림을 받을 수 있나요?
아니요. 이미 존재하는 마켓만 구독할 수 있고, 상장 결정은 시세 소켓이 아니라 업비트 공지사항에 게시됩니다. 이를 위해서는 상장 공지 API가 필요합니다.
한국에 있는 봇을 위한 더 낮은 지연의 엔드포인트가 있나요?
네. wss://kr.cryptolisting.ws는 AWS 서울에서 운영되며 업비트와 빗썸 공지를 전송합니다. 한국에 위치한 봇은 서울→도쿄 네트워크 구간을 거치지 않아도 됩니다. 업비트만 받으려면 ?cex=upbit를 붙이세요. 도쿄 엔드포인트는 바이낸스, 업비트, 빗썸을 전송하며, 로빈후드는 세 번째 엔드포인트 wss://us.cryptolisting.ws에서 제공합니다.
빗썸과 바이낸스는요?
같은 공지 피드가 빗썸(서울과 도쿄 엔드포인트 모두)과 바이낸스(도쿄 전용)도 다룹니다. 도쿄나 서울 엔드포인트에서 ?cex= 필터로 거래소를 고를 수 있습니다. 로빈후드(영문 페이지)도 전용 미국 엔드포인트(wss://us.cryptolisting.ws)로 제공합니다.
API 키 받기
텔레그램으로 문의해 업비트 상장 공지 스트리밍을 시작하세요. 요금제 및 등급, 전체 문서(영문), 업비트 상장 알림 개요도 확인해 보세요.
텔레그램에서 API 키 받기