donaricano-btn

1. 타인의 타이핑 확인

채팅을 하다보면 누군가가 글을 입력하고 있다는 알림을 보신적이 있습니다. 특히 slack을 애용하신다면 자주 보셨을 거라 생각합니다. 이번에는 저희가 만든 채팅프로그램에 누군가 입력중이라는 표시를 추가해보도록 하겠습니다.

2. 클라이언트 socket

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; }
      #nick { position: absolute; right: 0; top: 0;}
      #typing { position: absolute; right: 0; bottom: 80px; outline: 1px solid green}
    </style>
  </head>
  <body>
    <ul id="messages"></ul>
    <form action="">
      <input id="m" autocomplete="off" /><button>Send</button>
    </form>
      <input id="nick" placeholder="Enter your name"/>
    <div id="typing"></div>
    <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(e){
          e.preventDefault(); // prevents page reloading
          socket.emit('chat message', $('#nick').val() + ':' +$('#m').val());
          $('#m').val('');
          return false;
        });
        socket.on('chat message', function(msg){
           $('#messages').append($('<li>').text(msg));
         });
        socket.on('typing', function(msg){
            $('#typing').text(msg);
         });
        $('#m').on('keyup', function(e){
          if (e.target.value) {
            socket.emit('typing', $('#nick').val());
          }
        })
      });
    </script>

  </body>
</html>

- <div id="typing"></div>: 타이핑중이라는 표시를 해줄 태그를 추가했습니다.
- keyup 이벤트: 기존 인풋 박스에 keyup 이벤트를 생성하여 키보드입력이 있을시 서버소켓으로 타이핑중인 nickname을 날립니다.
- socket.on('typing'): 서버에서 받아온 typing 관련 메시지를 태그에 출력합니다
- #typing: 태그에 스타일을 추가합니다.

3. 서버 socket

index.js

const app = require('express')();
const http = require('http').createServer(app);
const io = require('socket.io')(http);

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

io.on('connection', function(socket){
	socket.broadcast.emit('chat message', 'user connection...');
	socket.on('chat message', function(msg){
		socket.broadcast.emit('typing', '');
		io.emit('chat message', msg);
	});
	socket.on('disconnect', function(){
		socket.broadcast.emit('chat message', 'user disconnection...');
	});
	socket.on('typing', function(msg){
		if(msg !== '') {
			socket.broadcast.emit('typing', msg + ' is typing...');
		}
	});
});

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

- socket.on('typing'): 클라이언트에서 오는 typing 메시지를 리슨하고 있습니다. 그리고 broadcast를 통해 저를 제외한 다른 사람들에게 타이핑 중이라는 메시지를 보냅니다.
- 입력을 끝내고 send를 눌렀을때 받는 chat message 이벤트에 typing 메시지값을 '' 로 전송하여 타이핑이 끝났음을 클라이언트에게 표시합니다.

위 화면처럼 잘 나왔다면 성공입니다.

4. 마무리

조금 아쉬운 부분은 socket.io api 문서를 참고하여 더욱 다양한 기능을 앞으로 추가해야될것 같습니다.

블로그 이미지

리딩리드

,
donaricano-btn

socket.io 글들을 순차적으로 진행하시면 socket.io를 이해하는데 더욱 도움이 됩니다.

1. 닉네임추가

기존에 완성했던 채팅창에는 누구의 글인지 알 수가 없었습니다. 이제는 닉네임을 추가해서 조금더 채팅창 처럼 보이도록 하겠습니다. 

2. 클라이언트 socket.io

index.html

<style>
...
#nick { position: absolute; right: 0; top: 0;}
</style>

<body>
    <ul id="messages"></ul>
    <form action="">
      <input id="m" autocomplete="off" /><button>Send</button>
    </form>
      <input id="nick" placeholder="Enter your name"/>// 닉네임 form 추가
    <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(e){
          e.preventDefault(); // prevents page reloading
          socket.emit('chat message', $('#nick').val() + ':' +$('#m').val());
          $('#m').val('');
          return false;
        });
        socket.on('chat message', function(msg){
           $('#messages').append($('<li>').text(msg));
         });
      });
    </script>
  </body>
  

- 먼저 닉네임을 만들 input 박스를 추가합니다.
- socket.emit() 부분에 닉네임을 포함한 msg 를 만들어 전송합니다
- style 부분에 저희가 만든 input에 absolute 포지션을 추가합니다.

3. 테스트

창을 여러게 열고 이름을 입력해보겠습니다.

이름이 잘 노출되나요??? 위와같이 나왔다면 성공입니다.
저는 클라이언트 사이드에서 임의로 닉네임을 추가했지만 만약 서버에 회원정보가 있다면 서버에서 클라이언트로 아이디를 추가해서 내려주는 구조로 만드는것이 좋을 것 같습니다.

블로그 이미지

리딩리드

,
donaricano-btn

1. 다른유저가 접속했는지 확인

앞의 소스들은 다른 소켓(클라이언트)이 접속을 했는지 않했는지 확인을 할 수 없었습니다. 
이번 장에서는 socket.broadcast를 이용하여 접속 여부를 기능을 추가해보도록 하겠습니다.

2. 서버 소켓

index.js

const app = require('express')();
const http = require('http').createServer(app);
const io = require('socket.io')(http);

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

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

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

- 앞의 소스와 유사합니다. 단지 소켓 이벤트를 받는 부분에 집중해주세요
- 처음 접속했다면 socket.broadcast를 이용하여 자신을 제외한 다른 클라이언트들에게 접속 여부를 알립니다.
- socket.on('disconnect') : 해당 함수로 소켓 통신이 끝났는지 확인 할 수 있습니다. 이곳에다 위와같은 작업을 추가합니다.

3. 확인

node index.js

localhost:3000

서버를 가동하고 localhost:3000으로 접속해주세요. 그리고 이후에 창을 하나더 띄워주세요

다시 브라우저 하나를 닫아주세요.

위와같이 나왔다면 성공입니다 :)

다음은 접속 유저의 닉네임을 추가해보도록 하겠습니다.

블로그 이미지

리딩리드

,
donaricano-btn

1. 이벤트 발생

앞의 예제에서 socket.io를 연동하고 클라이언트에서 채팅창을 구현했습니다. 또한 클라이언트가 소켓을 연결헀을때 서버 로그로 접속되는것 까지 확인했습니다. 이번에는 클라이언트에서 발생한 이벤트를 서버로 전달하겠습니다.

예를들어 클라이언트 입력폼에 메시지를 submit 하면 서버에서 해당메시지를 받는지 확인하겠습니다.

2. 클라이언트 설정

index.html

<body>
    <ul id="messages"></ul>
    <form action="">
      <input id="m" autocomplete="off" /><button>Send</button>
    </form>
    <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(e){
          e.preventDefault(); // prevents page reloading
          socket.emit('chat message', $('#m').val());
          $('#m').val('');
          return false;
        });
      });
    </script>
    
  </body>

기존에 작성했던 클라이언트 코드 <script> 부분을 위와같이 추가합니다.
- socket.emit() : 첫번째 변수가 key 값이 됩니다. server 소켓에서 이벤트를 감지할 경우 해당 키값으로 이벤트를 listen 합니다. 두번째 변수는 value 를 전달합니다.

3. 서버설정

index.js

const app = require('express')();
const http = require('http').createServer(app);
const io = require('socket.io')(http);

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

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

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

- socket.on(): 첫번째 변수는 키값으로 클라이언트에서 소켓 이벤트를 발생시켰을때 연결됩니다. 두번쨰 변수의 함수는 콜백함수로 클라이언트에서 넘어온 변수값을 받습니다.

위와 같이 localhost:3000으로 접속하여 채팅창에 값을 입력후 send를 누루면 서버 창에 log로 저희가 입력한 값들이 출력됩니다. 

4. 브로드캐스트

서버로 받은 메시지를 이젠 다른 클라이언트들이 공유할 수 있도록 브로드캐스트 해보겠습니다.

index.html

 <body>
    <ul id="messages"></ul>
    <form action="">
      <input id="m" autocomplete="off" /><button>Send</button>
    </form>
    <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(e){
          e.preventDefault(); // prevents page reloading
          socket.emit('chat message', $('#m').val());
          $('#m').val('');
          return false;
        });
        socket.on('chat message', function(msg){
           $('#messages').append($('<li>').text(msg));
         });
      });
    </script>

  </body>

- socket.on() : 서버에서 요청하는 이벤트를 listen 하는 역할을하며 데이터를 받아와 클라이언트에 노출시키는 작업을 할 수 있습니다.

index.js

const app = require('express')();
const http = require('http').createServer(app);
const io = require('socket.io')(http);

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

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

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

- socket.on(): 다른 소켓(클라이언트)온 이벤트를 처리합니다
- io.emit() : 해당함수를 이용하여 서버에 데이터를 연결된 소켓으로 전달하는 역할을 합니다. 저희가 만들려면 채팅프로그램의 핵심입니다.

node index.js

서버를 활성화 시킨후 localhost:3000 브라우저를 여러개 띄워주세요.

- 위 화면처럼 입력을 하면 양쪽의 브라우저에서 모두 노출되나요? 그렇다면 성공입니다. :)

5. 나를 제외한 클라이언트에게 브로드캐스팅

socket.broadcast.emit('chat message', 'hi');

socket.broadcast: 나를 제외한 다른 사람에게만 브로드캐스팅합니다. 

const app = require('express')();
const http = require('http').createServer(app);
const io = require('socket.io')(http);

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

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

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

- 저희가 작업한 server 소스중에 이벤트 리슨하는부분을 위와같이 변경해주세요.
이후에 localhost:3000을 하나씩 띄운다면 기존에 있던 창에 hi가 출력되는것을 볼 수 있습니다.

블로그 이미지

리딩리드

,