[Node JS] 웹 채팅 / socket.io 구현

104108 단어 node jssocket.ionode js

Node JSsocket.io를 이용해 웹 채팅을 구현했다.

Web Chat

기본 작동 방식

  • 클라이언트1이 채팅 내용을 서버로 보낸다.
  • 서버에서 나머지 클라이언트1을 제외한 나머지 클라이언트에 채팅 내용을 보내준다.
  • 반복

server.js

const express = require('express');
const app = express();

const port = 8080;
const server = app.listen(port, function() {
    console.log('Listening on '+port);
});

const SocketIO = require('socket.io');
const io = SocketIO(server, {path: '/socket.io'});

io.on('connection', function (socket) {
    console.log(socket.id, ' connected...');
    
    // broadcasting a entering message to everyone who is in the chatroom
    io.emit('msg', `${socket.id} has entered the chatroom.`);
  
  	// message receives
    socket.on('msg', function (data) {
        console.log(socket.id,': ', data);
        // broadcasting a message to everyone except for the sender
        socket.broadcast.emit('msg', `${socket.id}: ${data}`);
    });

    // user connection lost
    socket.on('disconnect', function (data) {
        io.emit('msg', `${socket.id} has left the chatroom.`);
    });
});

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

chat.html

<script src="/socket.io/socket.io.js"></script>
<h1>Message</h1>

<!-- chat contents will be written down below. -->
<div id="chatContent">
  
</div>
<input id="myChat" type="text">
<input type="submit" id="send" value="Send">

<script>
	var socket = io.connect('http://localhost:8080', {
		path: '/socket.io'
		// transports: ['websocket']
	});

	// receiving a message
	socket.on('msg', function (data) {
		var msgLine = $('<div class="msgLine">');
		var msgBox = $('<div class="msgBox">');
		msgBox.append(data);
        msgBox.css('display', 'inline-block');
        msgLine.append(msgBox);
        $('#chatContent').append(msgLine);
	  	// auto scorll down when a user send something
		chatContent.scrollTop = chatContent.scrollHeight;
	});

	// sending a message
	$("#myChat").on("keyup", function () {
		if (window.event.keyCode==13 && $(this).val()!="") {
			var msgLine = $('<div class="msgLine">');
            var msgBox = $('<div class="msgBox">');
            msgBox.append($(this).val());
            msgBox.css('display', 'inline-block');
            msgLine.css('text-align', 'right');
            msgLine.append(msgBox);
            $('#chatContent').append(msgLine);
            socket.emit('msg', $(this).val());
            $(this).val("");
            chatContent.scrollTop = chatContent.scrollHeight;
        }
	});
</script>
  
<style>
	* {
		box-sizing: border-box;
	}
	.msgLine {
		margin: 15px;
	}
	.msgBox {
		border: 1px solid black;
		background: black;
		padding: 2px 5px;
		border-radius: 10px;
	}
	#chatContent {
		border: 1px solid #000;
		width: 100%;
		height: 200px;
		margin-bottom: 10px;
		overflow-y: auto;
	}
	#myChat {
		width: 100%;
	}
	#msg, #myChat {
		width: 80%;
		height: 32px;
		border-radius: 8px;
	}
	#send {
		width: 16%;
		height: 34px;
		border-radius: 50px;
		background: black;
		color: white;
	}
</style>

http://localhost:8080/chat경로에서 웹 채팅을 구현했다.
아래 사진에 Node JS: Messenger를 누르면 채팅 화면으로 들어간다.

채팅 화면은 아래와 같다.

▼사용 예시▼

Server side

npm을 통해서 socket.io모듈을 설치해준다.

npm install socket.io

그 후 expresssocket.io를 이용해 기본적인 서버를 만들어준다.

const express = require('express');
const app = express();

const port = 8080;
const server = app.listen(port, function() {
    console.log('Listening on '+port);
});

const SocketIO = require('socket.io');
//this path has to same with client side path
const io = SocketIO(server, {path: '/socket.io'});

Things to know

  • Methods

  • io.emit();: 연결되어있는 모든 클라이언트에게 전송한다.
  • socket.broadcast.emit();: 메시지를 전송한 클라이언트를 제외하고 나머지 모든 클라이언트에게 전송한다.
  • socket.emit();: 서버에 메시지를 전송한 클라이언트에게만 전송한다.
  • io.to(id).emit();: 귓속말
  • Event

  • 이벤트라는것이 존재한다.
  • connection, disconnect 처럼 기본 이벤트가 존재한다.
  • msg처럼 개발자가 만든 이벤트도 존재한다.
  • msg이벤트의 경우 이 이벤트가 발생했을 시 해당 이벤트에 속하는 부분들이 실행된다.

서버를 만든 다음 아래의 코드도 추가해준다.
msg이벤트를 사용했음을 확인할 수 있다.
나중에 클라이언트에서도 같은 이름인 msg이벤트를 사용해야한다.

io.on('connection', function (socket) {
    console.log(socket.id, ' connected...');
    
    // broadcasting a entering message to everyone who is in the chatroom
    io.emit('msg', `${socket.id} has entered the chatroom.`);

  	// message receives
    socket.on('msg', function (data) {
        console.log(socket.id,': ', data);
        // broadcasting a message to everyone except for the sender
        socket.broadcast.emit('msg', `${socket.id}: ${data}`);
    });

    // user connection lost
    socket.on('disconnect', function (data) {
        io.emit('msg', `${socket.id} has left the chatroom.`);
    });
});
// - `io.emit(‘event_name’, msg);`: send a message to every connected client
// - `socket.emit(‘event_name’, msg);`: send a message to only who sent the message to server
// - `socket.boradcast.emit(‘event_name’, msg);`: send a message to every client except for who sent the message
// - `io.to(id).emit(‘event_name’, msg);`: send a message to a particular client
console.log(socket.id, ' connected...');

클라이언트가 연결 될때마다 connected...문구가 서버 터미널에 나타난다.

// broadcasting a entering message to everyone who is in the chatroom
io.emit('msg', `${socket.id} has entered the chatroom.`);
  • 클라이언트가 채팅에 접속시 입장 메시지 전송
  • msg이벤트를 사용했음을 확인할 수 있다.
// message receives
socket.on('msg', function (data) {
	console.log(socket.id,': ', data);
	// broadcasting a message to everyone except for the sender
	socket.broadcast.emit('msg', `${socket.id}: ${data}`);
});

서버에서 메시지 수신시 전송한 클라이언트를 제외한 나머지 클라이언트에게 해당 메시지 전달.

// user connection lost
socket.on('disconnect', function (data) {
	io.emit('msg', `${socket.id} has left the chatroom.`);
});

클라이언트 연결 끊겼을때 퇴장 메시지 전송.

Client side

chat.html

<h1>Message</h1>
<!-- chat contents will be written down below. -->
<div id="chatContent">

</div>
<input id="myChat" type="text">
<input type="submit" id="send" value="Send">

위의 코드는 아래와 같이 생겼다.

chat.html내부 JS▼

// importing JS file from socketIO server
<script src="/socket.io/socket.io.js"></script>
<script>
	var socket = io.connect('http://localhost:8080', {
		path: '/socket.io'
		// transports: ['websocket']
	});

	// receiving a message
	socket.on('msg', function (data) {
		var msgLine = $('<div class="msgLine">');
		var msgBox = $('<div class="msgBox">');
		msgBox.append(data);
		msgBox.css('display', 'inline-block');
		msgLine.append(msgBox);
		$('#chatContent').append(msgLine);
		// auto scorll down when a user send something
		chatContent.scrollTop = chatContent.scrollHeight;
	});

	// sending a message
	$("#myChat").on("keyup", function () {
		if (window.event.keyCode==13 && $(this).val()!="") {
			var msgLine = $('<div class="msgLine">');
			var msgBox = $('<div class="msgBox">');
			msgBox.append($(this).val());
			msgBox.css('display', 'inline-block');
			msgLine.css('text-align', 'right');
			msgLine.append(msgBox);
			$('#chatContent').append(msgLine);
			socket.emit('msg', $(this).val());
			$(this).val("");
			chatContent.scrollTop = chatContent.scrollHeight;
		}
	});
</script>
  • 클라이언트에서도 같은 msg이벤트를 사용해 서로 통신하도록 했다.
  • 나중에 더 많은 채팅을 만들때도 다른 이벤트 이름을 사용하면 채팅방 구별이 가능하다.

chat.html내부 CSS▼

<style>
	* {
		box-sizing: border-box;
	}
	.msgLine {
		margin: 15px;
	}
	.msgBox {
		border: 1px solid black;
		background: black;
		padding: 2px 5px;
		border-radius: 10px;
	}
	#chatContent {
		border: 1px solid #000;
		width: 100%;
		height: 200px;
		margin-bottom: 10px;
		overflow-y: auto;
	}
	#myChat {
		width: 100%;
	}
	#msg, #myChat {
		width: 80%;
		height: 32px;
		border-radius: 8px;
	}
	#send {
		width: 16%;
		height: 34px;
		border-radius: 50px;
		background: black;
		color: white;
	}
</style>
  • socket.io모듈은 /socket.io경로에 /socket.io.js파일을 포함하고있다.
  • 브라우저에 http://localhost:8080/socket.io/socket.io.js를 타고 들어가면 아래처럼 함수를 확인할 수 있다.
<script src="/socket.io/socket.io.js"></script>
var socket = io.connect('http://localhost:8080', {
  path: '/socket.io'
  // transports: ['websocket']
});
  • 위의 코드는 socket.io가 자동으로 만들어둔 http://localhost:8080/socket.io/socket.io.js에 접근해 자바스크립트를 실행하여 서버와 통신한다.

// receiving a message
socket.on('msg', function (data) {
	var msgLine = $('<div class="msgLine">');
	var msgBox = $('<div class="msgBox">');
	msgBox.append(data);
	msgBox.css('display', 'inline-block');
	msgLine.append(msgBox);
	('#chatContent').append(msgLine);
	// auto scorll down when a user send something
	chatContent.scrollTop = chatContent.scrollHeight;
});
  • 서버에서 msg이벤트를 사용해 전송을 했을때 클라이언트에서 위의 코드로 수신할수 있다.
  • data변수를 사용해 메시지에 접근 가능하고, 웹상에 나타나도록 해주었다.
  • 마지막부분은 채팅이 누적되었을 경우 자동으로 스크롤 다운 되게 해주었다.
// sending a message
$("#myChat").on("keyup", function () {
  if (window.event.keyCode==13 && $(this).val()!="") {
    var msgLine = $('<div class="msgLine">');
    var msgBox = $('<div class="msgBox">');
    msgBox.append($(this).val());
    msgBox.css('display', 'inline-block');
    msgLine.css('text-align', 'right');
    msgLine.append(msgBox);
    $('#chatContent').append(msgLine);
    socket.emit('msg', $(this).val());
    $(this).val("");
    chatContent.scrollTop = chatContent.scrollHeight;
  }
});
  • 클라이언트에서 msg이벤트로 서버에 전달하는 방법이다.
  • 텍스트 박스가 비어있지 않고 엔터가 눌릴때마다 실행된다.
  • 마찬가지로 채팅이 누적되었을 경우를 대비해 자동으로 스크롤 다운이 되도록 해주었다.

FYI

io.on('connection', function (socket) {
    console.log(socket.id, ' connected...');
    
    // broadcasting a entering message to everyone who is in the chatroom
    io.emit('msg', `${socket.id} has entered the chatroom.`);
    // message receives
    socket.on('msg', function (data) {
        console.log(socket.id,': ', data);
        // broadcasting a message to everyone except for the sender
        socket.broadcast.emit('msg', `${socket.id}: ${data}`);
    });
    // user connection lost
    socket.on('disconnect', function (data) {
        io.emit('msg', `${socket.id} has left the chatroom.`);
    });

    // broadcasting a entering message to everyone who is in the chatroom
    io.emit('msg2', `${socket.id} has entered the chatroom.`);
    // message receives
    socket.on('msg2', function (data) {
        console.log(socket.id,': ', data);
        // broadcasting a message to everyone except for the sender
        socket.broadcast.emit('msg2', `${socket.id}: ${data}`);
    });
    // user connection lost
    socket.on('disconnect', function (data) {
        io.emit('msg2', `${socket.id} has left the chatroom.`);
    });
});
<!-- importing JS file from socketIO server -->
<script src="/socket.io/socket.io.js"></script>
<h1>Message</h1>
<!-- chat contents will be written down below. -->
<div id="chatContent">
                        
</div>
<input id="myChat" type="text">
<input type="submit" id="send" value="Send">

<h1>Message2</h1>
<!-- chat contents will be written down below. -->
<div id="chatContent2">
                        
</div>
<input id="myChat2" type="text">
<input type="submit" id="send2" value="Send">

<script>
	var socket = io.connect('http://localhost:8080', {
		path: '/socket.io'
		// transports: ['websocket']
	});

	// receiving a message
	socket.on('msg', function (data) {
	// socket.on('msg', function (data) {
		var msgLine = $('<div class="msgLine">');
		var msgBox = $('<div class="msgBox">');
		msgBox.append(data);
		msgBox.css('display', 'inline-block');
		msgLine.append(msgBox);
		$('#chatContent').append(msgLine);
		// auto scorll down when a user send something
		chatContent.scrollTop = chatContent.scrollHeight;
	});

	// sending a message
	$("#myChat").on("keyup", function () {
		if (window.event.keyCode==13 && $(this).val()!="") {
			var msgLine = $('<div class="msgLine">');
			var msgBox = $('<div class="msgBox">');
			msgBox.append($(this).val());
			msgBox.css('display', 'inline-block');
			msgLine.css('text-align', 'right');
			msgLine.append(msgBox);
			$('#chatContent').append(msgLine);
			socket.emit('msg', $(this).val());
			$(this).val("");
			chatContent.scrollTop = chatContent.scrollHeight;
		}
	});


	// receiving a message
	socket.on('msg2', function (data) {
		var msgLine = $('<div class="msgLine">');
		var msgBox = $('<div class="msgBox">');
		msgBox.append(data);
		msgBox.css('display', 'inline-block');
		msgLine.append(msgBox);
		$('#chatContent2').append(msgLine);
		// auto scorll down when a user send something
		chatContent2.scrollTop = chatContent2.scrollHeight;
	});

	// sending a message
	$("#myChat2").on("keyup", function () {
		if (window.event.keyCode==13 && $(this).val()!="") {
			var msgLine = $('<div class="msgLine">');
			var msgBox = $('<div class="msgBox">');
			msgBox.append($(this).val());
			msgBox.css('display', 'inline-block');
			msgLine.css('text-align', 'right');
			msgLine.append(msgBox);
			$('#chatContent2').append(msgLine);
			socket.emit('msg2', $(this).val());
			$(this).val("");
			chatContent2.scrollTop = chatContent2.scrollHeight;
		}
	});
</script>
<style>
	* {
		box-sizing: border-box;
	}
	.msgLine {
		margin: 15px;
	}
	.msgBox {
		border: 1px solid black;
		background: black;
		padding: 2px 5px;
		border-radius: 10px;
	}
	#chatContent {
		border: 1px solid #000;
		width: 100%;
		height: 200px;
		margin-bottom: 10px;
		overflow-y: auto;
	}
	#myChat {
		width: 100%;
	}
	#msg, #myChat {
		width: 80%;
		height: 32px;
		border-radius: 8px;
	}
	#send {
		width: 16%;
		height: 34px;
		border-radius: 50px;
		background: black;
		color: white;
	}


	.msgLine2 {
		margin: 15px;
	}
	.msgBox2 {
		border: 1px solid black;
		background: black;
		padding: 2px 5px;
		border-radius: 10px;
	}
	#chatContent2 {
		border: 1px solid #000;
		width: 100%;
		height: 200px;
		margin-bottom: 10px;
		overflow-y: auto;
	}
	#myChat2 {
		width: 100%;
	}
	#msg2, #myChat2 {
		width: 80%;
		height: 32px;
		border-radius: 8px;
	}
	#send2 {
		width: 16%;
		height: 34px;
		border-radius: 50px;
		background: black;
		color: white;
	}
</style>
  • 위의 코드처럼 이벤트 두개를 사용하면 아래와 같은 사진처럼 채팅방을 여러개 만들수 있다.

좋은 웹페이지 즐겨찾기