누군가에겐 필요한 기록 #1. node.js로 모바일 채팅서버 구현하기

 

 

 

세상에 두가지 언어만 남기라면 C++와 자바스크립트만 남을 것이라는 이야기를 종종 한다.

서버 솔루션이나 SI, 모바일에선 여전히 자바가 인기가 있지만,

자바는 사공이 많아 점점 산으로 가고 있고

자바의 유행을 지속하고 있는 거대기업들(현재는 구글이 대표적)이

기술의 트렌드를 바꾸면 언제 인기가 사그러들기 시작할지 모르는 일이다.

그리고, 포지션이 애매하다. 좋은 언어이지만 꼭 필요한 언어는 아니다.

마찬가지로 PHP또한 이제 대안이 너무 많고,

상당수의 파이를 워드프레스가 차지하고 있으므로,

혹여 워드프레스가 몰락하게 되면(설마 그럴일은 없겠지 워낙 강력해서..)

퍼센테이지가 급격하게 빠질 것으로 예상한다.

일전에 node를 언급하면서

R&R에서 개인의 커버리지를 넓힐 수 있는 가장 빠른 방법이라 했었다.

물론 그 생각엔 변함이 없고, 그 생각을 만들어준 간단한 코드를 보여드릴까 한다.

 

준비물

1.linux 머신

- 윈도우 + virtualbox도 무방

2.인터넷공유기

- 가정이라면 유동ip일 확률이 높으므로 포트포워딩과 ddns가 지원되는 기종 추천

3.안드로이드 개발환경

- 안드로이드 폰이 없다면 AVD로 대신할 수 있음

 

개발환경 설정

 

개인적으로 데비안 계열과 레드햇 계열을 많이 사용하는데, 기준은 데비안 계열로 하겠다.

먼저 nodejs와 npm을 설치한다.

 $ sudo apt-get install curl  
 $ sudo curl -sL https://deb.nodesource.com/setup_4.x | bash ?  
 $ sudo apt-get install -y nodejs  

npm이 설치되면 node의 버전을 이 글에서 사용할 기준버전으로 변경한다.

 $ sudo npm install -g n  
 $ sudo n 4.4.3  

node -v 라고 쳐 보면 node버전이 4.4.3으로 변경된 것을 확인할 수 있다.

 

필요한 모듈 설치

 

일단 프로젝트 경로를 하나 생성한다.

예를 들어 android-chat 이라고 만든다고 해 보자.

 $ mkdir android-chat  
 $ cd android-chat  

 

소스 경로로 진입한 뒤 모듈 설치를 한다.

 $ npm install express@3.4.8  
 $ npm install mysql@2.10.2  
 $ npm install mime@1.3.4  
 $ npm install socket.io@1.4.5  
 $ npm install winston@2.2.0  
 $ npm install dateformat@1.0.12  
 $ npm install urlencode@1.1.0  

이 코드를 작성해본 것이 꽤 되었기 때문에, 모듈 버전도 구버전일 수 있다.

모듈은 android-chat/node_modules 경로 안에 설치가 된다.

 

express는 node의 대표적인 웹 프레임워크다.

이 모듈을 로딩한 것만으로도 이 코드는 url을 통한 http request를 처리할 능력이 생겼다.

socket.io는 실시간 프로그램을 구성하기 위한 웹소켓 호환모듈의 일종이다.

html5에서 추가된 공식 웹소켓과 달리 이 모듈은 구버전 브라우저에서도 잘 돌아간다.

winston모듈은 많은 node사용자들에 의해 애용되고 있는 logger 모듈이다.

 

프로그램 작성 예시

 

이제 android-chat경로에 js파일을 하나 생성해 보자.

일단 index.js라고 이름짓겠다.

간단히 DB, API, socket.io 의 예제를 살펴보며 어떤 형태의 구성이 되는지 알아보자.

 

 var express = require(‘express’);  
 var app = express();  
 var server = require(‘http’).createServer(app);  
 var io = require(‘socket.io’)(server);  
 var port = process.argv[2] || 3000;  
 var mysql = require(‘mysql’);  

 

모듈은 require로 가져온다.

기본적으로 채팅 서버 프로그램의 구성에 필요한 최소한이라고 생각하는 것들을 넣어 보았다.

나중에 필요하다면 좀더 서버별 기능을 분리할 수 있겠으나,

일단은 글 작성의 목적이 초심자들을 위한 것이므로

한 서버 프로그램에 이 기능들을 다 때려넣는다.

 

먼저, mysql 커넥션을 생성하고 핸들러를 만든다.

 function handleDisconnect(){  
   client = mysql.createConnection({  
     user : ‘root’,  
     password : ‘testpass’,  
     database : ‘test’  
   });  
   client.connect(function(err) {  
     if(err) {  
       console.log(‘error when connecting to db:’, err);  
       setTimeout(handleDisconnect, 2000);  
     }  
   });  
   client.on(‘error’, function(err) {  
     console.log(‘db error’, err);  
     if(err.code === ‘PROTOCOL_CONNECTION_LOST’) {  
       handleDisconnect();  
     } else {  
       throw err;  
     }  
   });  
 }  
 handleDisconnect();  

 

node 서버 포트를 오픈한다.

 server.listen(port, function () {  
   console.log(‘Server listening at port %d’, port);  
 });  

 

express 로 받아들일 url 규칙을 정한다.

 app.use(express.static(__dirname + ‘/chat/public’));  
 app.use(express.bodyParser({uploadDir:__dirname+’/multipart’}));  

 

이제 express framework로 웹서버를 작성할 준비가 완료되었다.

그러면 post로 작동하는 api 예제를 보자.

 

 app.post(‘/get-user-info’ , function(request , response){  
   var mem_idx = request.param(‘mem_idx’);  
   var sql = ” SELECT user_id, profile_pic FROM members WHERE mem_idx = ? “;  
   client.query(sql , [mem_idx] , function(error , results){  
     if(error){  
       console.log(error);  
     }else{  
       console.log(results);  
       response.json(results[0]);  
     }  
   });  
 });  

 

실로 간단하지 않은가,

mem_idx라는 이름의 파라메터를 받고

mysql db에서 해당 회원번호의 멤버에 대한 user_id와 profile_pic주소를 가져와

callback이 오면 json형태로 response 해준다.

 

이때 유저가 접근해야 하는 주소는

http://서버주소:3000/chat/public/get-user-info 가 된다.

post 대신 get으로 파라메터를 받고 싶다면 app.get 이라고 바꿔 적으면 그만이다.

 

그렇다면 이번에는 socket.io의 새 메세지 생성 호출시 실시간 처리를 살펴보자.

 io.on(‘connection’, function (socket) { // socket.io코드는 on(‘connection’, ) 내에서 작성한다.  
   socket.on(‘new message’, function (data) {  
     var jsondata;  
     try{  
       jsondata = JSON.parse(data);  
     } catch(e) {  
       jsondata = data;  
     }  
     var now = new Date();  
     var reg_date = dateFormat(now, “yyyy-mm-dd HH:MM:ss”);  
     var sql = ” INSERT INTO messages SET seller_idx = ?, buyer_idx = ?, from_idx = ?, msg_json = ?, reg_date = ?, order_idx = ?, read_status = 0, type = ?, category = ? “;  
     client.query(sql , [jsondata.seller_idx, jsondata.buyer_idx, jsondata.from_idx, jsondata.msg_json, reg_date, jsondata.order_idx, jsondata.type, jsondata.category] , function(error , results){  
       if(error){  
         console.log(error);  
       }else{  
         var room_idx = “” + jsondata.order_idx + “-” + jsondata.category;  
         jsondata.reg_date = reg_date;  
         jsondata.msg_idx = results.insertId;  
         io.sockets.in(room_idx).emit(‘new message’, jsondata);  
       }  
     });  
   });  
 }  

 

클라이언트에서 서버측으로 'new message'라는 이름으로 data가 emit되면,

data를 파싱하여 DB에 메세지 내용을 쌓고

다시 클라이언트 측에 'new message'라는 이름으로 jsondata를 emit 해준다.

주고받는 것이 양방향 자유자재로 이루어질 뿐,

개발하는 방법론은 거의 API와 흡사하다.

 

채팅서비스 구성

 

먼저 DB다.

 

  1. members

- 회원정보가 들어있는 테이블이다.

 CREATE TABLE members (  
 mem_idx INT NOT NULL AUTO_INCREMENT, // 회원번호  
 user_id CHAR(20) NOT NULL, // ID  
 user_pw TEXT NOT NULL, // PW  
 profile_pic CHAR(100), // 프로필사진 URL  
 PRIMARY KEY (mem_idx),  
 UNIQUE (user_id))  

 

  1. messages

- 채팅 내역을 쌓는 테이블이다.

 CREATE TABLE messages (  
 msg_idx INT NOT NULL AUTO_INCREMENT, // 메세지 index  
 my_idx INT, // 채팅생성자(나)의 mem_idx  
 your_idx INT, // 채팅참여자(상대방)의 mem_idx  
 from_idx INT, // 채팅 작성자의 mem_idx <- my_idx 혹은 your_idx 둘중 하나가 됨  
 msg_json TEXT, // 메세지 컨텐츠의 json데이터  
 reg_date DATETIME, // 메세지 등록시간  
 room_idx INT, // 채팅방 구분값  
 read_status INT, // 상대가 메세지를 읽었는지  
 type INT, // 메세지 타입 (텍스트, 이미지URL, 첨부파일URL 기타등등…)  
 category INT, // 채팅방의 종류가 많을때  
 PRIMARY KEY (msg_idx))  

 

앞서 본 예시처럼 모든 API를 express로 구현하도록 한다.

기본기능 구현에 필요한 API는 다음과 같다.

  1. login (랜덤채팅 여부에 따라 회원가입은 옵션)
  2. get-user-info

- 채팅방 내외에서 사용할 유저 정보를 가져온다. id와 프로필사진 url 등..

  1. new-message

- 사실 실시간서비스에서 처리하면 되므로 사실 단순 채팅프로그램이라면 필요치 않다.

- 그러나 채팅 클라이언트가 아닌 다른 위치에서(웹페이지에서 유저액션에 의한 푸시라던가) 메세지를 생성해야 할 경우 전달받기가 좋을 것.

  1. room-list

- 참여한 채팅방 리스트 및 최근메세지와 안읽은 메세지 갯수 등

  1. chat-contents

- 채팅방 내 대화 내역.

  1. file-upload
  2. file-download

 

그리고 필요한 실시간 서비스는 다음과 같다.

  1. join

- 채팅방 입장

  1. new message

- 새로운 메세지 생성

  1. read message

- 메세지를 수신한 경우 읽음처리

 

서버측 코드를 첨부한다.

이제 나머지는 Q&A로..

코드가 좀 아쉬울 수도 있는데,

JS안만진지 10년만에 써본 코드니 감안하고 봐 주시길..

 

 var express = require(‘express’);  
 var app = express();  
 var server = require(‘http’).createServer(app);  
 var io = require(‘socket.io’)(server);  
 var port = process.argv[2] || 3000;  
 var fs = require(‘fs’);  
 var mysql = require(‘mysql’);  
 var path = require(‘path’);  
 var mime = require(‘mime’);  
 var winston = require(‘winston’);  
 var dateFormat = require(‘dateformat’);  
 var urlencode = require(‘urlencode’);  

 winston.add(winston.transports.File, {  
   level : ‘debug’,  
   json : true,  
   filename : ‘chatlog-‘,  
   datePattern : ‘yyyy-MM-dd.log’  
 });  

 function handleDisconnect(){  
   client = mysql.createConnection({  
     user : ‘root’,  
     password : ‘testpass’,  
     database : ‘test’  
   });  
   client.connect(function(err) {  
     if(err) {  
       console.log(‘error when connecting to db:’, err);  
       setTimeout(handleDisconnect, 2000);  
     }  
   });  
   client.on(‘error’, function(err) {  
     console.log(‘db error’, err);  
     if(err.code === ‘PROTOCOL_CONNECTION_LOST’) {  
       handleDisconnect();  
     } else {  
       throw err;  
     }  
   });  
 }  
 handleDisconnect();  

 if(typeof(String.prototype.trim) === “undefined”)  
 {  
   String.prototype.trim = function()  
   {  
     return String(this).replace(/^\s+|\s+$/g, ”);  
   };  
 }  

 server.listen(port, function () {  
   console.log(‘Server listening at port %d’, port);  
 });  
 app.use(express.static(__dirname + ‘/chat/public’));  
 app.use(express.bodyParser({uploadDir:__dirname+’/multipart’}));  

 app.post(‘/login’ , function(request,response){  
   console.log(‘/login’);  
   var user_id = request.param(‘user_id’).trim();  
   var user_pw = request.param(‘user_pw’).trim();  
   var info = {  
     ‘user_id’:user_id,  
     ‘user_pw’:user_pw  
   };  
   console.log(info);  
   var json = {};  
   var sql = ‘INSERT INTO members set ? ‘;  
   console.log(sql);  
   client.query(sql , info , function(error , results){  
     if(error){  
       console.log(error);  
     }else{  
       console.log(results);  
       var sql_mem_sel = ‘ SELECT mem_idx FROM members WHERE user_id = ? ‘;  
       console.log(sql_mem_sel);  
       client.query(sql_mem_sel , [user_id] , function(error , results){  
         if(error){  
           console.log(error);  
         }else{  
           var mem_idx = results[0].mem_idx;  
           var room_idx = Math.floor(Math.random() * (30000 ? 20000) + 20000);  
           var sql_msg_ins = ” INSERT INTO messages SET my_idx = ?, your_idx = ?, from_idx = ?, msg_json = ?, reg_date = now(), room_idx = ?, read_status = 0, type = ?, category = ? “;  
           console.log(sql_msg_ins);  
           client.query(sql_msg_ins, [mem_idx, 1, 1, “talk with : id soso pw soso”, room_idx, 0, 1] , function(error , results){  
             if(error){  
               console.log(error);  
             }else{  
               console.log(results);  
             }  
           });  
         }  
       });  
     }  
   });  
   var sql_check_mem = ‘ SELECT mem_idx, user_id, user_pw, profile_pic FROM members WHERE user_id = ? ‘;  
   console.log(sql_check_mem);  
   client.query(sql_check_mem , [user_id] , function(error , results){  
     if(error){  
       console.log(error);  
       json = {result : 0};  
     }else{  
       if(results.length > 0 && user_pw == results[0].user_pw){  
         console.log(results);  
         json = {result : 1,  
           mem_idx : results[0].mem_idx,  
           profile_pic : results[0].profile_pic};  
       }else{  
         json = {result : 0};  
       }  
     }  
     response.send(json);  
   });  
 });  

 app.post(‘/get-user-info’ , function(request , response){  
   console.log(‘/get-user-info’);  
   var mem_idx = request.param(‘mem_idx’);  
   console.log(mem_idx);  
   var sql = ” SELECT user_id, profile_pic FROM members WHERE mem_idx = ? “;  
   console.log(sql);  
   client.query(sql , [mem_idx] , function(error , results){  
     if(error){  
       console.log(error);  
     }else{  
       console.log(results);  
       response.json(results[0]);  
     }  
   });  
 });  

 app.post(‘/profile-pic’, function(request, response){  
   console.log(‘/profile-pic’);  
   var mem_idx = request.param(‘mem_idx’);  
   var filename = request.param(‘filename’);  
   console.log(“” + mem_idx + path);  
   var sql = ” UPDATE members SET profile_pic = ? WHERE mem_idx = ? “;  
   console.log(sql);  
   client.query(sql, [filename, mem_idx], function(error, results){  
     if(error){  
       console.log(error);  
       json = {result : 0};  
     }else{  
       console.log(results);  
       json = {result : 1};  
       response.send(json);  
     }  
   });  
 });  

 app.post(‘/new-message’ , function(request , response){  
   console.log(‘/new-message’);  
   var my_idx = request.param(‘my_idx’);  
   var your_idx = request.param(‘your_idx’);  
   var from_idx = request.param(‘from_idx’);  
   var msg_json = request.param(‘msg_json’);  
   var reg_date = request.param(‘reg_date’);  
   var room_idx = request.param(‘room_idx’);  
   var type = request.param(‘type’);  
   var category = request.param(‘category’);  
   console.log(msg_json);  
   var sql = ” INSERT INTO messages SET my_idx = ?, your_idx = ?, from_idx = ?, msg_json = ?, reg_date = ?, room_idx = ?, read_status = 0, type = ?, category = ? “;  
   console.log(sql);  
   client.query(sql , [my_idx, your_idx, from_idx, msg_json, reg_date, room_idx, type, category] , function(error , results){  
     if(error){  
       console.log(error);  
     }else{  
       console.log(results);  
       response.send(results);  
     }  
   });  
 });  

 app.post(‘/room-list’, function(request, response){  
   console.log(‘/room-list’);  
   var mem_idx = Number(request.param(‘mem_idx’));  
   var category = Number(request.param(‘category’));  
   console.log(mem_idx);  
   var sql = “SELECT messages.msg_idx, messages.my_idx, messages.your_idx, messages.from_idx, messages.msg_json, messages.room_idx, DATE_FORMAT(messages.reg_date , ‘%Y-%m-%d %H:%i:%s’) AS reg_date, messages.read_status, messages.type, messages.category “  
       + “FROM (SELECT MAX(msg_idx) AS msg_idx, my_idx, your_idx, room_idx, category FROM messages WHERE (my_idx = ? OR your_idx = ?) AND category = ? GROUP BY room_idx)”  
       + ” AS subtbl INNER JOIN messages ON subtbl.msg_idx = messages.msg_idx AND subtbl.room_idx = messages.room_idx ORDER BY msg_idx DESC”;  
   console.log(sql);  
   client.query(sql, [mem_idx, mem_idx, category], function(error, results){  
     if(error){  
       console.log(error);  
     }else{  
       console.log(results);  
       var sql_mem = “SELECT mem_idx, user_id, profile_pic FROM members WHERE ” ;  
       for(var i=0; i<results.length; i++){  
         var otherside_idx = (mem_idx == results[i].my_idx) ? results[i].your_idx : results[i].my_idx;  
         results[i].mem_idx = otherside_idx;  
         if(i!=0){  
           sql_mem = sql_mem + ” OR “;  
         }  
         sql_mem = sql_mem + “mem_idx = ” + otherside_idx;  
       }  
       console.log(sql_mem);  
       client.query(sql_mem, [], function(error, mem_results){  
         if(error){  
           console.log(error);  
         }else{  
           console.log(mem_results);  
           for (var i=0; i<results.length; i++){  
             for (var j=0; j<mem_results.length; j++){  
               if(results[i].mem_idx == mem_results[j].mem_idx){  
                 results[i].user_id = mem_results[j].user_id;  
                 results[i].profile_pic = mem_results[j].profile_pic;  
               }  
             }  
           }  
           for (var i=0; i<results.length; i++){  
             if(typeof results[i].user_id == “undefined”){  
               results[i].user_id = “noname”;  
             }  
             if(typeof results[i].profile_pic == “undefined”){  
               results[i].profile_pic = “”;  
             }  
           }  
           var sql_msg = “SELECT MAX(msg_idx) as msg_idx, room_idx, category, COUNT(*) AS read_status FROM messages WHERE (my_idx = ? OR your_idx = ?) AND category = ? AND read_status = 0 AND from_idx != ? GROUP BY room_idx”;  
           console.log(sql_msg);  
           client.query(sql_msg, [mem_idx, mem_idx, category, mem_idx], function(error, msg_cnt_results){  
             if(error){  
               console.log(error);  
             }else{  
               console.log(msg_cnt_results);  
               for (var i=0; i<results.length; i++){  
                 results[i].read_status = 0;  
                 for (var j=0; j<msg_cnt_results.length; j++){  
                   if(results[i].room_idx == msg_cnt_results[j].room_idx && results[i].category == msg_cnt_results[j].category){  
                     results[i].read_status = msg_cnt_results[j].read_status;  
                   }  
                 }  
               }  
               console.log(results);  
               response.json(results);  
             }  
           });  
         }  
       });  
     }  
   });  
 });  

 app.post(‘/chat-contents’, function(request, response){  
   console.log(‘/chat-contents’);  
   var room_idx = request.param(‘room_idx’);  
   var category = request.param(‘category’);  
   console.log(room_idx);  
   var sql = ” SELECT msg_idx, my_idx, your_idx, from_idx, msg_json, room_idx, DATE_FORMAT(reg_date , ‘%Y-%m-%d %H:%i:%s’) AS reg_date, read_status, type, category FROM messages WHERE room_idx = ? AND category = ? ORDER BY msg_idx ASC”;  
   console.log(sql);  
   client.query(sql, [room_idx, category], function(error, results){  
     if(error){  
       console.log(error);  
     }else{  
       console.log(results);  
       response.json(results);  
     }  
   });  
 });  

 app.get(‘/multipart/:name’ , function(request , response){  
   console.log(‘/multipart’);  
   if(request.params.name!=null){  
     console.log(request.params.name);  
     console.log(urlencode(request.params.name));  
     var file = __dirname + ‘/multipart/’ + urlencode(request.params.name);  
     if(fs.existsSync(file)){  
       var filename = path.basename(file);  
       var mimetype = mime.lookup(file);  
       response.setHeader(‘Content-disposition’, ‘attachment; filename=’ + filename);  
       response.setHeader(‘Content-type’, mimetype);  
       var filestream = fs.createReadStream(file);  
       filestream.pipe(response);  
     }  
   }else{  
     var json = {result : 0};  
     response.send(json);  
   }  
 });  

 app.post(‘/file-upload’ , function(request , response){  
   console.log(‘/file-upload’);  
   var utf8name = request.param(“file_name”);  
   var imageFile = request.files.file;  
   console.log(imageFile);  
   if(imageFile){  
     var name = imageFile.name  
     var path = imageFile.path;  
     var type = imageFile.type;  
     var filename = Date.now() + ‘_’ + urlencode(utf8name);  
     var outputPath = __dirname + ‘/multipart/’ + filename;  
     fs.rename(path , outputPath , function(error){  
       if(error){  
         console.log(error);  
       }else{  
         var json = {filename : filename};  
         console.log(json);  
         response.send(json);  
       }  
     });  
   }  
 });  


 io.on(‘connection’, function (socket) {  

   socket.on(‘join’ , function(data){  
     console.log(“join”);  
     console.log(data);  
     var jsondata;  
     try{  
       jsondata = JSON.parse(data);  
     } catch(e) {  
       jsondata = data;  
     }  
     var room_no = “” + jsondata.room_idx + “-” + jsondata.category;  
     console.log(room_no);  
     socket.join(room_no);  
   });  

   socket.on(‘new message’, function (data) {  
     console.log(“new message”);  
     console.log(data);  
     var jsondata;  
     try{  
       jsondata = JSON.parse(data);  
     } catch(e) {  
       jsondata = data;  
     }  
     var now = new Date();  
     var reg_date = dateFormat(now, “yyyy-mm-dd HH:MM:ss”);  
     var sql = ” INSERT INTO messages SET my_idx = ?, your_idx = ?, from_idx = ?, msg_json = ?, reg_date = ?, room_idx = ?, read_status = 0, type = ?, category = ? “;  
     console.log(sql);  
     client.query(sql , [jsondata.my_idx, jsondata.your_idx, jsondata.from_idx, jsondata.msg_json, reg_date, jsondata.room_idx, jsondata.type, jsondata.category] , function(error , results){  
       if(error){  
         console.log(error);  
       }else{  
         console.log(results);  
         var room_no = “” + jsondata.room_idx + “-” + jsondata.category;  
         jsondata.reg_date = reg_date;  
         console.log(“room idx : ” + room_no);  
         jsondata.msg_idx = results.insertId;  
         console.log(jsondata);  
         io.sockets.in(room_no).emit(‘new message’, jsondata);  
       }  
     });  
   });  

   socket.on(‘read message’, function (data) {  
     console.log(“read message”);  
     console.log(data);  
     var jsondata;  
     try{  
       jsondata = JSON.parse(data);  
     } catch(e) {  
       jsondata = data;  
     }  
     var sql = ” UPDATE messages SET read_status = 1 WHERE room_idx = ? AND category = ? AND msg_idx <= ? AND from_idx != ? AND read_status = 0″;  
     console.log(sql);  
     client.query(sql , [ jsondata.room_idx, jsondata.category, jsondata.msg_idx, jsondata.mem_idx ] , function(error , results){  
       if(error){  
         console.log(error);  
       } else{  
         console.log(results);  
         var room_no = “” + jsondata.room_idx + “-” + jsondata.category;  
         console.log(room_no);  
         socket.broadcast.to(room_no).emit(‘read message’, jsondata);  
       }  
     });  
   });  
 });  

 

그리고 안드로이드 클라이언트측의 socket.io 코드를 첨부한다.

 private Socket mSocket;  

   {  
     try {  
       mSocket = IO.socket(Const.SERVER_SOCKET);  
     } catch (URISyntaxException e) {  
       throw new RuntimeException(e);  
     }  
   }  

   public void initSocket() {  
     mSocket.on(Socket.EVENT_CONNECT_ERROR, onConnectError);  
     mSocket.on(Socket.EVENT_CONNECT_TIMEOUT, onConnectError);  
     mSocket.on(“new message”, onNewMessage);  
     mSocket.on(“read message”, onReadMessage);  
     mSocket.connect();  
   }  

   public void disconnectSocket() {  
     mSocket.disconnect();  
     mSocket.off(Socket.EVENT_CONNECT_ERROR, onConnectError);  
     mSocket.off(Socket.EVENT_CONNECT_TIMEOUT, onConnectError);  
     mSocket.off(“new message”, onNewMessage);  
     mSocket.off(“read message”, onReadMessage);  
   }  

   private Emitter.Listener onConnectError = new Emitter.Listener() {  
     @Override  
     public void call(final Object… args) {  
       runOnUiThread(new Runnable() {  
         @Override  
         public void run() {  
         }  
       });  
     }  
   };  

   private Emitter.Listener onNewMessage = new Emitter.Listener() {  
     @Override  
     public void call(final Object… args) {  
       runOnUiThread(new Runnable() {  
         @Override  
         public void run() {  
           try {  
             JSONObject data = (JSONObject) args[0];  
             ChattingModel chatModel = new ChattingModel();  
             chatModel.setRoom_idx(data.getInt(“room_idx”));  
             chatModel.setMsg_idx(data.getInt(“msg_idx”));  
             chatModel.setMy_idx(data.getInt(“my_idx”));  
             chatModel.setYour_idx(data.getInt(“your_idx”));  
             chatModel.setMsg_json(data.getString(“msg_json”));  
             chatModel.setFrom_idx(data.getInt(“from_idx”));  
             chatModel.setType(data.getInt(“type”));  
             chatModel.setCategory(data.getInt(“category”));  
             chatModel.setRead_status(data.getInt(“read_status”));  
             chatModel.setReg_date(data.getString(“reg_date”));  
             insertMsgToRealm(chatModel);  
           } catch (JSONException e) {  
             e.printStackTrace();  
           }  
         }  
       });  
     }  
   };  

   private Emitter.Listener onReadMessage = new Emitter.Listener() {  
     @Override  
     public void call(final Object… args) {  
       runOnUiThread(new Runnable() {  
         @Override  
         public void run() {  
         }  
       });  
     }  
   };  

   private void joinRoom() {  
     MessageModel cm = new MessageModel();  
     cm.setOrder_idx(mOrder_idx);  
     cm.setCategory(mCategory);  
     Gson gson = new Gson();  
     String data = gson.toJson(cm);  
     DevLog.v(“chattest”, data);  
     mSocket.emit(“join”, data);  
   }  

   private void sendNewMessage(String msg, int type) {  
     DevLog.w(this, “insertMsg() msg >> ” + msg);  
     Calendar cal = Calendar.getInstance();  
     SimpleDateFormat format = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);  
     String regDate = format.format(cal.getTime());  
     MessageModel cm = new MessageModel();  
     cm.setMy_idx(mMy_idx);  
     cm.setYour_idx(mYour_idx);  
     cm.setFrom_idx(mMem_Idx);  
     cm.setMsg_json(msg);  
     cm.setRoom_idx(mRoom_idx);  
     cm.setReg_date(regDate);  
     cm.setRead_status(0);  
     cm.setType(type);  
     cm.setCategory(mCategory);  
     Gson gson = new Gson();  
     String data = gson.toJson(cm);  
     DevLog.v(“chattest”, data);  
     mSocket.emit(“new message”, data);  
   }  

   private void readAllMessage(int msgIdx) {  
     MessageModel cm = new MessageModel();  
     cm.setMsg_idx(msgIdx);  
     cm.setRoom_idx(mRoom_idx);  
     cm.setCategory(mCategory);  
     cm.setMem_idx(mMem_Idx);  
     Gson gson = new Gson();  
     String data = gson.toJson(cm);  
     DevLog.v(“chattest”, data);  
     mSocket.emit(“read message”, data);  
   }  

 

여기에서는 node session을 다루지 않는다.

예제수준의 코드를 작성하는데 사용자 인증절차가 들어가면

비슷한 코드의 연속으로 인한 라인만 늘어나기 때문.

그러나 코드는 간단하니

http://webframeworks.kr/tutorials/expressjs/auth_log_in_out/

를 참고하길 바란다.

 

One thought on “누군가에겐 필요한 기록 #1. node.js로 모바일 채팅서버 구현하기

  1. 어우,, 잘 읽고갑니다 : )
    질문이 이는데요~
    몽고디비 등에서 얻어온 JSON을 console.log(“내용”)이렇게 콘솔에다가 출력할 수 있잖아요?
    그러면 반대로 웹에다 출력하려면 어찌해야할까요? ㅠㅠ?
    아이디 눌러주세요 메일링크 걸어놨어요~

Leave a Reply

Your email address will not be published. Required fields are marked *