2013 이전/node.js

[node.js] Socket.io 맛보기 (웹 채팅 만들기)

hagulu 하구루2017.02.25 16:34

node.js 가 나타나면서 가장 주목 받았던 모듈중에 하나였던 Socket.io를 소개 해보려고 한다.

 
 웹을 통한 애플리케이션을 개발할때 가장 힘든점이, 바로 실시간 데이터 적용이다. 서버에서 넘어온 정보를 실시간 으로 화면에 보여 주어야 하는데 refresh를 이용하면 화면이 깜박이는 문제가 있다. 이를 위한 대안으로 Ajax를 많이 사용하게 된다. 하지만 이것은 Client위주의 개발에 적합하다. 서버에 변화 된 내용을 항상 유지하려면 poliing을 직접 구현해야 하는데 여간 번거로운 일이 아닐수 없다.
 이를 보완하기 위해 등장한것이 바로 WebSocket이다. 일반 애플리케이션에서 사용하면 Socket을 브라우져에서 사용가능하게 한 것으로, 어렵지 않게 웹상에서 Socket과 같은 방식의 애플리케이션 구현이 가능하다. 하지만 아직 표준이 정해지지 않았고, 이를 호환하는 브라우져가 제한적이다. 그리고 보안에 대한 논란도 아직 진행중이다.




  WebSocket 지원 여부(이미지 출처: http://caniuse.com)

 표에 보는 것처럼 전체의 55%정도만 완벽하게 지원이되고 부분적인 지원이 5%정도이다. 그리고 국내에서 가장 많이 사용하는 IE에서는 10.0에서나 지원이 가능하다. 
 
 이에 대한 대안이 바로 Socket.io이다. 서버는 node.js의 모듈로 간단히 이용이 가능하고 client도 모듈에 포함된 javascript 파일 하나만 있으면 지원이 된다. 일반 javascript를 사용하기 때문에 호환 문제도 걱정이 없다.
 
 더 길게 끌지 않고 예제를 통해서 살펴 보도록 하겠다.
 소켓 통신을 이용할때 가장 만만한 예제가 채팅이므로 이를 만드는 예제를 보도록 하겠다.
node.js와 socket.io 모듈의 설치에 관해서는 아래 두 포스팅을 참고하기 바란다.
[node.js] npm을 이용한 module 설치

Socket.io는 기본적인 웹서버 모듈과 연동하게 된다.
여기에서는 단순하게 http 모듈을 이용해서 소개해 보겠다.
var app = require('http').createServer(handler)
	, io = require('socket.io').listen(app)
	, fs = require('fs')
  
    app.listen(8005);
  
function handler (req, res) {
    fs.readFile(__dirname + '/index.html',
    function (err, data) {
        if (err) {
        	res.writeHead(500);
        	return res.end('Error loading index.html');
       	}
  
       	res.writeHead(200);
       	res.end(data);
    });
}
  
io.sockets.on('connection', function (socket) {
      socket.on('my other event', function (data) {
         	console.log(data);
        	socket.emit("my_message", data);
        	socket.broadcast.emit("message", data);
       });
 });
 handler 부분은 http를 위한 부분이니 다음에 다루어 보도록 하겠다.
 중요한 부분은 아래 소켓 관련된 부분이다.
 일반 프로그래밍에서 소켓을 통한 개발을 해보았다면 어렵지 않게 이해가 가능 할것으로 보인다.
 2번째 라인에 require 부분에서 app 즉, http서버를 통해서 socket을 listen을 하게 된다.
 그리고 20번째 라인에서 Client가 연결이 되었을떄의 작업을 function을 통해 정의 해주게 된다. 보는 것처럼 연결이 되었을때 생성된 해당 socket은 파라미터로 가져다 쓸 수가 있다. 이 소켓을 통해 연결된 Client와 통신하게 된다.
 여기에서 다시 해당 소켓에 새로운 이벤트를 추가해주게 된다. 해당 소켓에 on 함수를 통해 새로운 이벤트를 추가를 해주면 된다. 위 소스에서는 "my other event" 라는 이벤트를 추가하고 해당 이벤트가 발생했을때, 이루어질 작업을 function을 통해서 등록 해주게 된다. 이벤트와 함께 들어온 data는 파라미터를 통해 이용할 수 있다.
 23번째 라인은 들어 온 데이터를 다시 Client로  "my_message" 라는 이벤트로 전송하는 것이다. 이쯤 되면 감이 올것이다. 이벤트를 생성하여 발생시키는 것은 emit라는 메소드를 이용하면 된다. 잠시후 client에서도 보겠지만 같은 함수를 사용한다. 일반적으로 socket에 내장되어 있는 함수로 해당 소켓으로만 이벤트를 발생 시키는 것이다. 하지만 여기서 해보려는것은 채팅이다. 채팅의 경우 자기 자신만이 아니라 모두에게 전송이 이루어 져야 한다.
 이를 구현한것이 바로 24번째 라인이다. socket에 broadcast의 emit를 통해서 이벤트를 발생시키면, 해당 소켓이 연결된 Client를 제외한 다른 소켓으로 다른 모든 Client들에게 이벤트를 발생시키게 된다.
 이러면 자연스럽게 채팅과 같은 기능을 하는 서버가 완성이 된 것이다.
 정말 간단하기 그지 없다.
 이어서 바로 Client부분을 보겠다.
 먼저 아래 파일은 위 소스에서 구현한 javascript 파일과 같은 디렉토리에 index.html에 작성하면된다. 그 이유는 위 소스의 handler의 설정에 따른것 이다. 필요하다면 이를 수정해서 다른 디렉토리나 파일로 이용하는 것도 가능하다.
 

Client에서는 조심해야할 부분이 많다.
 먼저 조심해야할 부분이 1라인의 src부분이다. 내 디렉토리에는 눈씻고 찾아 봐도 /socket.io/socket.io.js 파일이 없는데, 왜 그래도 해야 할까 싶지만, 이것은 서버에 있는 socket.io 모듈이 알아서 연결해 주는 부분이다. 그러므로 의심 하지 말고 이용하기 바란다. 혹시 다른 곳에서 구하거나, 다른 곳의 링크를 이용할 경우 socket.io와 socket.io.js의 버젼이 맞지 않아서 문제가 발생할 수도 있으니 꼭 위와 같은 방식으로 이용하기 바란다.
 5번째 라인에서 소켓을 연결하게 된다. 간단하게 소켓을 생성하고 바로 연결이 된다. 예전 버젼에서는 번거롭게 진행해야 하니 최신버젼을 꼭사용하기 바란다. 본인은 원격지 서버로 이용하고, 포트 설정떄문에 포트를 다르게 했지만, local에서 테스트 할경우 "http://localhost" 형식으로 해주기만 하면된다.
 이제 서버에서 올라오게될 이벤트를 등록해주는 부분이 6~13라인이다. 보는 것처럼 서버와 문법이 똑같다. node.js의 장점이 바로 이런것이다. 서버에서 작성한 문법 그대로 웹 클라이언트에서 구현해주면 된다. 위에서는 24라인에 있는 div에 새로온 메시지와 현제 메시지를 합쳐 주는 일을 한다. "message"는 다른 곳에서 온 메시지를 처리하는 것이고, "my_message"는 내 메시지가 서버를 거쳐서 다시 오게되는 메시지를 처리하는 것이다. "my_message"는 굳이 서버를 거칠 필요는 없지만, 소켓의 동작을 보여주기 위해서 적용해 보았다.
 15~18라인은 메시지를 서버로 보내는 부분이다. 이 function은 아래 22 ~ 23라인에서 return키 혹은 버튼 클릭을 통해서 불려지게 된다. 이벤트 발생은 서버와 마찬가지로  emit 메소드를 통해서 사용하면 된다. 서버에 등록 해 두었던 "my other event" 로 이벤트를 발생시키도록 하였다. 메시지 내용은 아래 22번째 라인에 있는 input의 벨류로 하면된다. 17라인은 보낸 다음에 input을 비워주는 부분이다.
 
 여기까지 진행이되면 기본적인 채팅 프로그램이 간단하게 완성이 된다.
 로컬로 진행되었을경우 브라우져로 http://localhost로 접속을 하게 되고, 저 처럼 원격지로 진행된경우는 원격지 도메인을 입력하여 실행하여 보면된다.
간단하게 실행한 예이다





신고

댓글

댓글쓰기 폼

hagulu.com

.....

VISITED

Today : 101

Total : 119,812

Lately Comment