본문 바로가기

Side Project

[PROJECT] Socket.io 를 이용한 채팅 애플리케이션 (7) - 채팅 기능 구현 (들어갔으니 채팅을 치자 - 서버)

[PROJECT] Socket.io 채팅 어플리케이션 (7) - 채팅 기능 구현 (채팅치기 - 서버)

Socket.io 채팅 애플리케이션 (7) - 채팅 기능 구현 (들어갔으니 채팅을 치자 - 서버)

지난 시간에

지난 시간에는 채팅방 접속 관련 서버 / 클라이언트 기능을 구현했다.

  • 채팅방에 들어가보자 (server / client)
  • 들어갔으니 채팅을 치자 (server / client)
  • 거의 다했으니 마무리를 하자

그러면 이번 차시에서는 채팅방에 들어갔으니 채팅을 치자.

 

서버측 구현

이번에도 클라이언트와 서버의 플로우를 나누어 생각해보겠다

  1. (c) chatForm 으로 입력받은 값을 서버로 보낸다. send message 이벤트 발생
  2. (s) send message 이벤트 발생 시 이벤트를 발생시킨 소켓의 socket.idroomId 를 가져와 new message 이벤트 발생
  3. (c) new message 이벤트 발생 시 chatLog 에 해당 메세지 내용 추가

지난번 보다 플로우가 엄청 간단하다. 그럼 서버 설정을 진행해 보겠다.

 

2. (s) send message 이벤트 발생 시 이벤트를 발생시킨 소켓의 socket.idroomId 를 가져와 new message 이벤트 발생

# /app.js
io.sockets.on('connection', function(socket){
----------
    socket.on("send message", function (data) {
        io.sockets.in('room' + data.roomId).emit('new message', {
            name: getUserBySocketId(socket.id),
            socketId: socket.id,
            msg: data.msg
        });
    });
    
});

클라이언트 측에서 발생시킨 send message 에서 msgroomId 를 이용해 바로 new message이벤트를 발생시켰다.

놀랍게도 서버의 코드는 이게 전부다.

아래에 위 코드를 포함시킨 전체 코드를 작성해 놓았다.

 

이번에 작성한 전체 코드

# /app.js
var express = require('express'),
    port = process.env.PORT || 3000,
    app = express(),
    server = require('http').createServer(app),
    io = require('socket.io').listen(server),
    users = {
        'test': {
            id: 'test',
            pw: 'test'
        }
    },
    onlineUsers = {};

app.use(express.static('public'));

app.get('/', function (req, res) {
    res.redirect('/chat');
});

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

server.listen(port, () => {
    console.log(`server open ${port}`);
});


io.sockets.on('connection', function (socket) {
    socket.on("join user", function (data, cb) {
        if (joinCheck(data)) {
            cb({
                result: false,
                data: "이미 존재하는 회원입니다."
            });
            return false;
        } else {
            users[data.id] = {
                id: data.id,
                pw: data.pw
            };
            cb({
                result: true,
                data: "회원가입에 성공하였습니다."
            });

        }
    });

    socket.on("login user", function (data, cb) {
        if (loginCheck(data)) {
            onlineUsers[data.id] = {
                roomId: 1,
                socketId: socket.id
            };
            socket.join('room1');
            cb({
                result: true,
                data: "로그인에 성공하였습니다."
            });
            updateUserList(0, 1, data.id);
        } else {
            cb({
                result: false,
                data: "등록된 회원이 없습니다. 회원가입을 진행해 주세요."
            });
            return false;
        }
    });

    socket.on('logout', function () {
        if (!socket.id) return;
        let id = getUserBySocketId(socket.id);
        let roomId = onlineUsers[id].roomId;
        delete onlineUsers[getUserBySocketId(socket.id)];
        updateUserList(roomId, 0, id);
    });

    socket.on('disconnect', function () {
        if (!socket.id) return;
        let id = getUserBySocketId(socket.id);
        if(id === undefined || id === null){
            return;
        }
        let roomId = onlineUsers[id].roomId || 0;
        delete onlineUsers[getUserBySocketId(socket.id)];
        updateUserList(roomId, 0, id);
    });

    socket.on('join room', function (data) {
        let id = getUserBySocketId(socket.id);
        let prevRoomId = onlineUsers[id].roomId;
        let nextRoomId = data.roomId;
        socket.leave('room' + prevRoomId);
        socket.join('room' + nextRoomId);
        onlineUsers[id].roomId = data.roomId;
        updateUserList(prevRoomId, nextRoomId, id);
    });

    function updateUserList(prev, next, id) {
        if (prev !== 0) {
            io.sockets.in('room' + prev).emit("userlist", getUsersByRoomId(prev));
            io.sockets.in('room' + prev).emit("lefted room", id);
        }
        if (next !== 0) {
            io.sockets.in('room' + next).emit("userlist", getUsersByRoomId(next));
            io.sockets.in('room' + next).emit("joined room", id);
        }
    }

    function loginCheck(data) {
        if (users.hasOwnProperty(data.id) && users[data.id].pw === data.pw) {
            return true;
        } else {
            return false;
        }
    }

    function joinCheck(data) {
        if (users.hasOwnProperty(data.id)) {
            return true;
        } else {
            return false;
        }
    }

    function getUserBySocketId(id) {
        return Object.keys(onlineUsers).find(key => onlineUsers[key].socketId === id);
    }

    function getUsersByRoomId(roomId) {
        let userstemp = [];
        Object.keys(onlineUsers).forEach((el) => {
            if (onlineUsers[el].roomId === roomId) {
                userstemp.push({
                    socketId: onlineUsers[el].socketId,
                    name: el
                });
            }
        });
        return userstemp;
    }
});

 

다음 시간에

거의 다했다. 다음 시간에 클라이언트 코드를 짜서 채팅을 완성시켜보자