JavaScript로 채팅 애플리케이션 구축

채팅 앱을 구축해야 하는 이유



무언가를 배우는 쉬운 방법은 문제를 해결하려고 노력하는 것입니다. 제 경우에는 [Node JS] 앱( https://nodejs.org/en/ )을 빌드하고 클라우드에 배포하고 싶었습니다(나중에 Heroku과 같이 🔎 아웃).



So here is the problem >> Most of my friends were working in different organizations, to communicate with each other on desktop we tried apps like hangout ... but most of the apps were blocked in most of the organizations. WhatsApp Web was not launched by then (Aug 2014), so I decided to solve this problem by learning Node JS and socket.io.




시작하기




  • NodeJS를 설치하고 아래의 package.json으로 새 노드 프로젝트를 시작합니다.

  • 
    {
      "name": "Chat-App",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "author": "",
      "license": "ISC",
      "dependencies": {
        "express": "^4.13.3",
        "moment": "^2.12.0",
        "socket.io": "^1.3.7"
      }
    }
    
    


    응용 프로그램 설정을 위한 설정Node JS 파일

    var PORT = process.env.PORT || 3000;
    var express = require("express");
    var app = express(); // express app which is used boilerplate for HTTP
    var http = require("http").Server(app);
    // expose the folder via express thought
    app.use(express.static(__dirname + '/public'));
    http.listen(PORT, function() {
      console.log("server started");
    });
    


    UI용 클라이언트측 공용 폴더 설정
  • index.html을 추가하여 랜딩 페이지 시작

  • 채팅 창에서 로그인한 후 채팅 화면 열기에 추가chat.html

  • 노드 서버(Socket.io 사용)에서 받은 메시지를 표시하려면 app.js을 추가합니다.

  • 소켓 통신


  • 환영 메시지 표시 중

  • 사용자가 채팅방에 참가하면 시스템에 로그인하라는 환영 메시지가 표시됩니다.

      socket.emit("message", {
        text: "Welcome to Chat Appliction !",
        timestamp: moment().valueOf(),
        name: "System"
      });
    


    서버.js

    또한 다른 사람이 방에 참가한 경우 클라이언트 측에서 이벤트를 발생시켜야 합니다.

     socket.on("connect", function() {
       console.log("Connected to Socket I/O Server!");
       console.log(name + " wants to join  " + room);
       // to join a specific room
       socket.emit('joinRoom', {
         name: name,
         room: room
       });
     });
    


    app.js

    이제 서버는 이 메시지를 해당 룸에 참가한 모든 사용자에게 브로드캐스트합니다.

      socket.on('joinRoom', function(req) {
        clientInfo[socket.id] = req;
        socket.join(req.room);
        //broadcast new user joined room
        socket.broadcast.to(req.room).emit("message", {
          name: "System",
          text: req.name + ' has joined',
          timestamp: moment().valueOf()
        });
    
      });
    


    서버.js
  • 사용자가 입력할 때 알림 표시

  • 사용자가 메시지 필드에 입력하면 클라이언트 측에서 해당 이벤트를 내보냅니다.

     $('#messagebox').keyup(function() {
       console.log('happening');
       typing = true;
       $("#icon-type").removeClass();
       //console.log("typing typing ....");
       //socket.emit('typing', 'typing...');
       socket.emit('typing', {
         text: name + " is typing ..."
       });
       clearTimeout(timeout);
       timeout = setTimeout(timeoutFunction, 1000);
     });
    


    app.js

    그런 다음 서버는 이 알림을 브로드캐스트합니다.

      socket.on('typing', function(message) { // broadcast this message to all users in that room
        socket.broadcast.to(clientInfo[socket.id].room).emit("typing", message);
      });
    


    서버.js
  • 사용자가 메시지를 보내는 경우
    사용자가 메시지 양식을 제출하면 입력을 삭제한 후 메시지가 서버로 방출됩니다.

  •  var $form = $("#messageForm");
     var $message1 = $form.find('input[name=message]');
     $form.on("submit", function(event) {
       event.preventDefault();
       var msg = $message1.val();
       //prevent js injection attack
       msg = msg.replace(/</g, "&lt;").replace(/>/g, "&gt;").trim();
       if (msg === "") return -1; //empty messages cannot be sent
    
       socket.emit("message", {
         text: msg,
         name: name
       });
       // show user messageForm
       var $messages = $(".messages");
       var $message = $('<li class = "list-group-item"></li>');
    
       var momentTimestamp = moment().format("h:mm a");
       // $(".messages").append($('<p>').text(message.text));
       $message.append("<strong>" + momentTimestamp + " " + name + "</strong>");
       //$message.append("<p>" + $message1.val()+ "</p>");
       $message.append($("<p>", {
         class: "mymessages",
         text: $message1.val()
       }));
       $messages.append($message);
       $message1.val('');
       // manage autoscroll
       var obj = $("ul.messages.list-group");
       var offset = obj.offset();
       var scrollLength = obj[0].scrollHeight;
       //  offset.top += 20;
       $("ul.messages.list-group").animate({
         scrollTop: scrollLength - offset.top
       });
    
     });
    


    app.js

    서버는 위의 클라이언트 이벤트를 수신하고 입력 메시지가 미리 정의된 명령 {@currentUsers give list of users in current chat room}이 아닌지 확인한 후 수신된 메시지를 브로드캐스트합니다.

      socket.on("message", function(message) {
        console.log("Message Received : " + message.text);
        // to show all current users
        if (message.text === "@currentUsers") {
          sendCurrentUsers(socket);
        } else {
          //broadcast to all users except for sender
          message.timestamp = moment().valueOf();
          //socket.broadcast.emit("message",message);
          // now message should be only sent to users who are in same room
          socket.broadcast.to(clientInfo[socket.id].room).emit("message", message);
          //socket.emit.to(clientInfo[socket.id].room).emit("message", message);
        }
    
    


    서버.js
  • 사용자가 메시지를 보냈는지 여부 확인

  • 클라이언트 쪽에서 메시지를 받으면 사용자가 채팅 창을 열었는지 확인합니다. 채팅창이 열려있다면 메시지를 보고 이벤트를 발생시킨다는 뜻입니다.

    // notify, only when the user has not open chat view
       if (document[hidden]) {
         notifyMe(message);
         // also notify server that user has not seen messgae
         var umsg = {
           text: name + " has not seen message",
           read: false
         };
         socket.emit("userSeen", umsg);
       } else {
         // notify  server that user has seen message
         var umsg = {
           text: name + " has seen message",
           read: true,
           user: name
         };
         socket.emit("userSeen", umsg);
       }
     });
    


    app.js
    채팅창이 최소화되면 사용자에게 알림이 전송됩니다.

    사용자가 알림창을 클릭하면 사용자가 본 메시지가 출력되어 파란색 체크(메시지가 아닌 사용자)가 녹색(사용자가 메시지를 본 것임)으로 변환됩니다.

    function notifyMe(msg) {
       // Let's check if the browser supports notifications
       if (!("Notification" in window)) {
         alert("This browser does not support desktop notification,try Chromium!");
       }
    
       // Let's check whether notification permissions have already been granted
       else if (Notification.permission === "granted") {
         // If it's okay let's create a notification
         //  var notification = new Notification(msg);
         var notification = new Notification('Chat App', {
           body: msg.name + ": " + msg.text,
           icon: '/images/apple-icon.png' // optional
         });
         notification.onclick = function(event) {
           event.preventDefault();
           this.close();
           // assume user would see message so broadcast userSeen event
           var umsg = {
             text: name + " has seen message",
             read: true,
             user: name
           };
           socket.emit("userSeen", umsg);
           //window.open('http://www.mozilla.org', '_blank');
         };
       }
       // Otherwise, we need to ask the user for permission
       else if (Notification.permission !== 'denied') {
         Notification.requestPermission(function(permission) {
           // If the user accepts, let's create a notification
           if (permission === "granted") {
             var notification = new Notification('Chat App', {
               body: msg.name + ": " + msg.text,
               icon: '/images/apple-icon.png' // optional
             });
             notification.onclick = function(event) {
               event.preventDefault();
               this.close();
               var umsg = {
                 text: name + " has seen message",
                 read: true,
                 user: name
               };
               socket.emit("userSeen", umsg);
               // assume user would see message so broadcast userSeen event
    
             };
           }
         });
       }
    
       // At last, if the user has denied notifications, and you
       // want to be respectful there is no need to bother them any more.
     }
    


    app.js

    사용자가 메시지를 볼 때 서버 측에 알려야 함

     // to check if user seen Message
      socket.on("userSeen", function(msg) {
        socket.broadcast.to(clientInfo[socket.id].room).emit("userSeen", msg);
        //socket.emit("message", msg);
    
      });
    


    서버.js
  • 클라우드에 배포

  • 이제 코드를 클라우드에 배포해야 하며 이는 Heroku을 통해 쉽게 수행할 수 있습니다. Heroku에서는 한 번에 5개의 애플리케이션을 무료로 배포할 수 있습니다.


    결론



    이것을 친구들과 공유했을 때 정말 기뻤습니다. 조직 정책으로 인해 차단되지 않은 웹 애플리케이션을 통해 채팅할 수 있었습니다.
    이것은 4년 된 프로젝트입니다. dev.to에 대해 알게 되었을 때 여기에 제 학습 내용을 넣기로 결정했습니다.

    이 채팅 애플리케이션을 개선하기 위해 다음 기능을 추가할 수 있습니다.
  • OAuth2를 사용하여 인증 구현
  • 사용자 이름 변경 옵션을 추가하고 프로필 사진을 추가합니다.
  • 채팅 메시지를 유지하기 위해 DB를 추가합니다.
  • 기타 기능...

  • 소스 코드 : https://github.com/bhupendra1011/Chat-App
    데모: https://bhupendra1011.herokuapp.com/

    좋은 웹페이지 즐겨찾기