티스토리 뷰


저번 포스팅에서는 Node.js와 Express 프레임 워크로 간단한 서버를 만들어 보았습니다.


이번 포스팅에서는 저번 포스팅의 Express 코드를 그대로 활용하여 socket.io 를 사용하고 간단한 채팅을 구현해보겠습니다.



socket.io는 Node.js에서 사용할 수 있는, 아주 강력한 실시간 소켓통신 엔진입니다. 정말 간단하게는 20줄 이내의 서버코드로 채팅서버를 구현할 수 있습니다.


socket.io 공식 홈페이지에 들어가보시면, 메인 페이지부터 socket.io가 얼마나 쉬운지를 나타내는 10줄 이내의 코드를 선보이고 있습니다.


그럼 코드를 한번 작성해보도록 합시다.


코드를 작성하기 전, npm install socket.io --save 로 모듈 설치해주고, 


다음과 같이 코드를 작성합니다.


app.js

var express = require('express'); // 서버를 위한 express 모듈 가져오기
var path = require('path'); //
var app = express(); // express 서버 정의
var server = require('http').Server(app);
var io = require('socket.io')(server);
app.use(express.static(__dirname));

app.get("/", function(req, res, next) { // express 서버의 / (root 경로) 에 request가 들어오면,
  res.sendFile(path.join(__dirname, 'chat.html')); // response로 "chat.html" 를 전송
})

io.on('connection',function(socket) { //socket.io 연결 시에, 해당 연결에 대해서
  socket.on('chat',function(data) { // chat이라는게 들어오면, 매개변수 data를 아래와 같이 처리한다.
    io.emit('chat',data); //접속한 모든 이에게 data를 전송
  })
})

server.listen(8080, function() { //서버를 listen 상태로 대기시킴
    console.log("Server is running on port 8080..."); //서버가 실행되면 로그가 실행
});


chat.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>hello</title>
    <style>
      * {
        margin:0;
        padding:0;
      }
      .container-input {
        position:fixed;
        left:0;
        bottom:0;
        height:5%;
        width: 100%;
        border-top: 1px black solid;
      }
      input, button {
        height: 100%;
        border: none;
      }
      input#id {
        width: 10%;
        text-align: center;
      }
      input#message {
        width: 79%;
      }
      input#message:focus {
        outline:none;
      }
      button {
        width: 10%;
        background-color: lime;
        color:black;
      }
      .container-chat {
        position:fixed;
        overflow-y: auto;
        max-height: 95%;
        width: 100%;
      }
      body {
        overflow-y: hidden;
      }
      div.chat {
        width: 100%;
      }
      div.id, div.message {
        display: inline;
      }
      div.id {
        width: 10%;
        padding-left: 5px;
      }
      div.message {
        width: 90%;
      }
    </style>
  </head>
  <body>
    <div class="container-chat"></div>
    <div class="container-input">
      <input type="text" value="" disabled="true" id="id">
      <input type="text" value="" placeholder="Input message..." id="message" onkeydown="onKeyDown(event)">
      <button type="button" name="button" onclick="onClick()">Send</button>
    </div>
  </body>
  <script src="/socket.io/socket.io.js"></script>
  <script>
    var socket = io.connect('http://localhost:8080');
    socket.on('chat', function (data) {
      var child = document.createElement('div');
      child.className = "chat"
      child.innerHTML = `<div class="id"><b>${data.id}</b> : </div><div class="message">${data.message}</div>`;
      document.getElementsByClassName('container-chat')[0].appendChild(child)
      document.getElementsByClassName('container-chat')[0].scrollTop = document.getElementsByClassName('container-chat')[0].scrollHeight;
    });
    function onClick() {
      socket.emit('chat',{
        id: document.getElementById('id').value,
        message: document.getElementById('message').value
      });
      document.getElementById('message').value = '';
    }
    function onKeyDown(event) {
      if(event.keyCode == 13) {
        onClick();
      }
    }
    document.getElementById('id').value = 'user#'
    for(var i = 0; i < 4; i++) {
      document.getElementById('id').value += Math.floor(Math.random() * 10)
    }
  </script>
</html>


app.js와 chat.html을 작성하여 app.js를 실행시키면, 아래와 같은 웹 채팅 페이지가 만들어 집니다.



<두 페이지에서 채팅을 주고 받은 모습>


위 그림처럼 채팅이 이루어지는 코드를 짚어보겠습니다. (chat.html의 외적 부분은 짚고 넘어가지 않겠습니다. 따로 질문해주세요)


app.js에서 socket.on('chat',~) 이라는건, 소켓 상에, chat 이라는 이벤트가 발생했을 때, 수행하는 것을 뜻하고, 그 때 app.js는 io.emit('chat',data)을 쓰는데, socket.emit과 io.emit의 차이는, socket.emit 은 socket이 가리키는 해당 소켓에 대해서만 이벤트를 발생시키는 것이고, io.emit은 모든 접속에 대해 이벤트를 발생시킵니다. 


chat.html에서 역시 socket.on('chat',~)이 있고, 이때 div.chat 엘레먼트를 추가해주어 채팅을 표시했습니다. 그리고 채팅의 스크롤바를 최하단으로 내려 신규 채팅을 자동으로 확인할 수 있습니다. 그리고, 버튼의 OnClick 함수에서는, socket.emit이 있는데, 해당 소켓 연결에 대해서 입력창의 data와 id를 서버 측(app.js)에 전송합니다. 엔터를 눌렀을 시에도 마찬가지.


<대략적인 구조도>


이 간단한 구조에, 프론트엔드만 잘 쓰면, 심플한 채팅앱을 만들 수 있습니다.


다음 포스팅에는, MongoDB 모듈인 mongoose를 Node.js에 연동하고, Chatting Scheme를 작성하고, chattings collection을 만들어, 채팅 기록을 남기고, 불러오는 작업에 대해서 다뤄보겠습니다.

댓글