티스토리 뷰

etc

Socket.IO 시작하기

작은성공 2018. 6. 24. 19:46
728x90
반응형

Socket.IO 시작하기
이 글은 https://socket.io/get-started/chat/ 에 올려진 글을 개인적인 공부를 위해 번역 한 글입니다.
혹시 오역을 발견하시면 kimhc999@gmail.com으로 알려주시면 감사하겠습니다.

시작하기 : 채팅 프로그램

여기에서는 기본 채팅 응용 프로그램을 만드는 방법에 대해 다루고자 합니다. 이 튜토리얼은 Node.JS 혹은 Socket.IO에 대한 배경지식이 거의 필요 없습니다. 그러므로 이 튜토리얼은 초보자부터 전문가까지 모든 사람을 대상으로 합니다.

소개
전통적으로 LAMP (PHP)와 같은 인기있는 웹 응용 프로그램 스택에서 채팅 응용 프로그램을 만드는 것은 매우 어려웠습니다. 서버에서 변화가 있는지 끊임없이 체크해야 했으며, 타임스탬프를 기록하고 관리해야 했으며, 속도도 많이 느렸습니다.

소켓은 전통적으로 대부분의 실시간 채팅 시스템이 설계될 때 클라이언트와 서버간에 양방향 통신 채널을 제공하는 솔루션이었습니다.

즉, 서버가 클라이언트에 메시지를 보낼 수 있다는 말입니다. 채팅 메시지를 작성할 때, 문제는 어떻게 서버가 그 메시지를 받아서 또 다른 클라이언트들에게 그 메시지를 보낼 것인지에 대한 것입니다.

웹 프레임 워크
첫 번째 목표로 메시지 목록을 표시하는 간단한 HTML 웹 페이지를 만들 것입니다. 우리는 NodeJS 웹 프레임워크를 사용 할 예정입니다. Node.JS가 설치되어 있지 않다면, 우선 설치 해 주세요.


우선, 우리 프로젝트에 대한 package.json 메니페스트 파일을 만들겁니다. 빈 디렉토리에 package.json을 아래 내용으로 만드세요(저는 chat-example이라는 이름으로 프로젝트를 만들겁니다.)

{
  "name": "socket-chat-example",
  "version": "0.0.1",
  "description": "my first socket.io app",
  "dependencies": {}
}

이제, 우리가 사용할 패키지들을 추가하기 위해, npm install --save를 이용 할 거에요.
아래 문장을 터미널(명령 프롬프트)에서 실행하세요.

npm install --save express@4.15.2

express가 설치되면, index.js를 만들어서 우리가 만들 어플리케이션을 여기에 구현 할 거에요.

var app = require('express')();
var http = require('http').Server(app);

app.get('/', function(req, res){
  res.send('<h1>Hello world</h1>');
});

http.listen(3000, function(){
  console.log('listening on *:3000');
});

위 소스코드는 아래와 같은 뜻이에요.

1. Express는 app를 HTTP 서버에 제공 할 수있는 함수 핸들러로 초기화합니다 (2행 참조).
2. 웹 사이트를 방문 할 때 호출이 될 Route Handler "/"를 정의합니다.
3. 3000 포트에 HTTP 서버를 실행시킵니다.

이제 터미널 혹은 명령 프롬프트에서 node index.js를 실행하면 다음과 같이 표시 될거에요.



그리고, 브라우저에 http://localhost:3000이라고 입력하면 다음과 같이 나올거에요.





HTML 작성

지금까지 index.js에서 res.send를 호출하고 HTML을 전달하는 것에 대해서 알아보았습니다. 전체 애플리케이션의 HTML을 여기에 작성하면 코드가 매우 복잡할겁니다. 그래서, index.html 파일을 만들어서 HTML을 분리 할겁니다.

HTML 문자열 대신 라우터 핸들러에서 sendFile 호출해서 index.html을 넘겨주도록 리팩토링 해 봅시다.


app.get('/', function(req, res){
  res.sendFile(__dirname + '/index.html');
});    

index.html을 다음과 같이 작성합니다.





<!doctype html>
<html>
  <head>
    <title>Socket.IO chat</title>
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      body { font: 13px Helvetica, Arial; }
      form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
      form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
      form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
      #messages { list-style-type: none; margin: 0; padding: 0; }
      #messages li { padding: 5px 10px; }
      #messages li:nth-child(odd) { background: #eee; }
    </style>
  </head>
  <body>
    <ul id="messages"></ul>
    <form action="">
      <input id="m" autocomplete="off" /><button>Send</button>
    </form>
  </body>
</html>
    

Ctrl + C를 누른 뒤 "node index"를 다시 실행하여 프로세스를 다시 실행합니다. 그 후 웹 브라우저에서 페이지를 새로고침 하면 다음과 같이 나타납니다.



Socket.IO 구현

Socket.IO는 두 부분으로 나뉘어집니다.


  • Node.JS로 구현되어 있는 HTTP 서버: socket.io
  • 브라우저 쪽에서 사용되는 클라이언트 라이브러리: socket.io-client


개발하는 동안, socket.io는 클라이언트가 자동으로 제공됩니다. 터미널 혹은 명령 프롬프트에 아래 명령어를 쳐서 모듈을 설치 하세요.

npm install --save socket.io

그러면 모듈이 설치되고 package.json에 종속성이 자동으로 추가됩니다. 이제 index.js에 아래 코드를 추가 해 보세요.



var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res){
  res.sendFile(__dirname + '/index.html');
});

io.on('connection', function(socket){
  console.log('a user connected');
});

http.listen(3000, function(){
  console.log('listening on *:3000');
});


새로운 socket.io에 http(HTTP 서버) 객체를 넘겨서 초기화 한 것에 주목하세요. 그 후 소켓이 연결되면 connection 이벤트를 받는 것을 볼 수 있습니다. connection 이벤트를 받게 되면 console에 표시됩니다.

이제 index.html에서 </body> 앞에 다음과 같은 코드를 추가합니다.


<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io();
</script>
    

socket.io-client를 로드하면 io를 글로벌로 접근할 수 있게 되고,연결 됩니다.

io()를 호출 할 때는 아무 URL도 입력하지 않았어요. 왜냐하면, 그 페이지를 제공하는 서버에 연결되는 것을 기본적으로 제공하기 때문입니다.

서버를 새로 시작하거나 웹사이트를 새로고침하면, 콘솔에 "a user connected"라고 표시되는 것을 볼 수 있습니다.
탭을 여러 개 열게 되면, 메시지가 여러번 나오는 것을 볼 수 있어요.



각 소켓마다 disconnect 이벤트를 발생시키기도 합니다.


io.on('connection', function(socket){
  console.log('a user connected');
  socket.on('disconnect', function(){
    console.log('user disconnected');
  });
});
    

새로 고침을 여러번 해 보면, disconnect 이벤트가 여러번 들어오는 것을 확인해 볼 수 있어요.

이벤트 송신(emit)


Socket.IO의 목적은 다양한 이벤트를 주고 받을 수 있으며, 이벤트를 주고 받을 때 데이터도 포함해서 주고 받을 수 있다는 것입니다. JSON으로 인코딩 할 수있는 모든 객체를 주고 받을 수 있으며, 바이너리 데이터도 주고 받을 수 있습니다.

사용자가 메시지를 입력 할 때, 서버로 'chat message' 이벤트를 전달하도록 해 보겠습니다. index.html의 스크립트 부분을 다음과 같이 바꾸세요.


<script src="/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script>
  $(function () {
    var socket = io();
    $('form').submit(function(){
      socket.emit('chat message', $('#m').val());
      $('#m').val('');
      return false;
    });
  });
</script>
      


그리고 index.js에서 'chat message' 이벤트가 들어오면 콘솔로 출력되도록 합니다.



io.on('connection', function(socket){
  socket.on('chat message', function(msg){
    console.log('message: ' + msg);
  });
});
    

그렇게 하면, 아래 비디오와 같이 나옵니다.



브로드캐스팅(Broadcasting)


다음으로, 서버에서 나머지 클라이언트들에게 이벤트를 보내보도록 하겠습니다.

모든 클라이언트에게 이벤트를 보내기 위해, Socket.IO의 io.emit()을 사용하면 됩니다.

io.emit('some event', { for: 'everyone' });
특정 소켓을 제외한 모든 클라이언트에게 메시지를 보내려면 broadcast를 사용하면 됩니다.




io.on('connection', function(socket){
  socket.broadcast.emit('hi');
});
    

이 경우 간단히 구현하기 위해 이벤트를 보낸 클라이언트를 포함하여 모든 클라이언트에게 보냅니다



io.on('connection', function(socket){
  socket.on('chat message', function(msg){
    io.emit('chat message', msg);
  });
});
    

클라이언트 쪽에서는 'chat message' 이벤트를 받게 되면, 이를 페이지에 표시합니다. 클라이언트 측 JavaScript 코드는 다음과 같습니다.


<script>
  $(function () {
    var socket = io();
    $('form').submit(function(){
      socket.emit('chat message', $('#m').val());
      $('#m').val('');
      return false;
    });
    socket.on('chat message', function(msg){
      $('#messages').append($('<li>').text(msg));
    });
  });
</script>
    

드디어 20줄만의 코드로 채팅 어플리케이션을 완성했습니다. 아래와 같이 동작합니다.



과제

이 어플리케이션을 개선시킬 수 있는 몇가지 아이디어를 아래에 적어두겠습니다.


  • 또 다른 클라이언트가 연결되거나 연결이 끊길 때 연결 된 클라이언트들에게 메시지 보내기
  • 닉네임 지원
  • 자신이 보낸 메시지는 받지 않게 하세요. 대신 엔터키를 누를 때 메시지가 서버를 거치지 않고 곧바로 화면에 표시되게 하세요.
  • 어떠한 사용자가 입력중일 때 "{사용자}이(가) 입력하는 중" 이라는 메시지가 표시되게 하세요.
  • 누가 온라인 상태인지 표시하세요.
  • 비공개 메시지 기능을 추가하세요.
  • 당신의 개선사항을 다른사람들과 함개선 사항을 공유하십시오!



예제 소스


이 예제 소스를 아래 GitHub에 공유 해 두었습니다.

https://github.com/socketio/chat-example


728x90
반응형
댓글