728x90

Node.js 채팅 기본코드를 좀 더 수정 보완하고 Web 채팅과 안드로이드 채팅이 동시에 되는 걸 확인했다.

Node.js 설치 및 Express, socket.io 설치에 대한 사항은 이전 게시글을 참조하면 된다.




서버 chat.js


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

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

var numUsers=0;
var usernames=[];
io.on('connection', (socket) => {
    var addedUser = false;
    socket.on('join', function (username) {
        if (addedUser) return;
        socket.username = username;
        ++numUsers;
        addedUser = true;
        usernames.push(socket.username);
        console.log(socket.username + "님이 접속하셨습니다.");
        console.log('접속한 사용자수 : '+numUsers+'명');
        socket.broadcast.emit('userjoinedthechat', socket.username + "님이 접속하셨습니다.");
        updateUsernames();
    });

    function updateUsernames(){
        io.sockets.emit('usernames', usernames);
    }

    socket.on('messagedetection', (senderNickname, messageContent) => {
        // 서버 콘솔상에 메시지 보여주기
        console.log(senderNickname + " :" + messageContent);
        //message object 생성
        let message = {"message": messageContent, "senderNickname": senderNickname}
        // 클라이언트(Web, Android)로 메시지 전송
        io.emit('message', message); // 나를 포함한 모든 클라이언트에게 전송
    });

    socket.on('disconnect', function () {
        if (addedUser) {
            --numUsers;
            usernames.splice(usernames.indexOf(socket.username), 1);
        }
        console.log(socket.username+"님이 퇴장했습니다");
        console.log('접속한 사용자수 : '+numUsers+'명');
        socket.broadcast.emit("userdisconnect", socket.username + "님이 퇴장했습니다");
        // 나를 제외한 모든 클라이언트에게 전송
        updateUsernames();
    });

});

server.listen(3000, () => {
    console.log('Node chat app is running on port 3000');
});


Web Chatting UI

- css 파일을 별도 분리하여 인식시켰더니 감지를 못하더라. 그래서 같은 파일에 추가했다.

- 채팅 메시지가 많으면 자동으로 가장 하단의 메시지 내용이 보이도록 처리

- 줄바꿈 처리 기능 코드 추가 (스마트폰에서는 엔터키 입력 안되게 처리 코드 추가)

- Web 채팅과 Android 채팅 동시에 가능

- 반응형 화면으로 스마트폰과 PC에서 보이는 화면이 다르게 처리 (커스터마이징 필요)


<!DOCTYPE html>
<html>
<head>
<title>Web Chat Messenger</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" type="text/css" rel="stylesheet">
<style type="text/css">
.container{max-width:1170px; margin:auto;}
img{ max-width:100%;}

.messaging { padding: 0 0 50px 0;}

.inbox_msg {
  border: 1px solid #c4c4c4;
  clear: both;
  overflow: hidden;
}
.inbox_people {
  background: #f8f8f8 none repeat scroll 0 0;
  float: left;
  overflow: hidden;
  width: 35%; border-right:1px solid #c4c4c4;
}
.top_spac{ margin: 20px 0 0;}

.headind_srch{ padding:10px 29px 10px 20px; overflow:hidden; border-bottom:1px solid #c4c4c4;}
.recent_heading {float: left; width:100%;}
.recent_heading h4 {
  color: #05728f;
  font-size: 21px;
  margin: auto;
}

.inbox_chat { height: 550px; overflow-y: scroll;}

.mesgs {
  float: left;
  padding: 20px 5px 5px 10px;
  width: 65%;
}
.msg_history {
  height: 500px;
  overflow-y: auto;
  background: #FFFFFF;
}

.incoming_msg_img {
  display: inline-block;
  width: 6%;
}
.received_msg {
  display: inline-block;
  padding: 0 0 0 10px;
  vertical-align: top;
  width: 92%;
 }
.received_withd_msg { width: 77%;}
.received_withd_msg p {
  background: #F3E2A9 none repeat scroll 0 0;
  border-radius: 3px;
  color: #646464;
  font-size: 14px;
  margin: 0;
  padding: 5px 10px 5px 12px;
  width: 100%;
}
.time_date {
  color: #747474;
  display: block;
  font-size: 12px;
  margin: 8px 0 0;
}

.type_msg {border-top: 1px solid #c4c4c4;position: relative;}
.sent_msg {
  float: right;
  width: 76%;
}
.sent_msg p {
  background: #05728f none repeat scroll 0 0;
  border-radius: 3px;
  font-size: 14px;
  margin: 0; color:#fff;
  padding: 5px 10px 5px 12px;
  width:100%;
}
.outgoing_msg{ overflow:hidden; margin:26px 0 26px;}
.input_msg_write input {
  background: rgba(0, 0, 0, 0) none repeat scroll 0 0;
  border: medium none;
  color: #4c4c4c;
  font-size: 15px;
  min-height: 48px;
  width: 100%;
}

.msg_send_btn {
  background: #05728f none repeat scroll 0 0;
  border: medium none;
  border-radius: 50%;
  color: #fff;
  cursor: pointer;
  font-size: 17px;
  height: 33px;
  position: absolute;
  right: 0;
  top: 11px;
  width: 33px;
}


@media screen and (max-width: 800px) {
    .inbox_msg {
      display: block;
      width: 100%;
    }
    .inbox_people {width: 100%;}
    .inbox_chat { width: 100%;height: 250px;}

    .mesgs {
      display: block;
      width: 100%;
      padding: 20px 0px 10px 0px;
    }
    .msg_history {width: 100%;height: 450px;}
    .type_msg {width: 100%;}

}

</style>
</head>

<body>
<div class="container">
    <!--Form to enter UserName-->
    <div class="row" id="nickWrap">
        <div class="col-xs-9">
            <form id="setNick">
                <input id="username" class="form-control" placeholder="사용자명을 입력하세요"/>
                <input type="submit" class="btn btn-primary">
            </form>
        </div>
    </div>
    <!--end username-->
<div class="messaging" id="contentWrap">
<h3 class=" text-center" id="msg_leave">Messaging</h3>
    <div class="inbox_msg">
        <div class="inbox_people">
          <div class="headind_srch">
            <div class="recent_heading">
              <h4>접속 사용자 현황</h4>
            </div>
          </div>

        <div class="inbox_chat">
            <div class="panel panel-default">
                <div class="panel-body" id="users"></div>
            </div>           
        </div>
    </div>

    <div class="mesgs">
        <div class="msg_history" id="chat">
        </div>

        <div class="type_msg">
            <form id="send-message">
            <div class="input_msg_write">
              <textarea rows="3" id="message" class="form-control" placeholder="메시지를 입력하세요" /></textarea>
              <button class="msg_send_btn" type="button"><i class="fa fa-paper-plane-o" aria-hidden="true"></i></button>
            </div>
            </form>
        </div>
    </div>
</div>

<!--node.js and Jquery code-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.1/socket.io.js"></script>
<script>
$(function () {
    var socket = io();
    var myname;
    var i;
    var filter = "win16|win32|win64|mac|macintel";

    $('#contentWrap').hide();

    $('#setNick').submit(function () {
        myname = $('#username').val();
        if(myname.length == 0) {
            alert('이름을 입력하세요');
            return false;
        }
        socket.emit('join', myname);
        $('#nickWrap').hide();
        $('#contentWrap').show();
        return false;
    });

    //List of users
    socket.on('usernames', function (message) {
        var html = '';
        for (i = 0; i < message.length; i++) {
            html += message[i] + '<br/>'
        }
        $('#users').html(html);
    });

    $('.msg_send_btn').click(function (e) {
        e.preventDefault();
        msg_send();
    });

    $('#message').keypress(function (e) {
        if ( navigator.platform ) { // 모바일 접속이면 엔터키를 동작 안되게 처리
            if(filter.indexOf( navigator.platform.toLowerCase() ) > 0){
                if (e.which == 13 && !e.shiftKey) { // Shift + Enter키이면 줄바꿈처리 가능
                    msg_send();
                    return false;
                }
            }
        }
    });

    function msg_send(){
        if($('#message').val().length ==0){
            alert('메시지가 입력되지 않았습니다');
            $('#message').focus();
            return false;
        }
        socket.emit('messagedetection', myname, $('#message').val());
        $('#message').val(''); // 메시지를 전송하고 메시지 전송 창 내용을 비운다.
    }

    socket.on('message', function (msg) {
        msg.message = msg.message.replace(/(?:\r\n|\r|\n)/g, '<br />'); // 줄바꿈 처리
        if(myname == msg.senderNickname){ // 내가 전송한 메시지
            $('#chat').append('<div class="outgoing_msg"><div class="sent_msg"><p> '+ msg.message +'</p><span class="time_date">'+new Date().toLocaleString()+'</span></div></div>');
        } else { // 상대방이 보낸 메시지
            $('#chat').append('<div class="incoming_msg"><div class="incoming_msg_img"> <img src="https://ptetutorials.com/images/user-profile.png" alt="sunil"> </div><div class="received_msg"><div class="received_withd_msg"><p>'+ msg.message +'</p><span class="time_date">'+msg.senderNickname+', '+new Date().toLocaleString()+'</span></div></div></div>');
        }
        $("#chat").scrollTop($("#chat")[0].scrollHeight); // 최근 메시지 출력된 내용이 보이게 처리
    });

    socket.on('userjoinedthechat', function (msg) {
        $('#chat').append('<div class="incoming_msg"><div class="incoming_msg_img"></div><div class="received_msg"><div class="received_withd_msg"><p>'+ msg +'</p><span class="time_date">'+new Date().toLocaleString()+'</span></div></div></div>');
        $("#chat").scrollTop($("#chat")[0].scrollHeight); // 최근 메시지 출력된 내용이 보이게 처리
    });
   
    socket.on('userdisconnect', function (msg) {
        $('#chat').append('<div class="incoming_msg"><div class="incoming_msg_img"></div><div class="received_msg"><div class="received_withd_msg"><p>'+ msg +'</p><span class="time_date">'+new Date().toLocaleString()+'</span></div></div></div>');
        $("#chat").scrollTop($("#chat")[0].scrollHeight); // 최근 메시지 출력된 내용이 보이게 처리
    });

});
</script>
</body>
</html>



채팅 UI는 bootstrap 코드를 검색해서 원하는 코드로 변경하면 모바일 Web에서도 깔끔하게 보이게 처리할 수 있을 것이다.

블로그 이미지

Link2Me

,