[Node.js] WebSocket 구현하기

2024. 2. 8. 16:32Backend/NodeJS

 

🎈개인적인 경험이 포함되어 있습니다. 틀린 부분이 있을 수 있습니다.

 

잠시 Node.js를 접하게 되면서 WebSocket과 WebRTC를 공부할 일이 생기게 되었습니다. 그래서 다음 기술들을 이용하고 레퍼런스들을 참고해서 간단하게 구현해봤습니다.

 

1. Visual Studio Code, Javascript, Node.js
2. npm init으로 Node.js 환경 실행
3. npm으로 install : express, dotenv, socket.io

 


 

WebSocket

WebSocket이란 클라이언트와 서버를 연결하고, 실시간 소통이 가능하도록 한 컴퓨터 통신 프로토콜입니다. Request/Response로 연결되는 HTTP 통신도 있고, Polling, Long Polling도 있지만... 양방향이면서 실시간으로 통신할 수 있는 기술이 WebSocket입니다.

 

WebSocket 라이브러리 중 유명한 socket.io(https://socket.io/)을 활용하여 구현해보려고 합니다.

 

Socket.IO is a library that enables low-latency, bidirectional and event-based communication

between a client and a server.

 

Socket.io는 클라이언트와 서버 간, 양방향 통신을 가능하게 하는 라이브러리입니다. 해당 라이브러리에 여러 메서드들이 있겠지만, 저는 on과 emit을 이용하고 레퍼런스 참고하여 간단하게 구현하였습니다.

 

1. on : 수신

2. emit : 송신

 


코드 예제

 

기본적으로 Node.js를 통해 웹 페이지를 띄울 수 있다는 가정하에 진행하겠습니다.

 

1. package.json

기본적으로 npm init 이후, npm install을 통해 설치할 수 있는데..

- dotenv에서 포트번호를 작성하여 메인 서버인 server.js에서 활용할 수 있습니다.

- express는 서버로 활용할 수 있습니다.

- socket.io는 양방향 통신을 위해 활용할 수 있습니다.

{
  "main": "server.js",
	// 중략
  "dependencies": {
    "dotenv": "^16.4.1",
    "express": "^4.18.2",
    "socket.io": "^4.7.4"
  }
}

 

2. server.js

- socket.io를 활용하여 클라이언트와 서버를 연결(connection)한 뒤,

- socket 을 연결시켰고, view단에서 방 번호와 user 입력창을 따로 둬서 방에 입장하게끔 구분했습니다.

- 이후 해당 방에서 대화할 시, 해당 방 접속자만 서로 대화할 수 있도록 구현했습니다.

//채팅 연습
//socket server
const socket = require('socket.io');
const io = socket(server);

//socket connected
io.on('connection', (socket) => {
  console.log('socket connected');
  //from Client
  socket.on('join', (msg) => {
    //방에 입장
    console.log(msg.userId + '가 입장');
    console.log(msg.roomId + '에 입장');
    socket.join(msg.roomId);
  });
  //from Client
  socket.on('toServer', (msg) => {
    //to Client
    io.to(msg.roomId).emit('toClient', msg);
  });
  socket.on('disconnect', () => {
    console.log('socket discconnectd');
  });
});

 

3. ~~.html

- 일단 접속 div 하나 구현하고, div 접속되었을 경우 채팅할 수 있는 div를 다르게 구현했습니다.

<body>  
    <!-- webSocket 연습을 위한 html 코드 -->
    <div id="chat">
        <form type="submit" id="roomList">
            <input type="text" id="room" placeholder="roomId"/>
            <input type="text" id="user" placeholder="userId"/>
            <button id="roomBtn">방 입장</button>
        </form>
        <form type="submit" id="chatGroup">
            <input type="text" id="roomId" placeholder="roomId" readonly/>
            <input type="text" id="userId" placeholder="userId" readonly/> 
            <input type="text" id="chatInput" placeholder="내용"/>
            <button id="chatBtn">메시지 전송</button>
        </form>
        <div id="msgBox">
            <div id="msgLine"></div>
        </div>
    </div>
    <!-- socket.io -->
    <script src="/socket.io/socket.io.js"></script> 
    <!-- JS -->
    <script>
        // socket
        let socket = io();
        const chat = document.getElementById('chat');
        const chatGroup = document.getElementById('chatGroup');

        const roomList = document.getElementById('roomList');
        const room = document.getElementById('room');
        const user = document.getElementById('user');
        const roomId = document.getElementById('roomId');
        const roomBtn = document.getElementById('roomBtn');

        const chatInput =  document.getElementById('chatInput');
        const userId = document.getElementById('userId');
        const chatBtn = document.getElementById('chatBtn');
        let chatRoomData = {};
        
        //chat

        //Room
        roomList.addEventListener("submit", async (e) => {
            e.preventDefault();
            chatRoomData = {'msg' : '', 
                            'userId' : user.value, 
                            'roomId' : room.value };
            socket.emit('join', chatRoomData);
            //값을 입력
            userId.value = user.value;
            roomId.value = room.value;
        });
        
        //to Server
        chatGroup.addEventListener("submit", async (e) => {
            e.preventDefault();
            if (chatInput.value) {
                chatRoomData = {'msg' : chatInput.value, 
                                'userId' : userId.value, 
                                'roomId' : roomId.value };
                socket.emit("toServer", chatRoomData);
                chatInput.value = "";
            }
        });

        //from Server
        socket.on("toClient", async (msg) => {
            let item = document.createElement("div");
            if(msg.roomId !== roomId.value){
                alert('another room');
                return;
            } else {
                item.textContent = msg.userId + '님 :' + msg.msg;
                msgLine.appendChild(item);
            }
        });
    </script>

 


실행화면

 

1. room1에 user1, user2 입장

 

2. room2에 user3 입장

- room1과 구분을 지었기 때문에, 채팅 내용이 보이지 않음

 

 

 

 

References

1. 웹소켓이란? 

2. Socket.io

3. Socket.io 모듈

4. Socket.io 사용해보기

 

'Backend > NodeJS' 카테고리의 다른 글

[Node.js] npm  (0) 2024.02.03
[Node.js] 설치  (0) 2024.01.30