# 전화로 PC를 조종할 수 있다?

# 오픈클로 전화 연동 실험

목적은 "Slack에서 키워드나 커맨드를 입력하면, 봇이 내 휴대폰으로 전화, 음성으로 대화하면서, 내 PC에서 작업을 트리거하고 결과를 다시 음성으로 알려주는" 흐름을 실제로 구현 가능한지 검증하는 것이었어요. 

![화제의 OpenClaw, 이제는 전화도 건다](https://www.youtube.com/shorts/fHSHAcEre8c)

_위 영상에서 영감을 얻어 진행된 실험입니다._

결론부터 말하면, 아키텍처는 성립했지만 Twilio Trial 계정 정책, 국가 제한 때문에 "한국 번호로 수신" 단계에서 막혀서 이번 라운드는 실패로 종료됐습니다.

---

## 1) 목표와 성공 기준

원하는 사용자 경험은 아래였어요.

- Slack에서 호출하듯이 한 줄 명령, 예: `/callme` 또는 특정 키워드 메시지

- 봇이 내 휴대폰으로 전화를 건다

- 통화 중 음성으로 내 명령을 받아서 STT로 텍스트화한다

- 텍스트를 명령으로 파싱하고, 내 PC에서 작업(쉘 커맨드, 스크립트 실행 등)을 수행한다

- 결과를 TTS로 읽어준다

- 가능하면 Make 없이도 동작한다

성공 기준은 최소 3단계였어요.

1. Slack 트리거로 Twilio 발신이 실제로 걸린다

2. 통화 중 음성 입력을 받고 서버가 웹훅을 정상 수신한다

3. PC 작업 실행 결과를 다시 음성으로 돌려준다

---

## 2) 초기 가설, 도구 선택

처음엔 "가장 쉬운 방법" 기준으로 Make(구 Integromat)로 시작했어요.

- Slack 메시지 감지, 키워드 필터

- Twilio "Make a call"로 발신

- TwiML을 재생하거나, 호스팅된 음성 파일을 재생

하지만 곧 문제가 명확해졌습니다.

- Make만으로는 "양방향 음성 대화, 실시간 음성 입력(STT), 명령 파싱, PC 조작"까지는 무리

- 결국 Twilio의 `<Gather input="speech">` 와 웹훅 서버가 필요

그래서 아키텍처를 이렇게 재정의했습니다.

- Slack(트리거) → CallBot(서버) → Twilio(전화, 음성수집) → CallBot(웹훅) → PC 작업(exec) → TTS 응답

---

## 3) 구현 접근, Make 없이 Slack Slash Command로 전환

Make 없이도 Slack에서 한 줄로 트리거하려면 Slash Command가 더 직선이에요.

- Slack `/callme` 호출

- Request URL로 CallBot 서버의 `/slack-call` 엔드포인트에 POST

- CallBot이 Twilio REST API로 전화를 건다

- 통화 중 TwiML 흐름을 따라 `<Gather>`로 음성을 받고 웹훅으로 전송

여기서 중요한 포인트는 Socket Mode를 쓰더라도 Slash Command는 "HTTP Request URL"이 필요하다는 점이었어요. 이벤트 수신을 소켓으로 받는 것과, Slash Command가 호출되는 경로는 별개였습니다.

---

## 4) ngrok 도입, localhost 문제 해결

초기에는 HOST_URL을 `http://localhost:3000`으로 두고 진행했는데, Slack, Twilio가 로컬호스트로는 접근할 수 없어서 ngrok이 필요했습니다.

- `https://<ngrok-subdomain>.ngrok-free.dev` 형태로 외부 HTTPS URL 확보

- CallBot의 `.env`에 `HOST_URL`을 ngrok URL로 설정

- TwiML의 `<Gather action=".../webhook">`도 ngrok URL로 교체

중간에 `Cannot GET /` 화면이 떠서 헷갈렸는데, 이건 정상 동작이었어요. 서버가 `/` 라우트를 정의하지 않았기 때문에 루트로 접근하면 Express가 "Cannot GET /"를 보여주는 게 자연스러운 상태였습니다.

정상 확인은 루트가 아니라 다음으로 했습니다.

- `GET /call-flow.xml` 접근 시 TwiML XML이 보이면 OK

- `POST /slack-call`이 외부에서 200으로 응답하면 OK

실제로 TwiML XML이 정상 출력됐고, `/slack-call`도 200 OK로 응답이 돌아왔습니다. 즉, 네트워크, ngrok, 서버 라우팅 자체는 성공으로 판정했습니다.

---

## 5) 실제로 막힌 지점, Twilio Trial 제한, 한국 번호 인증 제한

문제는 통화 발신 단계에서 다음 에러가 반복적으로 발생한 것입니다.

- 에러: `21219 The number +82... is unverified. Trial accounts may only make calls to verified numbers.`

이건 Twilio Trial 계정의 대표적인 제한입니다. Trial에서는 발신 대상(To)이 "Verified" 목록에 있어야 통화를 걸 수 있어요.

그래서 To 번호를 Verified로 등록하려고 했는데, 콘솔에서 또 막혔습니다.

- Trial 계정에서 "verification call(전화 인증)"은 지원하지 않음

- "SMS 인증"으로 전환하려 했으나, 한국(+82)이 "restricted country for verifying a caller ID by SMS"로 차단됨

즉, Trial 계정 상태에서 한국 번호를 Verified destination으로 만들 수 있는 공식 경로가 차단돼 있었어요. 그래서 구조는 정상인데, 정책 제한에 걸려 마지막 발신이 실패했습니다.

---

## 6) "인증되어 있는데 왜 unverified?"로 보였던 이유

중간에 "Verified로 보이는데도 21219가 뜬다"는 상황이 있었고, API로 확인해보니 결정적인 단서가 나왔어요.

- Verified 목록에 저장된 번호 형식이 `+82` 뒤에 `010`의 0이 포함된 형태로 잡혀 있었습니다(예: `+82010...`)

- 우리가 실제로 dial 하려는 번호는 정상 E.164 형태인 `+8210...`였습니다

이 상태에서는 "내가 봤을 때는 인증된 것 같은데, 호출할 때는 매칭이 안 되는" 문제가 생길 수 있어요.

다만 최종적으로는 "한국 번호 자체가 Trial에서 SMS 인증 제한 국가라 재인증도 막힌다"가 본질 원인이었습니다.

---

## 7) 부수 이슈, 서버 재시작, 포트 충돌

서버를 여러 번 띄우는 과정에서 3000 포트 충돌이 발생했습니다.

- `EADDRINUSE: address already in use :::3000`

이 문제는 이미 떠 있는 Node 프로세스를 종료한 뒤 재기동하는 방식으로 해결했습니다. 이 이슈 자체는 기술적으로 흔한 수준이고, 핵심 장애는 Twilio 정책이었습니다.

---

## 8) 이번 실험 결론

이번 라운드의 결론을 "기술적 성립"과 "운영 가능성"으로 나눠서 정리하면 이렇습니다.

기술적으로는 성립합니다.

- ngrok로 외부 HTTPS URL 확보

- Slack Slash Command에서 CallBot 서버로 POST 유입 확인

- CallBot 서버에서 TwiML 제공, Twilio가 TwiML을 가져갈 준비까지는 완료

운영적으로는 "Trial, 한국번호" 조합에서 실패했습니다.

- Trial 계정은 To 번호가 Verified여야 함

- 한국 번호는 SMS 인증이 제한 국가로 차단됨

- 결과적으로 Trial 환경에서는 한국 휴대폰으로 통화 수신 테스트가 불가

---

## 9) 다음 액션 플랜

현실적인 옵션은 3가지입니다.

1. Twilio 유료 전환(결제 수단 등록, Trial 해제)

- 목적이 "한국 번호로 받는 전화 봇"이라면 이게 가장 직선입니다.

2. Twilio를 유지하되, 한국 번호 수신을 당장 포기하고 우회 테스트

- 예: SMS 인증 가능한 국가 번호로 To를 Verified로 만들어 통화 흐름만 먼저 검증

- 다만 이건 기존 목표와는 거리가 있습니다.

3. 공급자 변경

- Vonage(Nexmo), Plivo 등으로 동일 구조를 재구현

- 다만 기존 Twilio 설정을 버리게 되니 비용이 듭니다.

---

## 10) 보안 메모, 즉시 조치 권장

실험 과정에서 인증 토큰, 키 값이 로그에 노출될 수 있는 순간이 있었습니다. 이런 키는 외부 유출 시 비용, 계정 탈취로 바로 이어질 수 있어요.

따라서 다음 조치는 "즉시"가 안전합니다.

- Twilio Auth Token은 바로 Rotate(재발급)하고, 기존 값은 폐기

- `.env`에도 새 토큰으로 교체

- Slack, ngrok 등 다른 키도 동일하게 노출된 적이 있다면 전부 교체

---

## 11) 짧은 회고

이번 실험은 "내가 원하는 제품 경험"을 구현하는 데 필요한 기술 스택과 연결 구조를 빠르게 확정한 점에서는 수확이 있었어요. 반면 "정책, 국가 제한" 같은 비기술 요인을 초기에 체크하지 않으면 구현이 아무리 맞아도 마지막에서 막힌다는 걸 확인했습니다.

다음 라운드는 "Twilio 결제 전환 여부 결정"이 먼저이고, 그 다음에 STT, 명령 파싱, PC 실행 범위를 안전하게 제한하는 방식(허용 명령 allowlist, 인증 토큰, IP 제한)을 설계하는 쪽으로 가는 게 맞습니다.

For the site tree, see the [root Markdown](https://blog.teamjcurve.com/.md).
