기술 포스트
Websockets를 활용한 USB 카드 리더기 연결
Websockets와 NodeJS를 활용하면 어떤 웹 브라우저에서도 USB 카드 리더기에 연결할 수 있습니다. 즉, 가상 단말기에서 EMV 거래를 처리할 수 있다는 의미입니다. 자세한 방법은 아래에서 확인하세요.
지난번에는 JavaScript를 통한 USB 연결 설정 방법 을 NodeJS와 node-hid라는 모듈을 이용하여 소개했습니다. 그 결과, 단 75줄 정도의 코드만으로 JavaScript에서 USB 디바이스에 프로그래밍 방식으로 접근할 수 있었습니다. 작성한 스크립트는 자동 디바이스 감지 및 연결 기능을 구현했으며, USB 데이터 읽기 및 쓰기를 수행할 수 있는 디바이스 핸들을 제공했습니다.
Node 스크립트 내에서 USB 데이터에 프로그래밍 방식으로 접근하는 것만이 목적이라면, 이것으로 충분합니다.
하지만 해당 데이터를 다른 프로세스와 주고받아야 한다면 어떨까요? 예를 들어, USB 데이터를 웹 브라우저로 전송하거나 서버로 푸시해야 하는 경우라면요?
걱정하지 않아도 됩니다. 충분히 가능하고, 방법도 간단합니다!
Websockets로 문제 해결하기
Websocket 프로토콜(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)에서 직접 불러오는 것입니다:
이 스크립트가 준비되면, 웹 페이지에서 직접 구축한 소켓 서버에 연결할 준비가 완료됩니다.
Websocket 서비스 제공
루프백 모드(즉, 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를 사용해 브라우저에서 직접 실제 게이트웨이를 통한 비접촉 결제 거래를 처리하는 방법을 다룰 예정입니다! 조만간 다시 확인해 보세요!
