업비트 시세조회 API를 사용한 간단한 웹소켓 로직

프로젝트
프로젝트
카테고리
Dev
작성일
2023-07-15
태그
TIL
작성자
꾸생
상태
공개
업비트에서 제공하는 시세 API를 사용해 간단한 웹앱을 만들어 사용하다 이번에 마이그레이션을 진행했다.
기존 웹소켓 로직은 한 번 에러가 나면 이후 새로고침을 하지 않는 이상 그로기 상태에 빠져버리는데, 에러 처리 로직을 추가 작성했다.

요청 데이터 준비

필드명
내용
타입
필요 여부
type
수신할 시세 타입.(현재가 -> ticker체결 -> trade,호가 ->orderbook)
String
O
codes
수신할 시세 종목 정보.주의 : codes 필드에 명시되는 종목들은 대문자로 요청해야 합니다.
List
O
isOnlySnapshot
시세 스냅샷만 제공
Boolean
X
isOnlyRealtime
실시간 시세만 제공
Boolean
X
const currency = [ { ticket: 'kku.dev' }, { type: 'ticker', codes: ['BTC/KRW'] }, { format: 'SIMPLE' } ]
요청 형식은 위 형태로 작성하는데, ticket의 경우 공식 문서에 용도를 식별하기 위한 값으로 대상을 식별하며 되도록 유니크한 값을 사용하도록 권장한다고 나와있다. 내가 선택한 방법은 가장 대표적으로 사용하는 UUID를 이용했고 uuid 라이브러리를 사용해서 쉽게 만들어낼 수 있다.
타입에 시세는 현재가와 온리 비트코인이므로 ticket, ‘BTC/KRW’ 문자열만 배열로 넣

소켓 생성

const isNetwork = () => window.navigator.onLine // 네트워크 연결 체크 let timeout: NodeJS.Timeout | null = null // Timeout 객체 let retryCount = 1 // 서버 재접속 시도 횟수 const limitCount = 3 // 재시도 제한 횟수 const setTime = 5000 // ms 재시도 시간 간격 let socket: WebSocket | null = null // 소켓 생성
 
웹 소켓과 예외처리에 필요한 변수 작성

소켓 함수 작성

// 소켓 초기화 function initSocket() { socket = new WebSocket('wss://api.upbit.com/websocket/v1') socket.binaryType = 'arraybuffer' socket.onopen = function () { console.log('on socket!') retryCount = 1 // 재시도 횟수 초기화 this.send(JSON.stringify(currency)) console.log('Connect socket!') } socket.onmessage = (evt) => { const enc = new TextDecoder('utf-8') const arr = new Uint8Array(evt.data) const data = JSON.parse(enc.decode(arr)) console.log(data) // <-- 웹 서버로 부터 받은 데이터 } // 소켓 에러 핸들링 socket.onerror = (e) => { console.dir(e) if (socket === null) return if (!isNetwork()) { toast.warn(`인터넷 연결 오류 또는 서버 점검 중입니다. 나중에 다시 시도해 주세요 🙏`) socket.close() } } // 소켓 닫힘 socket.onclose = (e) => { console.dir(`비정상적 종료: ${e.code}`) if (e.wasClean || e.code === 1000) { console.log(`서버 연결 해제`) } else if (e.code === 1006) { // 비정상적 오류 timeout = setTimeout(() => { // 제한 횟수만큼 연결 재시도 console.log(`${setTime / 1000}초 후 재연결 시도합니다. (${retryCount++})`) if (retryCount > limitCount) { clearTimeOut() console.log(`서버가 응답하지 않습니다. 나중에 다시 시도해주세요. 🙏`) } else { initSocket() } }, setTime) } } }

Event

  • onopen: 소켓 연결이 열렸을 때
  • onmessage: 소켓으로 데이터를 수신했을 때
  • onerror: 소켓 연결이 일부 데이터 전송의 실패 등 오류로 인해 닫힐 때
  • onclose: 소켓 연결이 닫힐 때
중요 기능의 로직은 onmessage 이벤트에 작성하고 데이터를 전달받은 후 웹 상에서 렌더링 되도록 코드를 작성한다.

에러처리

웹 소켓을 이용하면서 발생되는 이벤트에 맞춰 알맞은 에러처리 로직을 작성해주는데, 위 코드에서는 onerroronclose 이벤트에 대부분의 로직을 작성했다.
onerror 이벤트에서 발생했을 때 인터넷 연결이 없는 상태라면 재시도를 할 필요가 없으므로 소켓을 그대로 종료시키도록 작성한다. 만약 다른 이유로 소켓이 종료 됐다면 서버가 살아있는지 확인해 보고 재접속 시도를 해보는 등 다른 작업을 할 수 있다.
이번에 구현한 프로젝트는 소켓 연결이 필수이므로 onclose 이벤트에 로직을 구현했다. 정상적인 로직에 의해 소켓이 연결 종료됐다면 그대로 끝내고 아닌 경우 재시도 로직을 실행한다.

소켓 종료

socket.close() socket.close(code) socket.close(code, reason
사용자가 임의에 코드로 소켓을 종료시킬 수 있고 onclose 이벤트에서 받아 사용할 수 있다.

에러코드

 
이미 약속된 에러 코드도 있으니 주의해서 사용한다.