관련 지식
node.js, http, websocket, express

node.js로 웹서버를 개발할때 express 패키지를 많이 사용할 것입니다. 그럴때 포트 바인딩 설정을 아래와 같이 사용하게 됩니다.

express.js 샘플)

  1. var express = require('express');
  2. var app = express();
  3. app.get('/', function(req, res){
  4. res.send('hello world');
  5. });
  6. app.listen(3000);

그런데 이러한 환경에서 실시간 처리를 위해 웹소켓을 사용할 경우가 있습니다. 서로 다른 패키지를 이용하여 포트 바인딩을 해야하니 다른 포트를 써야 할까요?

웹소켓 프로토콜

RFC 6455 문서에 나와있는 것처럼 웹소켓은 아래와 같은 프로토콜로 구성되어 있습니다.

  1. GET /chat HTTP/1.1
  2. Host: server.example.com
  3. Upgrade: websocket
  4. Connection: Upgrade
  5. Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
  6. Origin: http://example.com
  7. Sec-WebSocket-Protocol: chat, superchat
  8. Sec-WebSocket-Version: 13

웹소켓은 일반 소켓 통신처럼 ‘Connection Oriented’ 로 동작하지만 얼핏 봐서는 raw tcp 통신이라기 보단 일반 HTTP/HTTPS 통신과 다름 없어 보입니다. 실제로 웹소켓의 통신 방법은 HTTP/HTTPS 헤더 체계를 따르며 REFERER, COOKIE 등의 헤더 정보를 포함할 수 있습니다.

참고 : https://developer.mozilla.org/ko/docs/WebSockets/Writing_WebSocket_servers

따라서 웹소켓 서버는 익스프레스와 같은 포트를 사용할 수 있습니다.

적용법

npm 의 websocket 패키지가 필요합니다. 다른 패키지를 사용할 경우 안될 수 있습니다.

경로 : https://www.npmjs.com/package/websocket
문서 : https://github.com/theturtle32/WebSocket-Node/blob/HEAD/docs/index.md
설치 : npm install websocket
테스트버전 : 1.0.25

익스프레스 서버 바인딩)

  1. var server = http.createServer(app).listen(3000, function() {
  2. console.log('Express server listening');
  3. });

웹소켓 바인딩)

  1. var wsServer = new webSocketServer({
  2. httpServer : server
  3. });

매우 간단합니다. 기존에 사용한 ‘app.listen(3000);’ 코드를 지우고 위 코드로 대체하면 익스프레스와 웹소켓 양쪽다 같은 포트를 사용할 수 있습니다. 어떤 헤더를 가진 패킷이 들어오느냐에 따라 웹소켓 또는 익스프레스에서 구분하여 처리하게 될 것입니다.

테스트

서버 실행후 개발자도구를 열고 아래 한줄을 콘솔에 입력하면 됩니다.

  1. var client = new WebSocket("ws://127.0.0.1:3000/");

구글을 띄운 상태에서 호출했더니 아래처럼 로그가 나오네요

물론 브라우저에서 ‘http://127.0.0.1:3000/‘ 으로도 호출 가능합니다. 익스프레스가 처리할테니까요. 더 이상 웹소켓을 위해 8080, 8888 같은 별도 포트를 쓸 필요가 없습니다. 그냥 웹서버 대표 포트를 같이 이용하세요.

최종 샘플

  1. const express = require('express');
  2. const http = require('http');
  3. const webSocketServer = require('websocket').server;
  4. const app = express();
  5. app.get('/', function(req, res){
  6. res.send('hello world');
  7. });
  8. var server = http.createServer(app).listen(3000, function() {
  9. console.log('Express server listening');
  10. });
  11. var wsServer = new webSocketServer({
  12. httpServer : server
  13. });
  14. var eventHandler = {
  15. handleRequest : function(request) {
  16. console.log('Connection from origin ' + request.origin + '.');
  17. },
  18. handleMessage : function(message) {
  19. console.log(JSON.stringify(message));
  20. },
  21. handleClose : function(connection) {
  22. console.log("disconnected.");
  23. }
  24. };
  25. wsServer.on('request', eventHandler.handleRequest);