Vol. 26

개발일지

인터넷이 막힌 컴퓨터에 키를 쏘는 법 — 매장용 원격 콘솔 만들기

각 방에 따로 떨어진 컴퓨터들을, 한 자리에서 버튼 하나로 제어하는 작은 콘솔을 만들었어요. 인터넷을 일부러 끊어 둔 컴퓨터에 어떻게 키를 보내는지, 격리된 와이파이 위에서 WebSocket으로 통신하는 구조를 정리했습니다.

2026.06.05 · 발신 우체부J


title: "인터넷이 막힌 컴퓨터에 키를 쏘는 법 — 매장용 원격 콘솔 만들기" date: "2026-06-05" description: "각 방에 따로 떨어진 컴퓨터들을, 한 자리에서 버튼 하나로 제어하는 작은 콘솔을 만들었어요. 인터넷을 일부러 끊어 둔 컴퓨터에 어떻게 키를 보내는지, 격리된 와이파이 위에서 WebSocket으로 통신하는 구조를 정리했습니다." tags: ["dev", "nodejs", "websocket", "automation"] category: "dev"

제가 일하는 매장에는 방마다 컴퓨터가 한 대씩 따로 있어요. 각 방에서 프로그램이 풀스크린으로 돌아가고, 직원은 진행 상황을 보다가 딱 맞는 순간에 특정 키를 눌러 다음 장면으로 넘기거나 효과를 줘야 합니다.

원래는 직원이 그 방 컴퓨터 근처까지 직접 가서 키보드로 눌렀어요. 방이 여러 개라 이리저리 옮겨 다녀야 하고, 자리를 비울 수도 없고. 그래서 한 자리에 앉아서 모든 방을 원격으로 조작하는 작은 콘솔을 만들었습니다. 오늘은 그 구조 이야기예요.

큰 그림 — 메인 PC 한 대가 방 PC들을 지휘

구조는 단순해요.

  • 메인 PC: 작은 Node.js 서버 + 브라우저 컨트롤 패널 (카운터에 둠)
  • 방 PC들: 각자 백그라운드 클라이언트를 띄워 두고 메인 PC에 접속
  • 통신: 같은 망 안에서 WebSocket으로 실시간 연결

카운터 화면(브라우저)에서 버튼을 누르면 → 메인 PC 서버가 받아서 → 해당 방 PC로 넘기고 → 방 PC가 그 키를 자기 화면의 프로그램에 주입합니다.

// 브라우저 패널: 버튼을 누르면 어느 PC로 무슨 키를 보낼지 서버에 전송
ws.send(JSON.stringify({ cmd: 'send', target: 'room1-pc1', key: 'z' }));

서버는 이 메시지를 받아 target에 해당하는 방 PC의 소켓으로 그대로 흘려보내요. 중간에서 라우팅만 하는 아주 얇은 서버예요.

핵심 1 — "받은 키를 화면에 주입한다"

방 PC 클라이언트가 하는 일은 결국 하나예요. 메인 PC에서 받은 키를, 지금 화면에서 풀스크린으로 떠 있는 프로그램에 실제 키 입력처럼 넣어주는 것.

Windows에서는 활성 창(맨 앞 창)에 키를 보내는 방법이 있어요. 방 PC는 받은 키를 이 방식으로 쏩니다.

받은 키 'z'  →  지금 맨 앞에 떠 있는 창에 'z' 입력

그래서 방의 게임 프로그램은 항상 풀스크린 + 맨 앞이어야 해요. 다른 창이 위로 올라와 있으면 키가 엉뚱한 창으로 들어가 버리거든요. 이 부분이 처음에 제일 헷갈렸어요.

핵심 2 — 인터넷이 막힌 컴퓨터끼리 통신시키기

여기가 이 프로젝트에서 제일 재밌었던 부분이에요.

방 PC들은 일부러 인터넷을 끊어 둡니다. 손님이 혹시라도 그 컴퓨터로 검색을 하거나 딴 데로 빠지지 못하게요. 그런데 인터넷이 없으면, 메인 PC랑은 어떻게 통신할까요?

답은 인터넷은 없지만 자기들끼리는 연결된 망을 따로 까는 거예요. 공유기를 한 대 두되 인터넷 선(WAN)을 꽂지 않습니다. 그러면 바깥 인터넷은 자동으로 차단되지만, 그 공유기에 붙은 컴퓨터들끼리는 같은 네트워크라 서로 통신이 돼요.

[격리 공유기]  ← 인터넷 선 안 꽂음 (바깥은 차단)
   ├─ 메인 PC   (192.168.0.2)  ← 서버
   ├─ 방 1 PC
   ├─ 방 2 PC
   └─ 방 3 PC

WebSocket은 인터넷이 아니라 같은 망 안에서만 돌아도 충분하니까, 이 격리망 위에서 문제없이 동작해요. "인터넷은 막되 자기들끼리는 통하게"가 핵심이었어요.

핵심 3 — 아무 키나 들어가면 안 되니까 (화이트리스트)

원격으로 키를 쏘는 시스템이라, 안전장치를 하나 뒀어요. 방 PC는 미리 등록해 둔 키만 받아들이고 나머지는 그냥 무시합니다.

// 방 PC: 허용 목록에 없는 키는 거부
if (!config.allowedKeys.includes(key)) return;

이렇게 하면 혹시 패널에서 실수로 엉뚱한 키를 보내도, 방 게임이 의도치 않은 키로 흔들릴 일이 없어요. 키를 새로 추가할 땐 패널 쪽과 방 PC 쪽 양쪽에 같이 등록해야 동작합니다(한쪽만 하면 거부돼요).

거기서 욕심이 붙어서 — 연타 · 매크로

한 번 만들고 나니 현장에서 "이런 것도 됐으면" 하는 게 계속 생기더라고요.

자동 연타 — 어떤 동작은 같은 키를 빠르게 여러 번 눌러야 반응해요. 그래서 버튼 한 번에 방 PC가 알아서 N번 연타하게 옵션을 줬어요.

"keyOptions": { "w": { "repeat": 10, "intervalMs": 200 } }

w 버튼을 누르면 방 PC가 200ms 간격으로 10번 톡톡 눌러줍니다.

매크로 — 더 나아가서, 버튼 하나로 여러 동작을 순서대로 실행하게 했어요. "키 누르고 → 몇 초 기다리고 → 화면 한 곳을 클릭하고 → 다른 키 누르기" 같은 흐름을 JSON으로 정의해 두면 버튼 한 번에 쭉 실행돼요. 매장 문 닫고 다음 손님 받기 전에 프로그램을 초기 상태로 되돌리는 리셋도 이걸로 자동화했습니다.

만들면서 제일 고생한 건, 의외로 'USB'

기술적으로 막힌 것보다, 더 번거로웠던 건 배포였어요. 방 PC들이 인터넷이 안 되니까, 코드를 조금 고쳐서 방 PC에 새로 넣어주려면 파일을 USB에 담아 방마다 일일이 들고 다녀야 했어요. 한 군데 고치고 USB 꽂고, 또 고치고 다시 꽂고… 작은 수정 하나에도 발품이 꽤 들더라고요. 인터넷을 막은 대가인 셈이라 어쩔 수 없는 부분이었어요.

마무리

전공자도 아니고, 그냥 일하다 불편해서 시작한 건데 만들고 나니 배운 게 정말 많았어요. "인터넷 없는 컴퓨터끼리 어떻게 통신시키지?" 같은, 평소엔 생각도 안 해 봤을 문제를 직접 풀어보게 됐거든요.

무엇보다 직원들이 방마다 뛰어다닐 필요 없이 한 자리에서 다 처리하게 되니까, 현장이 훨씬 수월해졌어요. 작은 도구 하나가 매일의 일을 바꾸는 걸 보면, 또 다음 걸 만들고 싶어집니다.