본문 바로가기

Node.js

Node.js - Socket.IO

ws 패키지는 간단하게 웹 소켓을 사용하고자 할 때 좋다. 그러나 구현하려는 서비스가 좀 더 복잡해진다면 Socket.IO를 사용하는 것이 더 편하다. ws 모듈 또한 잘 구현하면 Socket.IO와 같은 기능을 하도록 만들 수 있지만, Socket.IO는 편리한 기능을 많이 지원하여 쓰기 좋다.

 

이전 포스트에서 연결된다.

2020/08/20 - [Node.js] - Node.js - ws로 웹 소켓 사용해보기 (Web Socket Using ws Module)

 

Node.js - ws로 웹 소켓 사용해보기 (Web Socket Using ws Module)

먼저 gif-chat이라는 새로운 프로젝트를 다음과 같이 만들어주고 패키지들을 설치해주자. { "name": "gif-chat", "version": "0.0.1", "description": "GIF CHATTING", "main": "app.js", "scripts": { "start": "..

lgphone.tistory.com

 

먼저 Socket.IO를 설치해주자.

 

> npm i socket.io

 

이제 socket.js의 ws 패키지의 웹소켓 객체를 Socket.IO로 대체해준다.

 

const SocketIO = require('socket.io');

module.exports = (server) => {
    const io = SocketIO(server, { path: '/socket.io' });

    io.on('connection', (socket) => { // 웹 소켓 연결 시
        const req = socket.request;
        const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
        console.log('새로운 클라이언트 접속', ip, socket.id, req.ip);
        
        socket.on('disconnect', () => { // 연결 종료 시
            console.log('클라이언트 접속 해제', ip, socket.id);
            clearInterval(socket.interval);
        });
        socket.on('error', (err) => {
            console.error(err);
        });
        socket.on('reply', (data) => {
            console.log(data);
        });
        socket.interval = setInterval(() => {
            socket.emit('news', 'Hello Socket.IO');
        }, 3000);
    });
};

 

아직까진 ws 패키지와 크게 다른 점이 없다. 먼저 socket.io 패키지를 불러와 익스프레스 서버에 연결했다. SocketIO 객체의 두 번째 인수로 옵션 객체를 넣어 서버에 관현 여러 가지 설정들을 할 수 있다. 여기선 클라이언트가 접속할 경로인 path 옵션만 사용했다. 클라이언트도 이 경로와 일치하는 path를 넣어야한다.

 

연결 후에는 이벤트 리스너를 붙인다. connection 이벤트는 클라이언트가 접속했을 때 발생하며, 콜백으로 소켓 객체를 제공한다. Socket.IO의 핵심은 socket 객체와 io 객체이다. socket.request 속성으로 요청 객체에 접근할 수 있고. socket.request.res로는 응답 객체에 접근할 수 있다. socket.id로 소켓 고유의 아이디도 가져올 수 있으며 이 아이디로 소켓의 주인을 특정할 수 있다.

 

socket에도 이벤트 리스너를 붙였다. disconnect는 클라이언트가 연결을 끊었을 때 발생하고, error는 통신 과정에서 에러가 나왔을 때 발생한다. reply는 사용자가 직접 만든 이벤트이다. 클라이언트에서 reply라는 이벤트 명으로 데이터를 보낼 때 서버에서 받는 부분이다. 이와 같이 이벤트 명들이 ws 모듈과는 다르다.

 

아래에 emit 메서드로 3초마다 클라이언트 한 명에게 메시지를 보내는 부분이 있는데, 인수가 두 개이다. 첫 번째 인수는 이벤트 이름, 두 번째 인수는 데이터다. 즉, news라는 이벤트 이름으로 Hello Socket.IO라는 데이터를 클라이언트에 보낸 것이다. 클라이언트가 이 메시지를 받기 위해선 news라는 이벤트를 받을 news 이벤트 리스너를 만들어두어야 한다. 따라서 클라이언트 부분인 index.html도 다음과 같이 바꿔준다.

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>GIF 채팅방</title>
</head>
<body>
    <div>F12키를 눌러 console 탭과 network 탭을 확인해보세요.</div>
    <script src="/socket.io/socket.io.js"></script>
    <script>
        const socket = io.connect("http://localhost:8005", {
            path: '/socket.io'
        });
        socket.on('news', function (data) {
            console.log(data);
            socket.emit('reply', 'Hello Node.js');
        })
    </script>
</body>
</html>

 

/socket.io/socket.io.js 는 Socket.IO에서 클라이언트로 제공하는 스크립트이며, 실제 파일이 아니다. 이 스크립트를 통해 서버와 유사한 API로 웹 소켓 통신이 가능하다. 스크립트가 제공하는 io 객체에 서버 주소를 적어 연결한다. ws 프로토콜이 아니라 http 프로토콜을 사용한다는 점이 ws 모듈과는 다른 점이다. 그 이유는 나중에 설명한다. 옵션으로 path를 주었는데, 이 부분이 서버의 path 옵션과 일치해야 통신이 가능하다.

 

서버에서 보내는 news 이벤트를 받기 위해 news 이벤트 리스너를 붙여두었다. news 이벤트가 발생하면 emit 메서드로 다시 서버에 답장을 한다. 서버의 reply 이벤트 리스너로 답장이 간다.

 

서버를 실행하고 http://localhost:8005에 접속해보자. 개발자 도구 (F12) 의 Network 탭을 보면 조금 독특한 것을 발견할 수 있는데, 바로 웹 소켓 연결 말고도 폴링 연결 (xhr) 이 있다는 것이다.

 

 

Socket.IO는 먼저 폴링 방식으로 서버와 연결한다. 그래서 코드에서 HTTP 프로토콜을 사용한 것이다. 폴링 연결 후, 웹 소켓을 사용할 수 있다면 웹 소켓으로 업그레이드한다. 웹 소켓을 지원하지 않는 브라우저는 폴링 방식으로, 웹 소켓을 지원하는 브라우저는 웹 소켓 방식으로 연결을 하는 것이다.

 

처음부터 웹 소켓만 사용하고 싶다면 클라이언트에서 socket 옵션에 transports: ['websocket'] 을 넣어 제한할 수 있다.

 

이제 웹 소켓을 사용할 수 있다. 더 많은 기능들을 구현하고 싶다면 다음 문서들과 포스트들을 참고하여 구현하도록 해보자.

 

https://socket.io/docs/

 

Introduction

What Socket.IO isSocket.IO is a library that enables real-time, bidirectional and event-based communication between the browser and the server. It consists of: a Node.js server: Source | API a Javasc

socket.io

 

https://www.zerocho.com/category/NodeJS/post/57edfcf481d46f0015d3f0cd

 

(NodeJS) Socket.io Server API - 설정하기, 전체 채팅, 1대1 채팅, 그룹 채팅

안녕하세요. 이번 시간에는 Socket.io Server API에 대해 알아보겠습니다. 지난 시간에는 간단하게 한 사용자로부터 받은 데이터를 전체 사용자들에게 뿌려줬는데요. 이번 시간에는 그 데이터를 특정

www.zerocho.com

 

 

출처

Node.js 교과서 개정 2판 - 길벗, 조현영

https://socket.io/docs/

https://www.zerocho.com/category/NodeJS/post/57edfcf481d46f0015d3f0cd