실시간 데이터 주고받기
채널(room.plugin)로 같은 채팅방 사람들끼리 채팅 메시지가 아닌 데이터를 주고받고, 받은 데이터를 검증하는 흐름을 설명해요.
마지막 수정 2026년 10월 17일
채널을 쓰면 같은 채팅방에 있는 사람들끼리 채팅 메시지가 아닌 데이터를 실시간으로 주고받을 수 있어요. 함께 보기, 게임, 투표처럼 모두의 화면을 맞춰야 하는 기능에 써요. 함수 목록과 한도의 정본은 채널 API와 한도예요.
채널 열기
room.plugin.add(채널이름)은 그 이름의 채널 객체를 돌려줘요. 같은 이름으로 다시 부르면 같은 객체를 돌려줘요. 같은 채널 이름을 쓰는 사람끼리 데이터를 주고받아요.
U.chat('my-room').on('after.create', function (room) {
var dice = room.plugin.add('dice');
});
채널 이름은 영문·숫자로 시작하고 영문·숫자·_·-로 된 64자 이내로 지으세요(save는 이 규칙을 지키지 않으면 거절돼요). 다른 기능과 겹치지 않게 내 서비스 이름을 앞에 붙이면 좋아요.
보내기
데이터는 언제나 배열로 보내요.
dice.send([4]); // 채팅방 모두에게(나 포함)
dice.sendTo('홍길동', ['hello', 1]); // 그 닉네임 한 사람에게만
- 배열 원소는 문자열·숫자·불리언만 돼요. 객체·배열·
null은 전송 중에 빠지므로, 구조가 필요하면 원소를 나눠 보내거나 문자열로 만들어 보내세요. send로 보낸 데이터는 보낸 사람 자신도 받아요.sendTo는 받는 사람만 받아요. 숨김 채팅금지된 사람이 보내면 둘 다 본인에게만 되돌아가요.- 무료 채팅방은 최근 60초 동안 받는 사람 수 합계에 한도가 있어, 넘으면 오류 428이 나요. 자주 보내는 기능은 보내는 횟수를 줄이세요. → 채널 API와 한도
받기
dice.onReceived(function (room, msg) {
// msg.user 보낸 사람 { nick, id, level, auth, ... }
// msg.type 0 모두에게 보낸 것, 1 나에게만 보낸 것
// msg.data 보낸 배열
});
콜백은 다른 이벤트처럼 (room, data)를 받아요. 같은 데이터는 이벤트의 before.plugin, after.plugin으로도 와요.
받은 데이터 검증하기
채널 데이터는 채팅방에 있는 누구나 개발자 도구로 원하는 값을 넣어 보낼 수 있어요. 받은 쪽에서는 항상 검증해요.
- 원소 개수와 타입, 값의 범위를 확인하고 맞지 않으면 버려요.
- 화면에 넣을 때는
textContent를 쓰거나 이스케이프해요.room.print는 HTML로 해석해요. - 보낸 사람을 확인할 때는
msg.user.auth(0 손님, 1 회원, 2 부관리자, 3 관리자, 4 서버)를 봐요. 닉네임만으로 판단하지 마세요. - 결과의 공정함이 중요하면(주사위, 추첨) 한 사람이 정한 값을 그대로 믿지 말고, 서버가 정해 서버 API로 보내게 하세요. → 서버에서 채팅방으로 알림 보내기
입력 명령 받기
addParser를 등록하면 기본 스킨 입력창에 !채널이름 인자...를 입력했을 때 그 함수가 인자 배열을 받아요. 그 입력은 채팅 메시지로 전송되지 않아요. 함수가 false를 돌려주면 처리하지 않은 것으로 보고 입력이 일반 메시지로 전송돼요.
dice.addParser(function (args) {
// 입력: !dice → args: []
dice.send([Math.floor(Math.random() * 6) + 1]);
});
상태 저장하기
save(배열)은 채널의 마지막 상태를 서버에 저장해요. 나중에 들어온 사람은 입장할 때 저장된 값을 받아요. clear()는 저장한 값을 지워요.
- 부관리자 이상만 저장할 수 있어요.
- 저장은 지금 있는 사람에게 보내지 않아요. 지금 있는 사람에게도 알리려면
send를 함께 부르세요. - 입장할 때 받는 저장 값은
type1(나에게만)로, 보낸 사람이 서버 사용자(auth4, 닉네임 없음)로 와요. 누가 저장했는지는 알 수 없어요. - 저장 크기 한도가 있고, 무료 채팅방은 다른 채널에 저장하면 기존 채널의 저장 값이 지워져요. → 채널 API와 한도
// 관리자가 고른 영상 아이디를 저장하고 지금 있는 사람에게도 보냄
video.save(['dQw4w9WgXcQ']);
video.send(['dQw4w9WgXcQ']);
닫기
destroy()는 채널을 닫고 등록한 받기·명령 함수를 함께 버려요. 같은 이름으로 다시 add하면 새 채널이 열려요.
전체 코드
!dice를 입력하면 주사위를 굴려 모두에게 알리는 예시예요.
<script>U=window.U=window.U||{},U.events=U.events||[],U.chat=function(n){return{on:function(e,t){U.events.push([n,e,t])},off:function(e){for(var t=U.events.length;t>0;)U.events[--t][0]==n&&U.events[t][1]==e&&U.events.splice(t,1)}}};</script>
<script async src="https://client.uchat.io/uchat.js"></script>
<u-chat room="my-room" style="display:inline-block; width:100%; max-width:500px; height:500px;"></u-chat>
<script>
function escapeHtml(text) {
return String(text).replace(/[&<>"']/g, function (c) {
return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c];
});
}
U.chat('my-room').on('after.create', function (room) {
var dice = room.plugin.add('dice');
dice.onReceived(function (room, msg) {
var value = msg.data[0];
if (msg.data.length !== 1 || typeof value !== 'number') return;
if (value % 1 !== 0 || value < 1 || value > 6) return;
var nick = msg.user ? msg.user.nick : '?';
room.print(escapeHtml(nick) + '님의 주사위: ' + value);
});
dice.addParser(function () {
dice.send([Math.floor(Math.random() * 6) + 1]);
});
});
</script>
봐도 잘 이해가 되지 않나요? 문의 게시판에 질문을 남겨 주세요.