WebRTC 에서 한국 070 통화하기 — 브라우저 한 줄, Asterisk 없이
WebRTC 에서 한국 070 통화하기 — 브라우저 한 줄, Asterisk 없이
브라우저에서 직접 한국 070 번호로 통화 거는 시나리오 — 콜센터 웹 클라이언트, 고객용 통화 위젯, 화상 진료 음성 모드. 기존엔 Asterisk·FreeSWITCH 자체 운영 + SIP trunk 계약이 필요했는데, ClawOps 는 표준 SIP-over-WebSocket 위에 동작하므로 JsSIP 같은 검증된 SIP UA 라이브러리만 붙이면 끝. 자체 미디어 서버 운영 없음.
연결 방식. ClawOps WebRTC 는 별도 독자 SDK 가 아니라 RFC 7118 SIP-over-WebSocket 표준입니다. 브라우저는
jssip으로 ClawOps SIP 게이트웨이에 붙고, 서버가 단기 SIP 토큰(POST /sip-credentials/:id/tokens)과 ICE 자격(GET /ice-servers)을 발급합니다. 자세한 흐름은 WebRTC 통합 문서 참고.
0. 활용 예
- 회사 내 콜센터 직원이 브라우저로 통화 (소프트폰)
- 고객 사이트에 "지금 전화하기" 버튼 → 브라우저 통화 즉시 시작
- 화상 진료 시스템의 음성 모드 (070 정식번호 caller ID)
- 게임/메타버스 안에서 음성 통화
1. 준비 — SipCredential + 서버측 토큰 발급
브라우저가 ClawOps API Key 를 직접 호출하면 안 된다. 구조는 단순하다:
- 대시보드 → SIP Credentials 에서 WebRTC 용 SipCredential 1회 발급 (발신 허용 070 번호 지정).
- 내 서버에 엔드포인트 1개를 둬서 ClawOps 에 단기 SIP 토큰 + ICE 자격을 요청한다. API Key 는 서버 환경변수로 가린다.
npm install jssip
// 서버측 토큰 발급 (Next.js route 예시)
const API_BASE = process.env.CLAWOPS_API_BASE!; // https://api.claw-ops.com
const ACCOUNT_ID = process.env.CLAWOPS_ACCOUNT_ID!;
const CREDENTIAL_ID = process.env.CLAWOPS_WEBRTC_CREDENTIAL_ID!;
const API_KEY = process.env.CLAWOPS_API_KEY!; // sk_... — 서버에만
export async function POST() {
const headers = { Authorization: `Bearer ${API_KEY}` };
// 1. SIP 단기 토큰 (TTL 7분)
const tokenRes = await fetch(
`${API_BASE}/v1/accounts/${ACCOUNT_ID}/sip-credentials/${CREDENTIAL_ID}/tokens`,
{ method: 'POST', headers: { ...headers, 'content-type': 'application/json' },
body: JSON.stringify({ ttl_seconds: 420 }) },
);
const { token } = await tokenRes.json();
// 2. ICE/TURN 자격
const iceRes = await fetch(`${API_BASE}/v1/accounts/${ACCOUNT_ID}/ice-servers`, { headers });
const { ice_servers } = await iceRes.json();
return Response.json({ token, iceServers: ice_servers });
}
2. 브라우저에서 070 으로 발신 (JsSIP)
토큰은 JWT 라서, 디코드하면 SIP 등록에 필요한 값(sip_username/sip_password/ws_url/realm/allowed_caller_ids)이 들어 있다.
<audio id="remote-audio" autoplay></audio>
<button id="call-btn">고객센터에 전화</button>
<script type="module">
import { UA, WebSocketInterface } from 'jssip';
function decodeJwt(jwt) {
const p = jwt.split('.')[1].replace(/-/g, '+').replace(/_/g, '/');
return JSON.parse(atob(p));
}
document.getElementById('call-btn').onclick = async () => {
// 1. 내 서버에서 토큰 + ICE 받기
const { token, iceServers } = await (await fetch('/api/webrtc-call/token', { method: 'POST' })).json();
const c = decodeJwt(token);
// 2. JsSIP UA 만들기 (값은 모두 토큰 payload 에서 — 하드코딩 금지)
const ua = new UA({
sockets: [new WebSocketInterface(c.ws_url)], // wss://...
uri: `sip:${c.sip_username}@${c.realm}`,
password: c.sip_password,
register: false,
});
ua.start();
// 3. 070 으로 발신 (받는 쪽엔 070 caller id 로 표시)
const session = ua.call(`sip:07052358010@${c.realm}`, {
mediaConstraints: { audio: true, video: false },
pcConfig: { iceServers },
fromUserName: c.allowed_caller_ids[0], // From 발신번호
});
session.on('confirmed', () => {
const tracks = session.connection.getReceivers().map(r => r.track).filter(Boolean);
document.getElementById('remote-audio').srcObject = new MediaStream(tracks);
});
};
</script>
마이크 권한 요청 → WSS 핸드셰이크 → SIP INVITE → ClawOps SIP gateway 가 070 로 routing → 받는 쪽은 070 caller id 로 표시.
3. inbound — 브라우저가 받기 (소프트폰)
수신 단말로 쓰려면 UA 를 register: true 로 등록하고, JsSIP 의 newRTCSession 이벤트로 들어오는 INVITE 를 받는다.
import { UA, WebSocketInterface } from 'jssip';
const { token, iceServers } = await (await fetch('/api/webrtc-call/token', { method: 'POST' })).json();
const c = decodeJwt(token);
const ua = new UA({
sockets: [new WebSocketInterface(c.ws_url)],
uri: `sip:${c.sip_username}@${c.realm}`,
password: c.sip_password,
register: true, // 수신 등록
});
ua.start();
ua.on('newRTCSession', ({ session, originator }) => {
if (originator !== 'remote') return; // 인바운드만
showIncomingUI(session); // "통화 수신" UI
document.getElementById('accept').onclick = () =>
session.answer({ mediaConstraints: { audio: true }, pcConfig: { iceServers } });
document.getElementById('reject').onclick = () => session.terminate();
});
콜센터 직원 N명이 같은 070 SipCredential 로 register → ClawOps 가 라우팅으로 한 명에게 inbound 전달.
4. 통화 컨트롤
JsSIP 세션 객체로 표준 제어를 한다:
session.mute({ audio: true });
session.unmute({ audio: true });
session.sendDTMF('1234'); // ARS 응답 (RFC 2833)
session.refer(`sip:01098765432@${c.realm}`); // 호 전환(transfer)
session.terminate(); // 끊기
5. AI Agent 와 통화 — 데모/TryItLive
claw-ops.com 메인의 "브라우저로 통화" 위젯은 위와 같은 SIP-over-WebSocket 으로 ClawOps 게이트웨이에 붙고, 발신 대상이 PSTN 070 이 아니라 AI 에이전트 종단이다. 에이전트(OpenAI Realtime / Gemini Live)는 발신 측 calls.create 의 ai={Provider, Model, ApiKey, Messages} (또는 Agent SDK) 로 구성한다. 브라우저 쪽은 동일한 JsSIP 코드를 쓰고, 도착 종단만 에이전트로 바뀌는 구조다.
6. 작동 원리
[브라우저 (Chrome/Safari/Firefox) — JsSIP UA]
↕ SIP-over-WebSocket (WSS) + DTLS-SRTP
[ClawOps SIP gateway, GCP 서울]
↕ SIP/2.0 + SRTP
[한국 070 게이트웨이]
↕ PSTN
[받는 쪽 휴대폰]
브라우저는 표준 SIP UA(JsSIP)만 알면 되고, 게이트웨이가 PSTN 까지 라우팅한다.
7. 대체재와의 비교
| 옵션 | 한국 070 | 셋업 시간 | 운영 |
|---|---|---|---|
| ClawOps (SIP-over-WS + JsSIP) | ✅ | 5분 | 0 (managed) |
| Asterisk 자체 운영 | ✅ (SIP trunk 별도 계약) | 2-4주 | 서버 운영 |
| FreeSWITCH | ✅ (동일) | 2-4주 | 서버 운영 |
| Twilio Voice JS SDK | ❌ (한국 070 발급 X) | 1주 | Twilio managed |
| Vonage Voice Web SDK | ❌ (동일) | 1주 | Vonage managed |
8. 보안
- API Key(
sk_...)는 서버 환경변수에만 둔다. 클라이언트 번들(NEXT_PUBLIC_*/VITE_*)에 절대 넣지 않는다. - 브라우저에는 **단기 SIP 토큰(JWT, TTL 5~7분)**만 내려준다. 만료 1회용이라 노출돼도 무해 (Twilio Voice JS / Vonage Client SDK 와 동일 패턴).
- 발신 대상(destination)은 서버가 결정한다. 클라이언트 입력을 그대로 믿으면 토큰 탈취 시 요금 폭탄.
- PSTN 발신은 토큰 발급 단위 rate-limit + 통화 길이 상한 필수. (자세한 운영 가이드는 WebRTC 문서 보안 섹션.)
- WebRTC TURN 서버: ClawOps 자체 운영 (한국 IP, latency 낮음).
GET /ice-servers의 시간제한 HMAC 자격. - 통화 자동 녹음 (server-side, browser 무관).
9. 비용
- ClawOps Individual ₩19,000/월 (수신 1,000분 = 콜센터 직원 1명 1주)
- Business ₩99,000/월 (동시통화 10, 직원 10명 multiplex)
다음 단계
관련 글 더 보기
ngrok 없이 로컬에서 음성 에이전트 띄우기 — 5분, ClawOps managed inbound
ngrok·터널링·자체 webhook 서버 없이 로컬 머신에서 한국어 voice agent 띄우는 가이드. ClawOps managed inbound 패턴 + Python 30줄.
가이드관리번호로 070 대량 발급·관리하기 — 파트너 가입중개(External Assignment)
프랜차이즈·플랫폼·법인이 최종이용자에게 070을 일괄 발급·관리하는 가이드. ClawOps 관리번호 Add-on + 발급 링크·본인인증 + 인입 라우팅 코드.
가이드070 번호 5분 발급 가이드 — API 한 줄, 무약정, 카드 등록 없이
한국 070 번호를 API 한 줄로 5분에 발급받는 가이드. 통신사 영업·KISA 등록·벌크 약정 없이 ClawOps Trial 무료로 시작.
가이드070 인바운드 webhook 라우팅 — 시간·번호·DTMF 기준 동적 분기
ClawOps 070 번호로 들어오는 통화를 시간대·발신자 번호·DTMF 응답 기준으로 다른 AI Agent / 상담사 큐 / 부재중 메모로 라우팅하는 패턴.
가이드1588·1566 대표번호 ClawOps 무료 연동 — 기존 8자리 번호 그대로 AI 응답
기존 1588·1566 대표번호를 ClawOps 070 인프라에 무료로 연동해서 AI 상담원이 받게 만드는 가이드. 기존 통신사 계약 유지하면서 AI 응대 추가.