ID TECH
기술 게시물 전체 보기

기술 포스트

Websockets를 활용한 USB 카드 리더기 연결

Websockets와 NodeJS를 사용하면 어떤 웹 브라우저에서도 USB 카드 리더기에 연결할 수 있습니다. 즉, 가상 단말기(Virtual Terminal)에서 EMV 거래를 처리할 수 있습니다. 아래에서 자세한 방법을 확인해 보세요!

지난 번에는 JavaScript를 통해 USB 연결을 설정하는 방법 을 NodeJS와 node-hid라는 모듈을 사용하여 소개해 드렸습니다. 약 75줄의 코드만으로 JavaScript에서 USB 장치에 프로그래밍 방식으로 접근할 수 있게 되었습니다. 해당 스크립트는 장치 자동 감지 및 연결 기능을 구현하였으며, USB 데이터 읽기 및 쓰기를 위한 장치 핸들을 제공했습니다.

Node 스크립트 내에서 USB 데이터에 프로그래밍 방식으로 접근하는 것만이 목적이라면 이것으로 충분합니다.

하지만 해당 데이터를 다른 프로세스에 전달해야 한다면 어떨까요? 예를 들어, USB 데이터를 웹 브라우저로 전송하거나 서버로 내보내야 하는 경우라면요?

걱정하지 않으셔도 됩니다. 충분히 가능하고, 방법도 간단합니다!

웹소켓의 등장

웹소켓 프로토콜(IETF 사양 여기)은 오랜 시간에 걸쳐 등장한 웹 표준 중에서도 가장 유용한 기술 중 하나입니다. 다행히도 모든 최신 브라우저에서 지원되며, Node 스크립트에서도 사용할 수 있습니다. 즉, 두 환경을 연결하는 소켓 연결만 생성하면 Node 코드와 브라우저 스크립트 간의 통신이 매우 간편해집니다.

Node 측에서는 OS 콘솔을 열고 npm install socket.io -g 를 실행하여(최초 1회) 널리 사용되고 있으며 그 인기가 충분히 납득되는 socket.io 모듈을 설치해야 합니다. 설치 후 스크립트에서 require("socket.io") 를 호출하면 이 모듈의 강력한 기능을 활용할 수 있습니다. (자세한 내용은 바로 다음에서 설명합니다.)

브라우저 측에서는 socket.io.slim.js 스크립트를 활용하면 웹 페이지에서 WebSocket 데이터를 수신할 수 있습니다. (표준 브라우저 WebSocket API는 사용하지 마십시오. 앞서 언급한 socket.io 모듈은 브라우저가 인식하지 못하는 자체 연결 유지 방식을 사용하기 때문입니다. 충돌을 방지하려면 클라이언트 측 스크립트인 socket.io.slim.js를 사용하십시오. 이 스크립트에는 구형 브라우저에서도 WebSocket을 사용할 수 있도록 해주는 폴리필(polyfill)이 포함되어 있다는 추가적인 이점도 있습니다.) 클라이언트 측 스크립트를 가장 간편하게 가져오는 방법은 아래 코드 조각을 웹 페이지에 삽입하여 엣지 서버(CDN)에서 직접 받아오는 것입니다.

해당 스크립트를 적용하면, 웹 페이지에서 직접 구축한 소켓 서버에 연결할 준비가 완료됩니다.

웹소켓 서버 구성

루프백 모드(즉, ws://localhost)에서 소켓 서버를 설정하는 방법을 살펴보겠습니다. 설정 방법은 놀라울 만큼 간단하며, 프로세스 간 통신에 매우 유용합니다.

물론 Node가 필요하며, 앞서 설명한 socket.io 모듈도 필요합니다. 그런 다음 Node를 실행하여 아래와 같은 스크립트를 구동하면 됩니다.

주석을 제외하면 실제 코드는 약 30줄에 불과합니다. 개념적으로 살펴보면, 먼저 require('http')를 호출하여 더미 HTTP 서버 인스턴스를 설정합니다. 그런 다음 require('socket.io').listen(server) 를 호출하여 socket.io 모듈이 수신되는 HTTP 요청을 WebSocket 연결로 업그레이드할 수 있도록 합니다.

기본적으로 WebSocket 연결은 연결된 당사자 간의 전이중(full-duplex) 방식의 메시지 기반 점대점(point-to-point) 통신을 지원합니다. 그러나 점대점 방식이라고 해서 메시지가 자동으로 다른 연결에 브로드캐스트되는 것은 아닙니다. 브로드캐스트를 활성화하려면 커스텀 이벤트 리스너인 on.('echo') 58번째 줄의 리스너는 수신된 "echo" 메시지를 'message' 유형의 새 메시지로 모든 소켓 연결에 재전송합니다. 여기서의 규칙은 다음과 같습니다. 1:1 메시지 전송에는 'message' 이벤트 유형을 사용하고, 소켓 서버가 메시지를 모든 리스너에게 전달하도록 하려면 'echo' 메시지 유형을 사용하십시오. (참고로, 이는 socket.io에서 강제하는 규칙이 아닌 저희 자체 규약입니다.)

마지막으로 주목할 점은, 위 코드 자체만으로는 아무런 동작도 하지 않는다는 것입니다. 클래스 정의일 뿐이므로, 실제로 사용하려면 런타임에 클래스를 인스턴스화해야 합니다. 하지만 이 과정은 매우 간단합니다. 코드 상단의 주석에 클래스 사용 방법이 설명되어 있으며, 이후 블로그 포스트에서도 활용 방법을 확인하실 수 있습니다.

이 시리즈의 다음 포스트들을 놓치지 마십시오. 곧 JavaScript를 사용하여 브라우저에서 직접 실제 게이트웨이와의 비접촉 거래를 처리하는 방법을 소개할 예정입니다! 近近 업데이트를 확인해 주십시오!