Socket.io 채팅 애플리케이션 (6) - 채팅 기능 구현 (채팅방에 들어가보자 - 클라이언트)
지난 시간에
지난 시간에는 채팅방에 들어가는 기능중에서 서버측 코드를 작성해 보았다.
이번 차시에서는 클라이언트 측에서 채팅방에 들어가보자.
클라이언트측 구현
지난 시간에 채팅방에 들어가는 플로우를 기억해보자.
- (c) 채팅방 목록중에 아무거나 클릭하면
join room
이벤트 발생 - (s)
join room
이벤트 발생시 기존에 있던 방에서 나가고 새로운 방에 입장socket.join()
- (s) 이제 방에 새로운 멤버가 들어왔으니 member list 업데이트 이벤트 발생
userlist
- (c)
userlist
이벤트 발생시memberWrap
에 있는 데이터를 서버한테 받은 데이터로 갱신 - (s) 유저가
disconnect
할때나 로그아웃할 때도userlist
update 이벤트 발생 - (c) 유저가 들어오거나 떠날 때 공지해주기
이중 클라이언트 측 구현은 1, 4, 6번 이였다.
1. (c) 채팅방 목록중에 아무거나 클릭하면 join room
이벤트 발생
# /public/js/script.js
$(function () {
var socket = io.connect();
var $userWrap = $('#userWrap');
var $contentWrap = $('#contentWrap');
var $loginForm = $('#loginForm');
var $joinForm = $('#joinForm');
var $chatForm = $('#chatForm');
var $roomSelect = $('#roomSelect');
var $memberSelect = $('#memberSelect');
var $chatLog = $('#chatLog');
var roomId = 1;
var socketId = "";
----------
if (res.result) {
alert(res.data);
socketId = socket.id;
roomId = 1;
id.val("");
pw.val("");
$userWrap.hide();
$contentWrap.show();
$chatLog.html(""); //<-- add
$('#chatHeader').html("Everyone"); //<-- add
}
----------
$roomSelect.on("click", "div", function () {
if (roomId !== $(this).data('id')) {
roomId = $(this).data('id');
}
$(this).parents().children().removeClass("active");
$(this).addClass("active");
$chatLog.html(""); // 채팅 기록을 지우는 코드
$('#chatHeader').html(`${$(this).html()}`);
socket.emit('join room', {
roomId
});
});
})
추가 시켜야 할 코드가 많으니 잘 따라오길 바란다.
일단 맨 위의 코드들은 코드의 가시성을 위해서 jQuery selector
들을 변수에 담아 놓은 것이다.
두번째 단락의 코드는 login
을 submit
하는 코드에 추가 시키는 것인데 default
로 접속되는 방인 EveryOne
으로 채팅창의 header
를 변경하고 채팅 기록을 지우는 코드이다.
세번째 단락의 코드는 logoutBtn
클릭이벤트 뒤에 작성한 코드로 (실제로 위치는 상관없음) roomEl
을 클릭했을때 해당 방의 목록의 엘리먼트에 active
클래스를 추가시켜주고, #chatHeader
의 내용을 클릭한 방의 이름으로 바꿔주고, 마지막으로 방을 들어갔다는 join room
이벤트를 서버에게 보내는 코드이다.
4. (c) userlist
이벤트 발생시 memberWrap
에 있는 데이터를 서버한테 받은 데이터로 갱신
# /public/js/script.js
----------
socket.on('userlist', function (data) {
let html = "";
data.forEach((el) => {
if (el.socketId === socketId) {
html += `<div class="memberEl">${el.name} (me)</div>`
} else {
html += `<div class="memberEl">${el.name}</div>`
}
});
$memberSelect.html(html);
});
서버로 부터 받은 userlist
정보를 $memberSelect
의 엘리먼트에 넣는 작업이다. 그리고 만약 자신의 socketId
와 동일하다면 <div class="memberEl">${el.name} (me)</div>
를 추가시켜 사용자가 자신인지 판별한다.
6. (c) 유저가 들어오거나 떠날 때 공지해주기
# /public/js/script/js
----------
socket.on('lefted room', function (data) {
$chatLog.append(`<div class="notice"><strong>${data}</strong> lefted the room</div>`)
});
socket.on('joined room', function (data) {
$chatLog.append(`<div class="notice"><strong>${data}</strong> joined the room</div>`)
});
유저가 채팅방에 들어오거나 나갔을 때 공지해주는 코드이다. 이 마크업에 스타일을 조금 입혀주자.
# /public/css/style.css
.notice {
text-align: center;
color: gray;
font-size: 13px;
}
이제 우리가 해야할 일은 테스트이다. 기존에 작성했던 테스트 코드를 지워보자.
# /chat.html
----------
<div id="chatLog">
<div class="anotherMsg"> // 삭제
<span class="anotherName">Jo</span> // 삭제
<span class="msg">Hello, Nice to meet you.</span> // 삭제
</div> // 삭제
<div class="myMsg"> // 삭제
<span class="msg">Nice to meet you, too.</span> // 삭제
</div> // 삭제
</div>
----------
<div id="memberSelect">
<div class="memberEl">test</div> // 삭제
<div class="memberEl">test1</div> // 삭제
<div class="memberEl">test2</div> // 삭제
<div class="memberEl">test3</div> // 삭제
</div>
그다음 테스트 계정으로 로그인 해보자
자신의 계정 옆에 (me)
라는 단어가 나온다면 잘한 것이다.
그다음 브라우저 새 탭을 열어 다른 계정을 만들어 로그인해보자.
그러면 두개의 계정이 Everyone
채팅방에 있는 것을 확인할 수 있다.
방을 옮기면 옮긴대로 사용자가 이동하고 다른 사용자의 userlist는 업데이트 된다.
그리고 로그아웃 버튼을 눌렀을때 성공적으로 로그아웃 되는 것을 확인할 수 있다.
이번에 작성한 전체 코드
# /public/js/script.js
$(function () {
var socket = io.connect();
var $userWrap = $('#userWrap');
var $contentWrap = $('#contentWrap');
var $loginForm = $('#loginForm');
var $joinForm = $('#joinForm');
var $chatForm = $('#chatForm');
var $roomSelect = $('#roomSelect');
var $memberSelect = $('#memberSelect');
var $chatLog = $('#chatLog');
var roomId = 1;
var socketId = "";
$("#loginBtn").click(function (e) {
e.preventDefault();
$loginForm.show();
$joinForm.hide();
});
$("#joinBtn").click(function (e) {
e.preventDefault();
$joinForm.show();
$loginForm.hide();
});
$("#logoutBtn").click(function (e) {
e.preventDefault();
socket.emit('logout');
socketId = "";
alert("로그아웃되었습니다.");
$userWrap.show();
$contentWrap.hide();
});
$roomSelect.on("click", "div", function () {
if (roomId !== $(this).data('id')) {
roomId = $(this).data('id');
}
$(this).parents().children().removeClass("active");
$(this).addClass("active");
$chatLog.html("");
$('#chatHeader').html(`${$(this).html()}`);
socket.emit('join room', {
roomId
});
});
socket.on('userlist', function (data) {
let html = "";
data.forEach((el) => {
if (el.socketId === socketId) {
html += `<div class="memberEl">${el.name} (me)</div>`
} else {
html += `<div class="memberEl">${el.name}</div>`
}
});
$memberSelect.html(html);
});
socket.on('lefted room', function (data) {
$chatLog.append(`<div class="notice"><strong>${data}</strong> lefted the room</div>`)
});
socket.on('joined room', function (data) {
$chatLog.append(`<div class="notice"><strong>${data}</strong> joined the room</div>`)
});
$loginForm.submit(function (e) {
e.preventDefault();
let id = $("#loginId");
let pw = $("#loginPw");
if (id.val() === "" || pw.val() === "") {
alert("check validation");
return false;
} else {
socket.emit('login user', {
id: id.val(),
pw: pw.val()
}, function (res) {
if (res.result) {
alert(res.data);
socketId = socket.id;
roomId = 1;
id.val("");
pw.val("");
$userWrap.hide();
$contentWrap.show();
$('#chatHeader').html("Everyone");
} else {
alert(res.data);
id.val("");
pw.val("");
$("#joinBtn").click();
}
});
}
});
$joinForm.submit(function (e) {
e.preventDefault();
let id = $("#joinId");
let pw = $("#joinPw");
if (id.val() === "" || pw.val() === "") {
alert("check validation");
return false;
} else {
socket.emit('join user', {
id: id.val(),
pw: pw.val()
}, function (res) {
if (res.result) {
alert(res.data);
id.val("");
pw.val("");
$("#loginBtn").click();
} else {
alert(res.data);
return false;
}
});
}
});
});
지난 번에 말했듯이 위에 코드를 이해 했으면 그냥 복붙해도 상관없다.
다음 시간에
이제 거의 다 끝났다. 다음시간에는 대망의 채팅을 구현할 것이다. 이번에 한 채팅방보다 구현이 쉽고 간단하다.
'Side Project' 카테고리의 다른 글
[PROJECT] Socket.io 를 이용한 채팅 애플리케이션 (8) - 채팅 기능 구현 (들어갔으니 채팅을 치자 - 클라이언트) (1) | 2018.09.28 |
---|---|
[PROJECT] Socket.io 를 이용한 채팅 애플리케이션 (7) - 채팅 기능 구현 (들어갔으니 채팅을 치자 - 서버) (0) | 2018.09.28 |
[PROJECT] Socket.io 를 이용한 채팅 애플리케이션 (5) - 채팅 기능 구현 (채팅방에 들어가보자 - 서버) (0) | 2018.09.28 |
[PROJECT] Socket.io 를 이용한 채팅 애플리케이션 (4) - 채팅 창 웹 디자인 (0) | 2018.09.27 |
[PROJECT] Socket.io 를 이용한 채팅 애플리케이션 (3) - 회원관리 기능 구현 (0) | 2018.09.27 |