서버에서 채팅방으로 알림 보내기
내 서버에서 서버 API(v2)로 채팅방 채널에 데이터를 보내고, 페이지 스크립트나 플러그인이 서버가 보낸 것만 골라 표시하는 흐름을 설명해요.
마지막 수정 2026년 10월 19일
내 서버에서 일어난 일(결제 완료, 새 글, 방송 시작 등)을 서버 API로 채팅방 채널에 보내면, 페이지 스크립트가 받아 채팅방에 표시할 수 있어요. 요청 형식과 오류 코드 전체는 서버 REST API에 있어요.
코드를 쓰지 않고 띄우기만 하려면 이벤트 알림창 플러그인을 켜고 plugin을 alertBox로 보내면 돼요. 글 등록·후원·구독 알림을 채팅 목록 안에 색 칸으로 보여 줘요. 후원 목표·방송 상태·점수판·카운트다운·순위표 플러그인도 같은 방식이에요.
흐름
- 페이지 스크립트(또는 플러그인)가 채팅방에서 채널(예:
notice-bot)을 열고 기다려요. - 내 서버가
POST https://api.uchat.io/v2/rooms/{id}/events로{"plugin":"notice-bot","data":[...]}를 보내요. - 채팅방에 지금 접속한 사람들이 그 채널로 데이터를 받아요. 보낸 사람은
auth가 4인 서버 사용자예요. - 페이지 스크립트가
auth를 확인하고 화면에 표시해요.
그냥 보내면 지금 접속한 사람에게만 가요. 아무도 없으면 받을 사람이 없을 뿐 오류는 아니에요. 나중에 들어온 사람에게도 보여야 하면 "save": true로 저장해요(아래 나중에 들어온 사람에게도).
API 키
관리 페이지 API 메뉴에서 API 키 발급을 눌러요. 이름을 정하고 권한에서 이벤트를 켜 두면 돼요. 키(uchat_…)는 발급할 때 한 번만 보이니 바로 복사해 둬요. 같은 화면에서 주소에 넣을 API 채팅방 아이디(room_…)도 복사해요.
API 키는 내 서버에만 둬요. 브라우저 자바스크립트에서 서버 API를 부르면 키가 드러나 누구나 서버 사용자로 데이터를 보낼 수 있어요. 키가 새면 API 메뉴에서 바로 폐기하거나 값을 다시 발급해요.
1. 받는 쪽 준비
<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) {
room.plugin.add('notice-bot').onReceived(function (room, msg) {
if (!msg.user || msg.user.auth !== 4) return; // 서버 API 또는 저장값만
if (msg.type !== 0) return; // 서버 API로 모두에게 보낸 것만
if (typeof msg.data[0] !== 'string') return;
room.print('[알림] ' + escapeHtml(msg.data[0]));
});
});
</script>
- 채팅방 사람들도 같은 채널 이름으로 데이터를 보낼 수 있어요. 서버가 보낸 것만 믿으려면
msg.user.auth === 4를 확인해요.auth4는 서버 API로 보낸 데이터 또는 부관리자 이상이 저장한 값이에요. 저장값은 입장할 때type1로 오므로, 모두에게 보낸 서버 API 데이터(type0)만 받으려면msg.type === 0도 확인해요. 닉네임을 지정해 보낸 서버 API 데이터도type1이라 저장값과 구분할 수 없어요. 서버 사용자는 닉네임이 없으므로 닉네임으로 확인하지 마세요. room.print는 HTML로 해석하므로 받은 글자는 이스케이프해서 넣어요.
2. 서버에서 보내기
curl:
curl -X POST https://api.uchat.io/v2/rooms/room_xxxxxxxxxxxxxxxx/events \
-H "Authorization: Bearer uchat_..." \
-H "Content-Type: application/json" \
-d '{"plugin":"notice-bot","data":["주문 #1024 결제가 완료되었습니다",12000]}'
data는 값 배열이에요. 문자열·숫자·불리언을 쓰고, 받는 쪽에는 모두 문자열로 가요.- 성공하면 HTTP 202와
{"data":{"sent":true}}, 실패하면 HTTP 상태와{"error":{"code":…,"message":…}}가 와요. - 보내기 전에 API 메뉴의 시험하기에서 같은 본문으로 실행해 볼 수 있어요.
Node.js(18 이상):
const ROOM = 'room_xxxxxxxxxxxxxxxx';
async function sendToRoom(plugin, data, options = {}) {
const res = await fetch(`https://api.uchat.io/v2/rooms/${ROOM}/events`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.UCHAT_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ plugin, data, ...options })
});
const result = await res.json();
if (!res.ok) console.warn('uchat api error', res.status, result.error);
return result;
}
await sendToRoom('notice-bot', ['주문 #1024 결제가 완료되었습니다', 12000]);
PHP:
<?php
function uchat_send($plugin, array $data, array $options = []) {
$ch = curl_init('https://api.uchat.io/v2/rooms/room_xxxxxxxxxxxxxxxx/events');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('UCHAT_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode(['plugin' => $plugin, 'data' => $data] + $options),
CURLOPT_RETURNTRANSFER => true,
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
return $result;
}
uchat_send('notice-bot', ['주문 #1024 결제가 완료되었습니다', 12000]);
한 사람에게만 보내기
본문에 "to"로 닉네임을 넣으면 그 사람에게만 보내요. 받는 쪽 msg.type은 1이에요. 한글 닉네임도 그대로 쓸 수 있어요.
curl -X POST https://api.uchat.io/v2/rooms/room_xxxxxxxxxxxxxxxx/events \
-H "Authorization: Bearer uchat_..." \
-H "Content-Type: application/json" \
-d '{"plugin":"notice-bot","to":"민지","data":["민지님, 쿠폰이 발급되었습니다"]}'
그 닉네임이 지금 채팅방에 없으면 HTTP 404 target_not_found가 와요.
나중에 들어온 사람에게도
"save": true를 붙이면 그 채널의 마지막 값으로 저장돼요. 지금 있는 사람에게 보내고, 나중에 들어오는 사람은 입장할 때 받아요(msg.type 1). 채팅방에 아무도 없을 때 보내도 저장돼요.
curl -X POST https://api.uchat.io/v2/rooms/room_xxxxxxxxxxxxxxxx/events \
-H "Authorization: Bearer uchat_..." \
-H "Content-Type: application/json" \
-d '{"plugin":"notice-bot","save":true,"data":["오늘 밤 12시 점검이 있어요"]}'
- 지우려면
"data":[]로 저장해요. 받는 쪽에는 빈 값이 가요. - 한도는 채널 저장과 같아요(무료 채팅방은 채널 하나·1KB). → 채널 API와 한도
- 저장값은 채팅방이 비거나 서버가 다시 시작돼도 남아요.
- 위 받는 쪽 예제는
msg.type !== 0을 버리므로, 저장값까지 받으려면 그 줄을 빼요.
자주 나는 오류
| 오류 | 뜻 | 할 일 |
|---|---|---|
401 missing_key, invalid_key |
키가 없거나 이 채팅방의 키가 아님 | Authorization: Bearer 헤더와 API 채팅방 아이디를 확인해요. 회원 연동 토큰이 아니라 API 키를 넣어요 |
403 insufficient_scope |
키에 이벤트 권한이 없음 | API 메뉴에서 그 키의 권한을 고쳐요 |
400 invalid_data |
data가 배열이 아니거나 줄바꿈 같은 제어 문자가 있음 |
[...] 모양으로, 줄바꿈 없이 보내요 |
404 target_not_found |
to의 닉네임이 채팅방에 없음 |
닉네임을 확인해요 |
429 rate_limited, chat_rate_limited |
호출·채널 전송 한도 초과 | 보내는 횟수를 줄여요. → 서버 REST API |
요청 본문 앞부분과 요청 IP는 API 메뉴의 호출 기록에 30일 동안 남아요. 개인정보나 결제 정보는 보내지 말고, 표시할 문구만 보내세요. 완성된 예제는 결제 완료 알림에 있어요. 예전 v1 방식(/rooms/{채팅방}/plugin/...)은 서버 REST API에 정리해 두었어요.
봐도 잘 이해가 되지 않나요? 문의 게시판에 질문을 남겨 주세요.