> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bonanzalab.io/llms.txt
> Use this file to discover all available pages before exploring further.

# WebSocket 이용 안내

> WebSocket 연결과 인증, 구독 요청, 연결 유지 및 재연결 방법을 안내합니다.

Dayfin WebSocket은 시세, 호가, 거래소 공지 등을 실시간으로 제공합니다.

REST API는 필요할 때마다 요청해서 응답을 받는 방식이지만, WebSocket은 연결을 한 번 맺고 원하는 데이터를 **구독**해 두면 새로운 데이터가 생길 때마다 서버가 바로 전달하는 방식입니다. 시세처럼 자주 바뀌는 데이터를 빠르게 받아야 할 때 적합합니다.

WebSocket 연결에는 REST API와 동일한 Access Token을 사용합니다. 토큰 발급 방법은 [토큰 발급 및 이용 안내](https://docs.bonanzalab.io/oauth.md)를 참고해 주세요.

## 이용 흐름

WebSocket은 연결, 구독, 수신의 세 단계로 이용합니다. 연결이 끊기면 구독 정보도 함께 사라지므로, 다시 연결한 뒤 구독을 처음부터 요청해야 합니다.

**1. 연결**

`Authorization` 헤더에 Access Token을 담아 WebSocket에 연결합니다.

**2. connected! 수신**

서버에서 `connected!` 메시지가 오면 연결이 완료된 것입니다.

**3. 구독 요청**

원하는 서비스의 구독 메시지를 보내고 성공 응답을 확인합니다.

**4. 실시간 데이터 수신**

구독한 서비스의 데이터가 실시간으로 전달됩니다.

## 연결

모든 서비스는 하나의 주소로 연결합니다.

```text theme={null}
wss://api.dayfin.io/v2/ws
```

연결 요청 시 Access Token을 `Authorization` 헤더에 담아 전달합니다. 쿼리스트링, 쿠키, `Sec-WebSocket-Protocol`로는 토큰을 전달할 수 없습니다.

```text theme={null}
Authorization: Bearer {ACCESS_TOKEN}
```

> [!NOTE]
>
> 인증과 연결이 완료되면 서버가 `connected!` 메시지를 보냅니다. 이 메시지는 JSON이 아닌 일반 문자열이며, 구독 요청은 이 메시지를 받은 후에 보내 주세요.

## 구독

연결이 완료되면 받고 싶은 데이터를 서비스 단위로 구독합니다. 구독한 서비스의 데이터만 전달되므로, 필요한 서비스와 대상만 골라 구독하면 됩니다.

### 구독 요청

`type`에 이용할 서비스명을, 나머지 필드에 구독 대상(마켓, 자산, 거래소 등)을 넣어 JSON으로 보냅니다. 서비스마다 필수 필드와 허용값이 다르므로 각 서비스 문서를 참고해 주세요.

```json theme={null}
{
  "type": "ticker",
  "marketCodes": ["KRW-BTC", "KRW-ETH"],
  "streamType": "snapshot"
}
```

구독이 정상 처리되면 `code`가 `"0000"`인 응답이 오고, 이후부터 실시간 데이터가 전달됩니다.

```json theme={null}
{ "type": "ticker", "code": "0000", "message": "Ok!" }
```

### 제공 서비스

| type | 설명 |
| - | - |
| `market_exchange` | 현재가(거래소) |
| `ticker` | 현재가(K-VWAP) |
| `ticker_currency` | 현재가(외화환산 K-VWAP) |
| `exchange_tot` | 일거래금액(거래소) |
| `market_tot` | 일거래금액(거래소-마켓별) |
| `kimp` | 시세프리미이엄 |
| `kimp_all` | 시세프리미엄(ALL) |
| `mass_trade` | 대량 체결 감지 |
| `notice` | 거래소 공지사항 |
| `whale` | 온체인 대량 이체 감지 |

이용 가능한 서비스와 거래소는 계약 조건에 따라 다를 수 있습니다.

### 여러 서비스 구독 · 변경 · 해제

하나의 연결에서 여러 서비스를 함께 구독할 수 있으며, 구독 메시지를 서비스별로 각각 보내면 됩니다.

구독 대상을 바꿀 때는 같은 `type`으로 **최종적으로 받고 싶은 전체 목록**을 다시 보내 주세요. 새 요청은 기존 목록에 추가되는 것이 아니라 기존 목록을 대체합니다. 예를 들어 `KRW-BTC`를 구독 중에 `KRW-ETH`를 추가하려면 `["KRW-BTC", "KRW-ETH"]`를 함께 보내야 합니다.

별도의 구독 해제 메시지는 제공되지 않습니다. 구독을 해제하려면 연결을 종료한 뒤 필요한 서비스만 다시 구독해 주세요.

> [!NOTE]
>
> 구독 수는 연결당 한도에 포함됩니다. 계산 기준과 한도는 [호출 정책](https://docs.bonanzalab.io/rate-limits.md)을 참고해 주세요.

## 메시지 처리

서버에서 오는 메시지는 형식과 데이터 타입이 일정하지 않을 수 있습니다. 다음 사항을 고려해 수신 로직을 구성해 주세요.

* 데이터는 Text 또는 **Binary** frame으로 올 수 있습니다. Binary는 UTF-8 문자열로 디코딩한 뒤 처리해 주세요.
* 가격과 수량은 문자열 또는 숫자로 올 수 있습니다.
* `code`는 `"0000"`, `"A1002"`처럼 항상 문자열로 비교해 주세요.

> [!NOTE]
>
> 실시간 데이터는 Best-effort 방식으로 제공됩니다. 빠른 전달을 우선하기 때문에 네트워크 상황에 따라 중복이나 누락이 발생할 수 있으며, 서로 다른 스트림 간 순서는 보장되지 않습니다. `sequenceId`, `timestamp` 등으로 중복·누락을 확인하고, 정확성이 중요한 데이터는 REST API로 보정해 주세요.

## 연결 유지와 재연결

WebSocket은 연결을 오래 유지하며 사용하는 만큼, 연결 상태 확인과 끊겼을 때의 재연결 처리가 중요합니다.

### Ping/Pong

서버는 연결이 살아 있는지 확인하기 위해 약 30초마다 PING frame을 보내며, 약 90초 이상 PONG 응답이 없으면 연결을 종료할 수 있습니다. 대부분의 WebSocket 라이브러리는 PONG을 자동으로 응답하므로 별도 구현은 필요 없습니다. 단, `{"type": "ping"}` 같은 JSON 메시지는 Heartbeat로 인정되지 않습니다.

### 토큰 만료

토큰은 연결을 맺는 시점에 검증됩니다. 연결 중 토큰이 만료되어도 즉시 끊기지 않을 수 있지만 연결 유지가 보장되지는 않으며, **재연결할 때는 반드시 유효한 토큰**이 필요합니다.

### 재연결

연결이 끊기면 기존 구독은 모두 사라집니다. 다음 순서로 다시 연결해 주세요.

1. 토큰 만료 여부를 확인하고, 필요하면 재발급합니다.
2. 새로 연결하고 `connected!`를 기다립니다.
3. 기존 구독을 **전부** 다시 요청합니다.

| 종료 코드 | 의미 |
| :-: | - |
| 1000 | 정상 종료 |
| 1006 | 네트워크 단절 등 비정상 종료 (클라이언트 감지) |
| 1011 | 서버 오류 또는 Heartbeat 타임아웃 |
| 1012 | 서버 재시작 또는 배포 |

## 오류 코드

요청을 처리할 수 없으면 `code`와 `message`가 담긴 응답이 전달됩니다.

```json theme={null}
{ "type": "error", "code": "0006", "message": "올바르지 않은 JSON 형식입니다." }
```

| 코드 | 설명 |
| - | - |
| `0006` | 올바르지 않은 JSON 형식 |
| `0008` | 서비스 이용 권한 없음 |
| `9996` | 비활성화된 서비스 |
| `9997` | 지원하지 않는 type |
| `9998` | type 누락 |
| `A1002` | 필수 입력값 누락 |
| `A1003` | 입력값 오류 |
| `A3000` | 지원하지 않거나 허용되지 않은 거래소 |
| `A3001` | 지원하지 않는 마켓 코드 |
| `A3002` | 지원하지 않는 자산 심볼 |
| `A3005` | 지원하지 않는 기준통화 |
| `9995` `9999` `A1001` | 서버 처리 오류. 잠시 후 다시 시도해 주세요. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.