세션
WebSocket을 통해 실시간 이벤트를 수신하려면 먼저 세션을 생성해야 합니다.
세션 생성 → WebSocket 연결 → 이벤트 구독 → 실시간 이벤트 수신
세션 유형
| 유형 | 인증 방식 | 최대 생성 수 | 설명 |
|---|---|---|---|
| 사용자 세션 (USER) | Access Token | 사용자당 3개 | 인증된 사용자의 이벤트만 구독 가능 |
| 클라이언트 세션 (CLIENT) | Client ID/Secret | 앱당 10개 | 애플리케이션 레벨 세션 |
지원 이벤트
| 이벤트 | 설명 | 필요 Scope |
|---|---|---|
CHAT |
채팅 메시지 | READ:LIVE_CHAT |
DONATION |
후원 (채팅 후원, 영상 후원) | READ:DONATION |
SUBSCRIPTION |
구독 | READ:SUBSCRIPTION |
WebSocket 연결
세션 생성 API 응답에 포함된 url로 WebSocket 연결을 수립합니다.
wss://{socketHost}/?type=OPENAPI_SESSION&sessionKey={sessionKey}
중요: 표준 WebSocket(RFC 6455)을 사용해야 합니다. Socket.IO, SockJS 등의 라이브러리는 자체 프로토콜 계층을 추가하므로 호환되지 않습니다. 브라우저의
new WebSocket(url)또는 각 언어의 표준 WebSocket 클라이언트를 사용하세요.
동시 연결
하나의 세션은 WebSocket 연결을 1개만 유지합니다. 이미 연결된 sessionKey로 새 WebSocket 연결을 수립하면 나중에 연결한 쪽이 해당 세션의 연결로 대체되고, 이전 연결은 이벤트 수신이 중단됩니다.
- 새 연결 요청은 거부되지 않습니다. 항상 성공하며 이전 연결을 대체합니다.
- 대체된 이전 연결은 서버가 즉시 종료하지 않습니다. 따라서 클라이언트에서는 연결이 살아있는 것처럼 보이지만 이벤트는 더 이상 전달되지 않습니다.
- 이벤트 구독은 세션에 저장되므로, 연결이 대체되어도 구독 내용은 그대로 유지됩니다.
주의: 같은
sessionKey를 여러 프로세스·탭·인스턴스에서 공유하면 가장 마지막에 연결한 쪽만 이벤트를 받습니다. 나머지는 조용히 이벤트를 놓치게 되므로, 동시에 여러 곳에서 이벤트를 수신해야 한다면 세션을 각각 생성해서 사용하세요.
제한사항
- 세션당 최대 30개의 이벤트 구독이 가능합니다.
- 세션은 생성 후 12시간 동안 유효합니다.
- 하나의 세션이 유지하는 WebSocket 연결은 1개입니다. 같은
sessionKey로 새로 연결하면 이전 연결이 대체됩니다. - WebSocket 연결은 AWS API Gateway WebSocket 기본 제약에 따라 최대 2시간 동안 유지됩니다. 2시간이 경과하면 서버에 의해 연결이 종료됩니다.
- WebSocket 연결에서 10분 동안 메시지가 없으면 WebSocket의 유휴 타임아웃으로 연결이 종료됩니다.
- WebSocket 연결이 서버에 의해 끊어질 수 있으므로, 자동 재연결 로직을 구현하는 것을 권장합니다.
참고: 세션 유효기간(12시간) 내에는 기존
sessionKey/url로 그대로 재연결할 수 있습니다. 재연결 시 기존 이벤트 구독도 유지되므로 재구독이 필요 없습니다. 세션이 만료되었거나(12시간 경과) 세션 수 제한으로 제거된 경우에만 세션을 새로 생성해야 합니다.
연결 유지 (PING)
유휴 타임아웃을 방지하려면 주기적으로 PING 메시지를 전송해야 합니다.
전송 형식
{"type":"PING"}
응답 형식
{"action":"PONG"}
- 1분 간격으로 PING 메시지를 전송하는 것을 권장합니다.
재연결
WebSocket 연결이 끊어진 경우, 세션이 아직 유효하다면(생성 후 12시간 이내) 기존 sessionKey/url로 그대로 재연결할 수 있습니다. 이때 기존 이벤트 구독은 유지되므로 재구독은 필요 없습니다.
1. 기존 WebSocket 객체가 남아 있다면 close()로 정리
2. 기존 url(sessionKey)로 WebSocket 재연결
3. (구독 유지됨 — 재구독 불필요)
이전 연결이 실제로 끊겼는지 확신할 수 없는 상황(네트워크 단절, 프로세스 재시작 등)에서도 재연결은 항상 성공합니다. 나중에 연결한 쪽이 세션의 연결이 되기 때문입니다. 다만 이전 연결을 정리하지 않으면 이벤트를 받지 못하는 소켓이 클라이언트에 남게 되므로, 재연결 전에 close()를 호출하는 것을 권장합니다.
세션이 만료되었거나(12시간 경과) 세션 수 제한으로 제거된 경우에만 세션을 새로 생성해야 하며, 세션 생성 엔드포인트는 세션 유형에 따라 다릅니다.
사용자 세션 (USER) 세션 재생성
- Access Token 만료 여부 확인, 만료 시 Refresh Token으로 갱신
- 세션 생성 (
GET /api/openapi/open/v1/sessions/auth, Access Token (Bearer) 필요) - WebSocket 연결 (응답의
url로 연결) - 이벤트 구독 (
POST /api/openapi/open/v1/sessions/events/subscribe/{event})
클라이언트 세션 (CLIENT) 세션 재생성
- 세션 생성 (
GET /api/openapi/open/v1/sessions/auth/client, Client ID/Secret 필요) - WebSocket 연결 (응답의
url로 연결) - 이벤트 구독 (
POST /api/openapi/open/v1/sessions/events/subscribe/{event})
주의: 클라이언트 세션을 새로 생성할 때는
/sessions/auth/client를 사용해야 합니다. USER용/sessions/auth는 Access Token(Bearer)이 필요하므로 Client ID/Secret만으로 호출하면 401이 발생합니다.
세션 API
사용자 세션 생성
GET /api/openapi/open/v1/sessions/auth
- 인증: Access Token (Bearer)
응답
| 필드 | 타입 | 설명 |
|---|---|---|
url |
string | WebSocket 연결 URL |
클라이언트 세션 생성
GET /api/openapi/open/v1/sessions/auth/client
- 인증: Client ID/Secret
응답
| 필드 | 타입 | 설명 |
|---|---|---|
url |
string | WebSocket 연결 URL |
사용자 세션 목록 조회
애플리케이션에 속한 사용자 세션 목록을 조회합니다.
GET /api/openapi/open/v1/sessions
- 인증: Client ID/Secret
Query 파라미터
| 파라미터 | 타입 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|
page |
number | X | 0 |
페이지 번호 (0부터 시작) |
size |
number | X | 20 |
페이지 크기 (1~50) |
응답
| 필드 | 타입 | 설명 |
|---|---|---|
data |
array | 세션 목록 |
data[].sessionKey |
string | 세션 식별자 |
data[].connectedDate |
string | null | 연결 시각 (ISO 8601). 미연결 시 null |
data[].disconnectedDate |
string | null | 연결 해제 시각 (ISO 8601). 해제된 적 없으면 null |
data[].subscribedEvents |
array | 구독 중인 이벤트 목록 |
data[].subscribedEvents[].eventType |
string | "CHAT" | "DONATION" | "SUBSCRIPTION" |
data[].subscribedEvents[].channelId |
string | null | 구독 대상 채널 ID |
클라이언트 세션 목록 조회
애플리케이션에 속한 클라이언트 세션 목록을 조회합니다.
GET /api/openapi/open/v1/sessions/client
- 인증: Client ID/Secret
Query 파라미터
| 파라미터 | 타입 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|
page |
number | X | 0 |
페이지 번호 (0부터 시작) |
size |
number | X | 20 |
페이지 크기 (1~50) |
응답
| 필드 | 타입 | 설명 |
|---|---|---|
data |
array | 세션 목록 |
data[].sessionKey |
string | 세션 식별자 |
data[].connectedDate |
string | null | 연결 시각 (ISO 8601). 미연결 시 null |
data[].disconnectedDate |
string | null | 연결 해제 시각 (ISO 8601). 해제된 적 없으면 null |
data[].subscribedEvents |
array | 구독 중인 이벤트 목록 |
data[].subscribedEvents[].eventType |
string | "CHAT" | "DONATION" | "SUBSCRIPTION" |
data[].subscribedEvents[].channelId |
string | null | 구독 대상 채널 ID |
이벤트 구독
세션에 이벤트 구독을 추가합니다. 모두 Access Token (Bearer) 인증을 사용합니다.
POST /api/openapi/open/v1/sessions/events/subscribe/{event}
{event}에 들어갈 수 있는 값:
chat— 채팅 이벤트 (Scope:READ:LIVE_CHAT)donation— 후원 이벤트 (Scope:READ:DONATION)subscription— 구독 이벤트 (Scope:READ:SUBSCRIPTION)
Query 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
sessionKey |
string | O | 이벤트를 구독할 세션 키 |
응답: 200 OK, 응답 본문 없음
이벤트 구독 해제
세션에서 이벤트 구독을 해제합니다. 모두 Access Token (Bearer) 인증을 사용합니다.
POST /api/openapi/open/v1/sessions/events/unsubscribe/{event}
{event}에 들어갈 수 있는 값:
chat— 채팅 이벤트 (Scope:READ:LIVE_CHAT)donation— 후원 이벤트 (Scope:READ:DONATION)subscription— 구독 이벤트 (Scope:READ:SUBSCRIPTION)
Query 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
sessionKey |
string | O | 이벤트 구독을 해제할 세션 키 |
응답: 200 OK, 응답 본문 없음
WebSocket 메시지 형식
이벤트 구독 후 수신되는 메시지는 다음과 같은 공통 JSON 형식입니다.
{
"event": "CHAT",
"data": { ... }
}
| 필드 | 타입 | 설명 |
|---|---|---|
event |
string | "CHAT" | "DONATION" | "SUBSCRIPTION" |
data |
object | 이벤트별 상세 데이터 |