실시간 (Realtime)
WebSocket 기반 실시간 통신 API입니다. 채팅, 알림, 협업 기능 등에 사용합니다.
📌
cb.realtime은 카테고리(category) 기반 pub/sub 입니다. 카테고리는 콘솔에서 생성하거나 서버에서 자동 생성된 이름(예:chat-room-1)을 사용합니다.
연결
typescript
// Public Key 만으로 연결 (게스트)
await cb.realtime.connect()
// 또는 앱 멤버 토큰으로 연결
const guest = await cb.auth.signInAsGuestMember()
await cb.realtime.connect({ accessToken: guest.access_token })connect() 의 옵션:
| 옵션 | 타입 | 기본값 | 설명 |
|---|---|---|---|
accessToken | string | - | 앱 멤버 JWT (지정 시 Public Key 대신 사용) |
userId | string | - | 표시용 사용자 식별자 |
maxRetries | number | 5 | 자동 재연결 횟수 |
retryInterval | number | 1000 | 재연결 간격 (ms) |
timeout | number | 30000 | 응답 대기 타임아웃 (ms) |
debug | boolean | false | 디버그 로그 |
카테고리 구독
typescript
const chat = await cb.realtime.subscribe('chat-room-1')
console.log(chat.info.category, chat.info.persist)subscribe() 가 반환하는 Subscription 객체는 다음 메서드를 가집니다:
| 메서드 | 설명 |
|---|---|
onMessage(handler) | 메시지 수신 핸들러 등록 (해제 함수 반환) |
send(data, options?) | 메시지 전송 |
getHistory(limit?) | 히스토리 조회 (persist=true 카테고리만) |
unsubscribe() | 구독 해제 |
메시지 수신 / 전송
typescript
const chat = await cb.realtime.subscribe('chat-room-1')
// 수신 핸들러 등록
const off = chat.onMessage<{ text: string; from: string }>((msg) => {
console.log('새 메시지:', msg.data.text, 'from', msg.data.from)
})
// 전송 (기본적으로 발신자에게도 echo 됨)
await chat.send({ text: '안녕!', from: 'me' })
// echo 없이 전송
await chat.send({ text: '...' }, { includeSelf: false })
// 핸들러 해제
off()히스토리 조회
persist=true 로 설정된 카테고리만 메시지를 저장합니다.
typescript
if (chat.info.persist) {
const history = await chat.getHistory(50)
history.messages.forEach((m) => {
console.log(m.from, m.data, new Date(m.sentAt).toISOString())
})
}구독 해제 / 연결 종료
typescript
await chat.unsubscribe()
cb.realtime.disconnect()연결 상태
typescript
const state = cb.realtime.getState()
// 'disconnected' | 'connecting' | 'connected' | 'reconnecting'
cb.realtime.connectionId // 현재 연결 ID
cb.realtime.appId // 연결된 앱 IDAI 스트리밍
LLM 응답을 토큰 단위로 스트리밍 받을 수 있습니다.
typescript
await cb.realtime.connect()
const session = await cb.realtime.stream(
[{ role: 'user', content: '안녕하세요' }],
{
onToken: (token) => process.stdout.write(token),
onDone: (result) => console.log('\n완료:', result.fullText),
onError: (e) => console.error('에러:', e)
},
{ provider: 'gemini', model: 'gemini-2.0-flash', temperature: 0.7 }
)
// 필요 시 중지
await session.stop()자동 재연결
SDK는 maxRetries 만큼 자동으로 재연결을 시도합니다. 별도 핸들러 등록 없이 동작합니다.
Presence / Typing / Read-receipt
2026-04-27 단일화 이후 cb.realtime 이 presence / typing / read-receipt 의 단일 SoT 입니다. cb.database.connectRealtime 은 DB 변경 구독 전용으로 분리됐고, presence/typing 메서드는 SDK v1.13 에서 deprecate, v2 에서 제거됐습니다.
typescript
// 본인 온라인 상태 publish (다른 디바이스/사용자에게 알림)
await cb.realtime.setPresence('online', { device: 'web', metadata: { nickname: '홍길동' } })
// 클라이언트가 disconnect 되면 자동으로 적용될 status 미리 등록
await cb.realtime.setPresenceOnDisconnect('offline')
// 특정 사용자 현재 상태 조회 (단건)
const info = await cb.realtime.getPresence('user_123')
// 여러 사용자 한 번에 조회
const map = await cb.realtime.getPresenceMany(['user_123', 'user_456'])
// 특정 사용자 상태 구독
const unsub = await cb.realtime.subscribePresence('user_123', (event) => {
console.log(event.userId, event.status, event.eventType) // join | leave | update
})
unsub() // 구독 해제typescript
// Typing indicator — 룸 단위 (chat 카테고리 / 게임 룸 등 임의 키)
await cb.realtime.startTyping('chat-room-123')
await cb.realtime.stopTyping('chat-room-123')
// 다른 사용자 typing 변경 구독
const offTyping = cb.realtime.onTypingChange('chat-room-123', (event) => {
console.log('현재 typing 중:', event.users) // userId[]
})
// Read-receipt — 메시지 ID 단위 읽음 표시
await cb.realtime.markRead('chat-room-123', 'msg_xxx')📌 presence 와 typing 은 in-memory 상태입니다(영구 저장 안 됨). 메시지/read-receipt 만 카테고리
persist=true옵션으로 영구 저장 가능.