본문 바로가기
Javascript/Node.js

[NodeJS] 채팅방UI 구성, 소켓 연결을 통한 채팅기능 완성하기 [express와 socket.io을 이용한 채팅기능 구현하기 - 2장]

by 임채훈 2019. 2. 27.

2019/02/27 - [NodeJS/NodeJS로 간단한 채팅기능 만들기] - [NodeJS] npm으로 express, socket.io 모듈 설치 및 웹 서버 구축, 소켓 연결하기 [express와 socket.io을 이용한 채팅기능 구현하기 - 1장]

 

 

이전 장에 이어 클라이언트가 이용할 채팅방의 UI를 그럴듯하게 구성하고

 

서버와 소켓간에 데이터를 주고받고 유저들끼리 채팅을 주고받을수 있도록 구현해보도록 하겠습니다.

 

 

 

1. chat.html파일에서 CSS스타일 작성

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        #container {
            width: 400px;
            height: 400px;
            border: 1px solid black;
            background: ivory;
        }
        #chatView {
            height: 90%;
            overflow-y: scroll;
        }
        #chatForm {
            height: 10%;
            border-top: 1px solid black;
            text-align: center;
        }
        #msg {
            width: 80%;
            height: 32px;
            border-radius: 8px;
        }
        #send {
            width: 16%;
            height: 34px;
            border-radius: 50px;
            background: black;
            color: white;
        }
    </style>
</head>
<body>
    <div id="container">
        <div id="chatView">
        </div>
        <form id="chatForm" onsubmit="return false">
            <input type="text" id="msg">
            <input type="submit" id="send" value="전송">
        </form>
    </div>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="/socket.io/socket.io.js"></script>
    <script>
        var socket = io();
        
    </script>
</body>
</html>
cs

 

container의 가로, 세로 길이를 임의로 지정해줍니다

 

chatView(채팅내용) 공간은 지정해준 세로 길이를 벗어난다면 scroll화 될수있도록 설정해주고,

 

msg입력창과 send버튼은 html 기본 디자인이 비교적 못생겼기 때문에 개인이 만족할 수 있는 스타일로 꾸며주면 됩니다.

 

 

- 결과

 

 

 

2. 유저가 메세지를 전송하면 서버가 메세지의 내용을 받아서 콘솔화면에 출력하기

 

- chat.html의 script코드

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<body>
    <div id="container">
        <div id="chatView">
 
        </div>
        <form id="chatForm" onsubmit="return false">
            <input type="text" id="msg">
            <input type="submit" id="send" value="전송">
        </form>
    </div>
    
 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="/socket.io/socket.io.js"></script>
 
    <script>
        var socket = io();
        
        var chatView = document.getElementById('chatView');
        var chatForm = document.getElementById('chatForm');
 
        chatForm.addEventListener('submit'function() {
            var msg = $('#msg');
 
            if (msg.val() == '') {
                return;
 
            } else {
                socket.emit('SEND', msg.val());
 
                var msgLine = $('<div class="msgLine">');
                var msgBox = $('<div class="me">');
 
                msgBox.append(msg.val());
                msgBox.css('display''inline-block');
                msgLine.css('text-align''right');
                msgLine.append(msgBox);
 
                $('#chatView').append(msgLine);
            }
        });
    </script>
</body>
cs
 

- chat.html의 CSS코드

 
1
2
3
4
5
6
7
8
9
10
11
<style>
    .msgLine {
        margin: 15px;
    }
    .msgBox {
        border: 1px solid black;
        background: skyblue;
        padding: 2px 5px;
        border-radius: 10px;
    }
</style>
cs

 

0. msgLine은 여러개의 msgLine이 일정한 간격을 갖고 적절한 위치를 갖기위해서 임의로 정해주고 msgBox도 입맛대로 지정해줍니다.

 

 

1. chatForm의 onsubmit이벤트가 발생하면 즉. 전송버튼이 마우스또는 키보드로인해 눌러졌을때 특정한 로직을 수행하도록 합니다.

 

2. msg의 값이 없을때는 아무 일도 일어나지않도록 해주고 값이 있을때 

socket에 'SEND'라는 이벤트명을 지정해주면서 msg의 값을 emit이란 메소드를 이용해서 서버측으로 날립니다.

 

3. chatView에 하나의 메세지를 가지고 있을 block레벨 element인 div태그에 임의로 CSS style을 지정해주기위해 msgLine이란 클래스를 넣어서 하나 만들어줍니다.

 

4. msgLine에 실제로 메세지의 내용을 가질 박스인 msgBox태그도 하나 만들어 줍니다.

 

5. msg의 val() (값)을 msgBox에 넣어주고, 내가 보낸 메세지는 chatView상에서 오른쪽에 위치하게 하도록 부모박스인 msgLine에 text-align속성을 right로 지정해줍니다.

 

6. msgLine에 msgBox를 넣어주고, 마지막에 최종적으로 chatView에 msgLine을 넣어주면 됩니다.

 

 

- server.js파일에서 클라이언트가 보낸 메세지 받아서 콘솔화면에 출력하기

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var express = require('express');
var app = express();
 
var http = require('http');
var server = http.Server(app);
 
var socket = require('socket.io');
var io = socket(server);
 
var port = 5000;
 
app.use('/'function(req, resp) {
    resp.sendFile(__dirname + '/chat.html');
});
 
io.on('connection'function(socket) {
    console.log('User Join');
 
    socket.on('SEND'function(msg) {
        console.log(msg);
    });
});
 
server.listen(port, function() {
    console.log('Server On !');
});
cs

 

특정 소켓에서 SEND라는 이벤트가 발생이 되고 어떠한 파라미터 또는 데이터가 넘어온다면 

 

console.log를 이용해서 넘어온 메세지를 콘솔화면에 출력할 수 있도록 해줍니다.

 

 

- 결과

 

 

 

위와 같이 성공적으로 내가 보낸 메세지가 채팅방에 나타나고 서버가 그 메세지를 받아서 콘솔화면에 잘 출력을하고 있는걸 확인할 수 있습니다.

 

 

그리고 추가적으로 메세지를 전송했을때 msg를 입력하는 input box를 비워주고

 

chatView가 overflow되었을때, 즉. 스크롤이 활성화 되었을때 메세지를 보낼때마다 스크롤의 위치를 가장 아래로 내려주기 위해서

 

아래 코드의 41번, 42번 라인의 코드를 추가해줍니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<body>
    <div id="container">
        <div id="chatView">
 
        </div>
        <form id="chatForm" onsubmit="return false">
            <input type="text" id="msg">
            <input type="submit" id="send" value="전송">
        </form>
    </div>
    
 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="/socket.io/socket.io.js"></script>
 
    <script>
        var socket = io();
        
        var chatView = document.getElementById('chatView');
        var chatForm = document.getElementById('chatForm');
 
        chatForm.addEventListener('submit'function() {
            var msg = $('#msg');
 
            if (msg.val() == '') {
                return;
 
            } else {
                socket.emit('SEND', msg.val());
 
                var msgLine = $('<div class="msgLine">');
                var msgBox = $('<div class="me">');
 
                msgBox.append(msg.val());
                msgBox.css('display''inline-block');
                msgLine.css('text-align''right');
                msgLine.append(msgBox);
 
                $('#chatView').append(msgLine);
 
                msg.val('');
                chatView.scrollTop = chatView.scrollHeight;
            }
        });
    </script>
</body>
cs

 

 

 

이제 유저간에 서로 채팅을 할수있도록 구현하도록 하겠습니다.

 

 

- server.js파일

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
var express = require('express');
var app = express();
 
var http = require('http');
var server = http.Server(app);
 
var socket = require('socket.io');
var io = socket(server);
 
var port = 5000;
var socketList = [];
 
app.use('/'function(req, resp) {
    resp.sendFile(__dirname + '/chat.html');
});
 
io.on('connection'function(socket) {
    socketList.push(socket);
    console.log('User Join');
 
    socket.on('SEND'function(msg) {
        console.log(msg);
        socketList.forEach(function(item, i) {
            console.log(item.id);
            if (item != socket) {
                item.emit('SEND', msg);
            }
        });
    });
 
    socket.on('disconnect'function() {
        socketList.splice(socketList.indexOf(socket), 1);
    });
});
 
server.listen(port, function() {
    console.log('Server On !');
});
cs

 

1. 먼저 채팅에 접속한 유저들의 소켓을 가지고 있을 배열변수(socketList)를 선언해줍니다. 11번 Line.

 

2. 특정 소켓에서 connection 이벤트가 발생할 시(소켓이 연결이 됐을때) socketList에 push해줍니다. 18번 Line.

 

3. 특정 소켓에서 disconnect 이벤트가 발생할 시(소켓 연결이 해제됐을때) socketList에서 해당 socket을 삭제해줍니다. 31번 ~ 33번 Line.

 

4. 특정 소켓에서 SEND 이벤트가 발생할 시(어떤 유저가 메세지를 보냈을 때) socketList에 저장된 socket의 id라는 속성값을 통해 비교해서 메세지를 보낸 유저를 제외하고 나머지 유저들에게 각각 메세지를 보내주는 (SEND라는 이벤트명으로 받은 메세지를 각각 emit해줌) 로직을 구성합니다. 23번 ~ 28번 Line.

 

 

 

- chat.html 파일

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<script>
    var socket = io();
        
    var chatView = document.getElementById('chatView');
    var chatForm = document.getElementById('chatForm');
 
    chatForm.addEventListener('submit'function() {
        var msg = $('#msg');
 
        if (msg.val() == '') {
            return;
                
        } else {
            socket.emit('SEND', msg.val());
 
            var msgLine = $('<div class="msgLine">');
            var msgBox = $('<div class="msgBox">');
 
            msgBox.append(msg.val());
            msgBox.css('display''inline-block');
 
            msgLine.css('text-align''right');
            msgLine.append(msgBox);
 
            $('#chatView').append(msgLine);
 
            msg.val('');
            chatView.scrollTop = chatView.scrollHeight;
        }
    });
 
    socket.on('SEND'function(msg) {
        var msgLine = $('<div class="msgLine">');
        var msgBox = $('<div class="msgBox">');
                
        msgBox.append(msg);
        msgBox.css('display''inline-block');
 
        msgLine.append(msgBox);
        $('#chatView').append(msgLine);
 
        chatView.scrollTop = chatView.scrollHeight;
    });
</script>
cs

 

 

1. 클라이언트 소켓에서 서버에서 발생시킨 이벤트인 SEND라는 이벤트가 발생하면 어떤 로직을 수행합니다.

 

2. 클라이언트가 자신이 보낸 메세지를 chatView에 보여주는 코드랑 동일하고 text-align 속성만 제외시켜주면 왼쪽에 위치할겁니다.

 

 

 

- 최종 결과

 

 

 

저는 동일한 공유기를 사용하는 친구들을 데리고 테스트를 해봤습니다.

 

혼자서 테스트 하시려면 각각 다른 브라우저 2개로 접속을 해서 해보시면 됩니다.

 

성공적으로 채팅이 이뤄진다면 성공적으로 끝난겁니다.

댓글