위의 실행 결과는 에뮬레이터와 제 갤럭시 탭을 사용해서 채팅 기능 테스트를 한 것입니다.
이전 게시물에서 MySQL 을 사용한 로그인, 회원가입을 구현해봤습니다. 이번에는 기능을 확장하여 채팅을 구현했습니다.
Firebase Realtime Database 를 사용해서 채팅을 구현 하는 것은 많이 해봐서 쉬운데 Firebase 를 사용하지 않고, MySQL 로 구현하려니 꽤 어려웠다... 왜냐하면, 안드로이드에서 보안문제 때문에 MySQL 과 직접 연동이 불가능해서 서버를 따로 만들고, 서버와의 통신으로 MySQL에 접근해야하기 때문이다.
우여곡절 끝에 MySQL 을 연동해서 데이터를 삽입하고, 불러오는 것 까지 완료했지만, 한가지 고려해야할 문제점이 있었다.
상대방이 채팅을 보냈을 때 안드로이드에서 그 신호를 받고 즉각적으로 채팅을 보여줘야하는데 MySQL 에는 그런 Listener 기능이 없다.
그래서 생각해낸 방법은 소켓통신을 통해 채팅을 하고, 로그인, 회원가입, 채팅목록 불러오기, 채팅 저장 등 같은 기능들은 MySQL 로 구현하는 것이다.
이 방법이 맞는 방법인지는 잘 모르겠지만, 아무튼 난 이렇게 구현했다
방법이 어찌됐던 MySQL, 소켓통신, Node.js공부를 한꺼번에 할 수 있으니 그걸로 만족한다
get, post 요청에 대한 부분의 작업을 처리하는 부분
const mysql = require('mysql2');
const dbconfig = require('../config/database.js');
const connection = mysql.createConnection(dbconfig);
var express = require('express');
var router = express.Router();
const bodyParser = require('body-parser'); // 1
router.use(bodyParser.urlencoded({ extended: true })); // 2
router.post('/position', (request, response)=>{
response.json(request.body); // or response.send(request.body);
});
router.get('/', function(req, res, next) {
res.status(200).json(
{
"success" : true
}
);
});
router.get('/users_info', (req, res) => {
connection.query('SELECT * FROM User', (error, rows) => {
if(error) throw error;
console.log('user info is : ', rows);
res.status(200).send(rows)
});
});
router.post('/getUserId', (req, res)=>{
const uid = req.body.UID
connection.query('select id from User where UID=?',[uid], (err,rows)=>{
if(err) throw err
console.log('user info is : ', rows)
res.status(200).send(rows)
})
})
router.post('/login', (req, res)=>{
const body = req.body;
const id = body.id;
const pw = body.pw;
connection.query('select * from User where id=? and password=?', [id,pw], (err, data)=>{
if(data.length == 0){ // 로그인 실패
console.log('로그인 실패');
res.status(200).json(
{
"UID" : -1
}
)
}
else{
// 로그인 성공
console.log('로그인 성공');
connection.query('select UID from User where id=?',[id],(err,data)=>{
res.status(200).send(data[0]);
});
}
});
});
router.post('/register', (req, res) =>{
const body = req.body;
const id = body.id;
const pw = body.pw;
connection.query('select * from User where id=?',[id],(err,data)=>{
if(data.length == 0){
console.log('회원가입 성공');
connection.query('insert into User(id, password) values(?,?)',[id,pw]);
res.status(200).json(
{
"message" : true
}
);
}else{
console.log('회원가입 실패');
res.status(200).json(
{
"message" : false
}
);
}
});
});
router.post('/room', (req,res)=>{
const body = req.body;
const sender_id = body.sender_id;
const receiver_id = body.receiver_id;
connection.query('select * from Room where (sender_id=? and receiver_id=?) or (sender_id=? and receiver_id=?)',[sender_id,receiver_id,receiver_id,sender_id],(err,data)=>{
if(data.length==0){
// 만들어진 채팅방이 없으므로 생성
connection.query('insert into Room(sender_id, receiver_id) values(?,?)',[sender_id,receiver_id]);
res.status(200).json(
{
"message" : true
}
)
}else{
// 이미 채팅방이 존재함
res.status(200).json({
"message" : false
})
}
});
});
router.post('/message', (req,res)=>{
const body = req.body;
const sender_id = body.sender_id;
const receiver_id = body.receiver_id;
const text = body.text;
const time = body.time;
connection.query('insert into message(sender_id, receiver_id, text, time) values(?,?,?,?)',[sender_id,receiver_id,text,time]);
console.log(text);
res.send(req.body);
});
router.post('/getMessage', (req,res)=>{
const body = req.body;
const sender_id = body.sender_id;
const receiver_id = body.receiver_id;
connection.query('select sender_id, receiver_id, text, time from message where (sender_id = ? and receiver_id = ?) or (sender_id = ? and receiver_id = ?)',[sender_id,receiver_id,receiver_id,sender_id],(error,rows)=>{
if(error) throw error;
console.log('user info is : ', rows);
res.status(200).send(rows)
});
});
router.post('/getAllRoom', (req,res)=>{
const sender_id = req.body.sender_id;
connection.query('select * from Room where sender_id=?',[sender_id],(error,rows)=>{
if(error) throw error;
console.log('user info is : ', rows);
res.status(200).send(rows)
});
})
router.post('/getRoom', (req,res)=>{
const body = req.body;
const sender_id = body.sender_id;
const receiver_id = body.receiver_id;
connection.query('select number from Room where (sender_id=? and receiver_id=?) or (sender_id=? and receiver_id=?) ',[sender_id,receiver_id,receiver_id,sender_id],(error,rows)=>{
if(error) throw error;
console.log('user info is : ', rows);
res.status(200).send(rows)
});
})
module.exports = router;
소켓통신을 담당하는 부분
socket.on('eventName', function(data)) 를 통해 클라이언트가 eventName 이라는 이벤트를 발생시키고 data 를 전달하면 중괄호 안에서 작업을 수행하고 io.emit() 을 통해 클라이언트에게 응답을 보낸다.
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
const bodyParser = require('body-parser'); // 1
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true })); // 2
io.on('connection', (socket) => {
console.log("user connect");
socket.on('connectReceive', (data) => {
console.log(data)
});
socket.on('disconnect', function() {
console.log('user disconnected');
});
socket.on('connect user', function(user){
console.log("Connected user ");
socket.join(user['roomNumber']);
console.log("roomNumber : ",user['roomNumber']);
console.log("state : ",socket.adapter.rooms);
io.emit('connect user', user);
});
//메세지 입력하면 서버 로그에 이거뜸
socket.on('chat message', function(msg){
console.log("Message " + msg['text']);
console.log("보내는 아이디 : ",msg['sender_id']);
console.log("방 번호 : ", msg['roomNumber'])
io.to(msg['roomNumber']).emit('chat message', msg);
});
});
app.use('/', require('./routes/rides'));
server.listen(8080, function(){
console.log("server on 8080");
});
다음 게시물에서 안드로이드와 연동하는 방법에 대해서 다루겠습니다.