Presentation is loading. Please wait.

Presentation is loading. Please wait.

채팅 서버 만들기 10장 Do it! Node.js 프로그래밍 이지스퍼블리싱 제공 강의 교안 2017/03

Similar presentations


Presentation on theme: "채팅 서버 만들기 10장 Do it! Node.js 프로그래밍 이지스퍼블리싱 제공 강의 교안 2017/03"— Presentation transcript:

1 채팅 서버 만들기 10장 Do it! Node.js 프로그래밍 이지스퍼블리싱 제공 강의 교안 2017/03
○ 본 강의 자료는 이지스퍼블리싱에서 제공하는 강의 교안입니다. ○ 본 강의 교안은 아래 출판 서적의 내용을 기준으로 구성되었습니다. 또한 다수의 기타 서적이나 사이트를 참조하였습니다. 레퍼런스를 참조하십시오. 2017, 정재곤, “Do it! Node.js 프로그래밍 (개정판)”, 이지스퍼블리싱 - 강의 교안에 사용된 화면 캡처나 실습 자료의 경우에는 문서 업데이트에 따라 변경될 수 있습니다.

2 강의 주제 및 목차 채팅 서버를 어떻게 만드는지 알아보자 강의 주제 목 차 Socket.IO 사용하기 일대일 채팅하기
목 차 1 Socket.IO 사용하기 2 일대일 채팅하기 3 그룹 채팅하기 4 채팅 웹문서 예쁘게 꾸미기

3 1. Socket.IO 사용하기 난이도 소요시간 30분

4 Socket.IO 모듈의 사용 메시지를 실시간으로 주고받을 수 있도록 만든 WebSocket 표준 프로토콜을 구현한 것
CORS도 사용해야 함 % npm install socket.io –save % npm install cors --save

5 메인 파일에서 모듈 사용하도록 수정 socket.io와 cors 모듈 사용하도록 수정 // socket.io 모듈 불러들이기
var socketio = require('socket.io'); // cors 사용 - 클라이언트에서 ajax로 요청하면 CORS 지원 var cors = require('cors'); ……. // cors를 미들웨어로 사용하도록 등록 app.use(cors());

6 서버 위에서 socket.io 사용 서버 시작 후 socket.io 로 처리하도록 listen() 메소드 호출
// 시작된 서버 객체를 반환받습니다. var server = http.createServer(app).listen(app.get('port'), function() { console.log('서버가 시작되었습니다. 포트 : ' + app.get('port')); database.init(app, config); }); // socket.io 서버를 시작합니다. var io = socketio.listen(server); console.log('socket.io 요청을 받아들일 준비가 되었습니다.');

7 socket.io로 대기하는 방식 listen() 메소드를 이용해 대기 메소드 이름 설명
attach(httpServer, options) 웹 서버 인스턴스가 socket.io를 처리합니다. listen(httpServer, options) 위의 attach( ) 메소드와 같은 기능입니다.

8 서버 동작 방식 서버 실행하여 로그가 정상적으로 출력되는지 확인

9 클라이언트 연결 시 이벤트 처리 connection 이벤트를 이용해 클라이언트 연결했을 때 처리 …….
// 클라이언트가 연결했을 때의 이벤트 처리 io.sockets.on('connection', function(socket) { console.log('connection info : ', socket.request.connection._peername); // 소켓 객체에 클라이언트 Host, Port 정보 속성으로 추가 socket.remoteAddress = socket.request.connection._peername.address; socket.remotePort = socket.request.connection._peername.port; });

10 웹 문서 만들기 웹 브라우저에서 사용자가 볼 웹 문서 작성 <body>
<h3>채팅 클라이언트 01</h3> <br> <div> <input type = "text" id = "hostInput" value = "localhost"/> <input type = "text" id = "portInput" value = "3000"/> <input type = "button" id = "connectButton" value = "연결하기"/> </div> <hr/> <p>결과 : </p> <div id = "result"></div> </body>

11 웹 문서의 자바스크립트 코드 작성 socket.io 라이브러리를 사용하는 코드 작성
<script src = "jquery min.js"></script> <script src = "socket.io.js"></script> ……. <script> var host; var port; var socket; // 문서 로딩 후 실행됨 $(function() { $("#connectButton").bind('click', function(event) { println('connectButton이 클릭되었습니다.'); host = $('#hostInput').val(); port = $('#portInput').val(); connectToServer(); });

12 웹 문서의 자바스크립트 코드 작성 socket.io 라이브러리를 사용하는 코드 작성 // 서버에 연결하는 함수 정의
function connectToServer() { var options = {'forceNew' : true}; var url = 'http : //' + host + ' : ' + port; socket = io.connect(url, options); socket.on('connect', function() { println('웹 소켓 서버에 연결되었습니다. : ' + url); }); socket.on('disconnect', function() { println('웹 소켓 연결이 종료되었습니다.'); } function println(data) { console.log(data); $('#result').append('<p>' + data + '</p>'); </script>

13 웹문서에서 요청하여 서버 로그 확인 웹페이지에서 요청 후 콘솔 확인

14 socket.io 접속 과정 클라이언트에서 서버에 접속하는 과정 정리

15 서버에서 보낸 메시지 받기 emit() 으로 보내고 on() 으로 받음 …….
송수신 이벤트 처리 메소드 설명 on(event, callback) 이벤트 수신 형태로 메시지를 수신했을 때 처리할 콜백 함수를 등록합니다. 콜백 함수의 파라미터로 수신한 객체가 전달됩니다. emit(event, object) 이벤트 송신 형태로 메시지를 송신합니다. ……. socket.on('connect', function() { println('웹 소켓 서버에 연결되었습니다. : ' + url); socket.on('message', function(message) { console.log(JSON.stringify(message)); println('<p>수신 메시지 : ' + message.sender + ', ' + message.recepient + ', ' + message.command + ', ' + message.type + ‘, ’ + message.data + '</p>'); });

16 보내고 받을 데이터 정의 메시지로 보낼 데이터의 형식 정의

17 웹페이지 작성 chat02.html 파일에서 보내는 사람, 받는 사람, 데이터를 입력할 수 있도록 작성 <div>
<span>보내는 사람 아이디 : </span> <input type="text" id="senderInput" value="test01"/> </div> <span>받는 사람 아이디 : </span> <input type="text" id="recepientInput" value="ALL"/> <span>메시지 데이터 : </span> <input type="text" id="dataInput" value="안녕!"/> <br> <input type="button" id="sendButton" value="전송"/> …….

18 웹페이지의 자바스크립트 코드 작성 버튼 클릭 시 emit() 메소드를 이용해 메시지 전송 // 전송 버튼을 클릭하면 처리
$("#sendButton").bind('click', function(event) { var sender = $('#senderInput').val(); var recepient = $('#recepientInput').val(); var data = $('#dataInput').val(); var output = {sender : sender, recepient : recepient, command : 'chat', type : 'text', data : data}; console.log('서버로 보낼 데이터 : ' + JSON.stringify(output)); if(socket == undefined) { alert('서버에 연결되어 있지 않습니다. 먼저 서버에 연결하세요.'); return; } socket.emit('message', output); });

19 서버쪽에서 메시지 받아 처리하는 코드 추가 on() 메소드를 이용해 이벤트를 받아 처리하도록 코드 추가
// 클라이언트가 연결했을 때의 이벤트 처리 io.sockets.on('connection', function(socket) { ……. // 'message' 이벤트를 받았을 때의 처리 socket.on('message', function(message) { console.log('message 이벤트를 받았습니다.'); console.dir(message); if(message.recepient =='ALL') { // 나를 포함한 모든 클라이언트에게 메시지 전달 console.dir('나를 포함한 모든 클라이언트에게 message 이벤트를 전송합니다.') io.sockets.emit('message', message); } });

20 메시지 전송 여부 확인 두 개의 웹페이지를 열고 한 쪽에서 전송하면 모두가 메시지를 받음

21 서버에서 클라이언트들에게 메시지 전송 방법 모두에게 보내거나 나를 제외한 모든 클라이언트에게 보낼 수 있음 메소드 이름 설명
io.sockets.emit(event, object) 나를 포함한 모든 클라이언트에 전송합니다. socket.broadcast.emit(event, object) 나를 제외한 모든 클라이언트에 전송합니다.

22 2. 일대일 채팅하기 난이도 소요시간 30분

23 웹페이지 작성 chat03.html 파일에 일대일 채팅을 위한 태그 추가 <div>
<input type = "text" id = "idInput" value = "test01"/> <input type = "password" id = "passwordInput" value = "123456"/> <input type = "text" id = "aliasInput" value = "소녀시대"/> <input type = "text" id = "todayInput" value = "좋은 날!"/> <input type = "button" id = "loginButton" value = "로그인"/> <input type = "button" id = "logoutButton" value = "로그아웃"/> </div> …….

24 로그인 버튼 클릭 시의 자바스크립트 코드 작성 로그인 버튼을 클릭하면 서버로 로그인 데이터를 보내도록 코드 작성
// 로그인 버튼을 클릭하면 처리 $("#loginButton").bind('click', function(event) { var id = $('#idInput').val(); var password = $('#passwordInput').val(); var alias = $('#aliasInput').val(); var today = $('#todayInput').val(); var output = {id : id, password : password, alias : alias, today : today}; console.log('서버로 보낼 데이터 : ' + JSON.stringify(output)); if(socket == undefined) { alert('서버에 연결되어 있지 않습니다. 먼저 서버에 연결하세요.'); return; } socket.emit('login', output); }); …….

25 로그인을 위해 전송하는 데이터 형식 id, password, alias, today 데이터 전송

26 서버 쪽에 로그인 처리를 위한 코드 추가 login 이벤트가 전달되면 로그인 정보를 객체에 추가
// 로그인 아이디 매핑 (로그인 ID -> 소켓 ID) var login_ids = {}; ……. // 'login' 이벤트를 받았을 때의 처리 socket.on('login', function(login) { console.log('login 이벤트를 받았습니다.'); console.dir(login); // 기존 클라이언트 ID가 없으면 클라이언트 ID를 맵에 추가 console.log('접속한 소켓의 ID : ' + socket.id); login_ids[login.id] = socket.id; socket.login_id = login.id; console.log('접속한 클라이언트 ID 개수 : %d', Object.keys(login_ids).length); // 응답 메시지 전송 sendResponse(socket, 'login', '200', '로그인되었습니다.'); });

27 응답을 보내는 함수 sendResponse 함수 정의 ……. // 응답 메시지 전송 메소드
function sendResponse(socket, command, code, message) { var statusObj = {command : command, code : code, message : message}; socket.emit('response', statusObj); }

28 메시지 이벤트를 받았을 때의 처리 message 이벤트를 받았을 때 일대일 채팅인 경우 상대방 소켓을 찾아 메시지 전송
socket.on('message', function(message) { console.log('message 이벤트를 받았습니다.'); console.dir(message); if(message.recepient =='ALL') { console.dir('나를 포함한 모든 클라이언트에 message 이벤트를 전송합니다.') io.sockets.emit('message', message); } else { if(login_ids[message.recepient]) { io.sockets.connected[login_ids[message.recepient]].emit('message', message); sendResponse(socket, 'message', '200', '메시지를 전송했습니다.'); sendResponse(socket, 'login', '404', '상대방의 로그인 ID를 찾을 수 없습니다.'); } });

29 대상 소켓 객체를 찾는 방법 login_ids 변수에 들어있는 값을 확인
io.sockets.connected[login_ids[message.recepient]]

30 일대일 채팅 기능 확인하기 두 개의 웹브라우저를 열고 일대일 채팅 기능 확인

31 3. 그룹 채팅하기 난이도 소요시간 30분

32 웹페이지 작성 chat04.html 파일에 그룹 채팅을 위한 태그 추가 <div>
<input type = "text" id = "roomIdInput" value = "meeting01"/> <input type = "text" id = "roomNameInput" value = "청춘들의 대화"/> <input type = "button" id = "createRoomButton" value = "방 만들기"/> <input type = "button" id = "updateRoomButton" value = "방 이름 바꾸기"/> <input type = "button" id = "deleteRoomButton" value = "방 없애기"/> </div> <br> <div id = "roomList"> …….

33 방 만들기 코드 추가 방 만들기 버튼을 클릭했을 때 방 만들도록 자바스크립트 코드 추가 // 방 만들기 버튼을 클릭하면 처리
$("#createRoomButton").bind('click', function(event) { var roomId = $('#roomIdInput').val(); var roomName = $('#roomNameInput').val(); var id = $('#idInput').val(); var output = {command : 'create', roomId : roomId, roomName : roomName, roomOwner : id}; console.log('서버로 보낼 데이터 : ' + JSON.stringify(output)); if(socket == undefined) { alert('서버에 연결되어 있지 않습니다. 먼저 서버에 연결하세요.'); return; } socket.emit('room', output); }); …….

34 방 만들기를 위해 전송하는 메시지 형식 방 만들기를 위해 roomId, roomName, roomOwner, command 등 전송

35 방 이름 바꾸기와 방 없애기 코드 추가 방 만들기와 유사한 방식으로 메시지 전송하도록 코드 추가
// 방 없애기 버튼을 클릭하면 처리 $("#deleteRoomButton").bind('click', function(event) { var roomId = $('#roomIdInput').val(); var output = {command : 'delete', roomId : roomId}; console.log('서버로 보낼 데이터 : ' + JSON.stringify(output)); if(socket == undefined) { alert('서버에 연결되어 있지 않습니다. 먼저 서버에 연결하세요.'); return; } socket.emit('room', output); }); …….

36 방 정보를 받았을 때 처리하는 코드 추가 방 리스트 등의 정보를 받았을 때 처리하는 코드 추가
// 그룹 채팅에서 방과 관련된 이벤트 처리 socket.on('room', function(data) { console.log(JSON.stringify(data)); println('<p>방 이벤트 : ' + data.command + '</p>'); println('<p>방 리스트를 받았습니다.</p>'); if(data.command == 'list') {// 방 리스트 var roomCount = data.rooms.length; $("#roomList").html('<p>방 리스트 ' + roomCount + '개</p>'); for (var i = 0; i < roomCount; i++) { $("#roomList").append('<p>방 #' + i + ' : ' + data.rooms[i].id + ', ' + data.rooms[i].name + ', ' + data.rooms[i].owner + '</p>'); } }); …….

37 방 관련 이벤트 처리 방식 방 만들기, 방 이름 바꾸기, 방 없애기, 방 리스트 출력 등의 기능을 이벤트로 받아 처리

38 방 만들기 서버 코드 추가 방 만들기를 위한 메시지를 받았을 때 처리하는 코드 추가 // room 이벤트를 받았을 때의 처리
socket.on('room', function(room) { console.log('room 이벤트를 받았습니다.'); console.dir(room); if(room.command === 'create') { if(io.sockets.adapter.rooms[room.roomId]) { // 방이 이미 만들어져 있는 경우 console.log('방이 이미 만들어져 있습니다.'); } else { console.log('방을 새로 만듭니다.'); socket.join(room.roomId); var curRoom = io.sockets.adapter.rooms[room.roomId]; curRoom.id = room.roomId; curRoom.name = room.roomName; curRoom.owner = room.roomOwner; }

39 방 입장, 방 나가기 메소드 방에 입장할 때 join(), 방 나갈 때 leave() 메소드 사용 메소드 이름 설명
join(roomName) 방에 입장합니다. 방이 없으면 방을 새로 만듭니다. leave(roomName) 방에서 나옵니다.

40 방 이름 바꾸기와 방 없애기 코드 추가 방 이름 바꾸기와 방 없애기를 위한 메시지를 받았을 때 처리하는 코드 추가
} else if(room.command === 'update') { var curRoom = io.sockets.adapter.rooms[room.roomId]; curRoom.id = room.roomId; curRoom.name = room.roomName; curRoom.owner = room.roomOwner; } else if(room.command === 'delete') { socket.leave(room.roomId); if(io.sockets.adapter.rooms[room.roomId]) { // 방이 만들어져 있는 경우 delete io.sockets.adapter.rooms[room.roomId]; } else { // 방이 만들어져 있지 않은 경우 console.log('방이 만들어져 있지 않습니다.'); }

41 방 정보 출력 시 방 정보를 출력해보면 방의 ID와 속성들이 들어있음

42 방 리스트를 배열에 담아 반환 만들어진 방의 리스트를 배열에 담아 반환하도록 코드 작성
function getRoomList() { console.dir(io.sockets.adapter.rooms); var roomList = [ ]; Object.keys(io.sockets.adapter.rooms).forEach(function(roomId) { // 각각의 방에 대해 처리 console.log('current room id : ' + roomId); var outRoom = io.sockets.adapter.rooms[roomId]; var foundDefault = false; var index = 0; Object.keys(outRoom).forEach(function(key) { console.log('#' + index + ' : ' + key + ', ' + outRoom[key]); if(roomId == key) { // default room foundDefault = true; console.log('this is default room.'); }

43 방 만들기 기능 확인 두 개의 브라우저를 열고 방을 만들었을 때의 출력 결과 확인

44 그룹 채팅에서 메시지를 보내기 위한 웹페이지 작성
그룹 채팅 메시지 전송을 위한 웹페이지 작성 <div> <input type = "button" id = "joinRoomButton" value = "방 입장하기"/> <input type = "button" id = "leaveRoomButton" value = "방 나가기"/> </div> <br> <span>보내는 사람 아이디 : </span> <input type = "text" id = "senderInput" value = "test01"/> <span>받는 사람 아이디 : </span> <input type = "text" id = "recepientInput" value = "ALL"/> <select name = "chattype" id = "chattype"> <option value = "chat">채팅</option> <option value = "groupchat" selected>그룹 채팅</option> </select>

45 방 입장하기와 방 나가기 코드 추가 방 입장하기, 방 나가기 버튼 클릭 시의 코드 추가
$("#joinRoomButton").bind('click', function(event) { var roomId = $('#roomIdInput').val(); var output = {command : 'join', roomId : roomId}; console.log('서버로 보낼 데이터 : ' + JSON.stringify(output)); if(socket == undefined) { alert('서버에 연결되어 있지 않습니다. 먼저 서버에 연결하세요.'); return; } socket.emit('room', output); });

46 방 입장하기와 방 나가기 코드 추가 방 입장하기, 방 나가기 버튼 클릭 시의 코드 추가 // 방 나가기 버튼을 클릭하면 처리
$("#leaveRoomButton").bind('click', function(event) { var roomId = $('#roomIdInput').val(); var output = {command : 'leave', roomId : roomId}; console.log('서버로 보낼 데이터 : ' + JSON.stringify(output)); if(socket == undefined) { alert('서버에 연결되어 있지 않습니다. 먼저 서버에 연결하세요.'); return; } socket.emit('room', output); });

47 전송 버튼 클릭 시 데이터 전송 전송 버튼 클릭 시 데이터 전송하는 코드 추가
$("#sendButton").bind('click', function(event) { // chattype 구별 var chattype = $('#chattype option : selected').val(); var sender = $('#senderInput').val(); var recepient = $('#recepientInput').val(); var data = $('#dataInput').val(); var output = {sender : sender, recepient : recepient, command : chattype, type : 'text', data : data}; console.log('서버로 보낼 데이터 : ' + JSON.stringify(output)); if(socket == undefined) { alert('서버에 연결되어 있지 않습니다. 먼저 서버에 연결하세요.'); return; } socket.emit('message', output); });

48 메시지 전송 방식 일대일 채팅과 그룹 채팅의 메시지 전송 방식

49 방 입장하기와 방 나가기 서버 코드 추가 방 입장하기는 join, 방 나가기는 leave 일 때 처리 …….
} else if(room.command === 'join') { // 방에 입장하기 요청 socket.join(room.roomId); // 응답 메시지 전송 sendResponse(socket, 'room', '200', '방에 입장했습니다.'); } else if(room.command === 'leave') { // 방 나가기 요청 socket.leave(room.roomId); sendResponse(socket, 'room', '200', '방에서 나갔습니다.'); }

50 메시지 이벤트를 받았을 때의 처리 메시지의 command가 chat일 때와 groupchat일 때를 구분하여 처리
if(message.command == 'chat') { // 일대일 채팅 대상에게 메시지 전달 if(login_ids[message.recepient]) { io.sockets.connected[login_ids[message.recepient]].emit('message', message); sendResponse(socket, 'message', '200', '메시지를 전송했습니다.'); } else { sendResponse(socket, 'login', '404', '상대방의 로그인 ID를 찾을 수 없습니다.'); } } else if(message.command == 'groupchat') { io.sockets.in(message.recepient).emit('message', message); sendResponse(socket, 'message', '200', '방 [' + message.recepient + ']의 모든 사용자들에게 메시지를 전송했습니다.');

51 그룹 채팅 기능 확인 두 개 또는 세 개의 브라우저를 열고 방에 있는 사람들에게 메시지 전송하는 기능 확인

52 4. 채팅 웹 문서 예쁘게 꾸미기 난이도 소요시간 20분

53 일대일 채팅 웹 문서 꾸미기 Semantic UI 라이브러리를 이용해 일대일 채팅을 위한 웹 문서 꾸미기
<div class = "container"> <div id = "cardbox" class = "ui blue fluid card"> <div class = "content"> <div class = "left floated author"> <img id = "iconImage" class = "ui avatar image" src = "./images/author.png"> </div> <div> <div id = "titleText" class = "header">일대일 채팅</div> <div id = "contentsText" class = "description"> 연결 및 로그인 후 메시지를 보내세요.

54 일대일 채팅 웹 문서 꾸민 후의 화면 Semantic UI 라이브러리를 이용해 일대일 채팅을 위한 웹 문서 수정 후 확인

55 일대일 채팅 웹 문서 꾸미기 일대일 채팅 메시지를 주고받는 부분의 태그와 CSS 속성을 수정하여 웹 문서 꾸미기
<ol class = "discussion"> <li class = "other"> <div class = "avatar"> <img src = "/public/images/user2.png"/> </div> <div class = "messages"> <p>어디쯤이야? 다들 기다리고 있어.</p> <time datetime = " : 10">18시 10분</time> </li> <li class = "self"> <img src = "/public/images/user1.png"/> <p>차가 막히네. 조금 늦을 듯.</p> <time datetime = " : 00">18시 00분</time>

56 일대일 채팅 웹 문서 꾸민 후의 화면 일대일 채팅 부분을 CSS로 꾸민 후의 화면

57 참고 문헌 [ References] 기본 서적
2017, 정재곤, “Do it! Node.js 프로그래밍 (개정판)”, 이지스퍼블리싱 Node.js Site


Download ppt "채팅 서버 만들기 10장 Do it! Node.js 프로그래밍 이지스퍼블리싱 제공 강의 교안 2017/03"

Similar presentations


Ads by Google