Socket.io 사용 경험기, 기본 사용법

기운찬곰·2024년 1월 15일
0

프론트개발이모저모

목록 보기
20/20

Overview

최근에 웹 소켓, Socket.io 를 사용해볼 일이 생겼습니다. 음... 그 동안은 간단한 개념만 알고 있었고 실제 사용해볼일은 없었습니다. 막상 해보니까 그렇게 어려운 건 아닌거 같더라고요. 사용하기 쉽고... 재밌습니다.

이번시간에는 간단하게 웹 소켓 개념과 Socket.io 사용법, 방 만들기 등을 해보면서 기본 사용법에 대해 알아보겠습니다.


웹 소켓 개념

참고 : https://ko.wikipedia.org/wiki/웹소켓

웹소켓은 하나의 TCP 접속에 전이중 통신 채널을 제공하는 컴퓨터 통신 프로토콜 입니다. 2011년 표준화되었다고 하네요. 따라서 대부분의 브라우저가 이 프로토콜을 지원하고 있습니다.

웹 소켓은 사용자의 브라우저와 서버 사이의 인터액티브 통신 세션을 설정할 수 있게 하는 고급 기술입니다. 개발자는 웹 소켓 API를 통해 서버로 메시지를 보내고 서버의 응답을 위해 서버를 폴링하지 않고도 이벤트 중심 응답을 받는 것이 가능합니다.

예를 들어, 채팅, 실시간 알림 등을 사용할 때 웹 소켓을 사용할 수 있겠죠?


Socket.io 사용법

참고 : https://socket.io/docs/v4/tutorial/introduction

Socket.io는 WebSocket을 쉽게 사용할 수 있도록 만들어진 라이브러리입니다. socket.io는 두 부분으로 구성됩니다.

  • socket.io : Node.JS HTTP 서버( 패키지) 와 통합(또는 마운트)되는 서버
  • socket.io-client : 브라우저 측에 로드되는 클라이언트 라이브러리

기본 연결 세팅

import express from 'express';
import { createServer } from 'node:http';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
import { Server } from 'socket.io';

const app = express();
const server = createServer(app);
const io = new Server(server);

const __dirname = dirname(fileURLToPath(import.meta.url));

app.get('/', (req, res) => {
  res.sendFile(join(__dirname, 'index.html'));
});

io.on('connection', (socket) => {
  console.log('a user connected');
});

server.listen(3000, () => {
  console.log('server running at http://localhost:3000');
});
  • (HTTP 서버) 객체를 socket.io전달하여 새 인스턴스를 초기화합니다
  • 그런 다음 들어오는 소켓에 대한 connection 이벤트로 수신하고 이를 콘솔에 기록합니다.

클라이언트 측에서는 이런식으로 사용하면 됩니다.

<script src="/socket.io/socket.io.js"></script>
<script>
  const socket = io();
</script>

이렇게 하고 브라우저에서 웹페이지를 새로 고치면 서버에서 사용자가 연결되었다는 콘솔이 출력되는 것을 확인할 수 있을 겁니다.

요청과 응답 플로우를 살펴보면 재밌는 점을 확인해볼 수 있습니다. 먼저 요청 메시지를 보겠습니다.

GET ws://localhost:3001/socket.io/?EIO=4&transport=websocket HTTP/1.1
Host: localhost:3001
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
Upgrade: websocket
Origin: http://localhost:3000
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate, br
Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
Sec-WebSocket-Key: lyFiq8x1UpYPkbd96Cb0+g==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

Connection: Upgrade 의미 : 이미 생성된 커넥션을 다른 프로토콜로 업그레이드/변경 하겠다는 의미입니다. 즉, webscoket으로 변경하겠다는 것입니다.

응답을 살펴보면 다음과 같습니다. Switching Protocols 이라고 나옵니다. 웹 소켓으로 프로토콜을 제대로 변경했다는 거겠죠?

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: Q4jPf8sCiOPncyzEBGfVqN7+wJo=

브라우저 개발자 도구를 확인하면 웹소캣에서 어떤 데이터를 주고 받는지 볼 수 있습니다. 처음에는 뭔가 설정값 같은걸 보내는거 같고. 이후에는 주기적으로 (25초마다) 통신하고 있는 것을 알 수 있습니다. pingInterval이 25000로 되어있네요. 이러한 이유는 연결 끊기지 말라고 하는거겠죠?

초록색 화살표는 브라우저에서 서버로 전송, 빨강색 화살표는 서버에서 브라우저로 보내는 데이터를 나타냅니다. 처음에 보면 좀 헷갈릴 수 있겠네요.

이벤트 내보내기 (emit)

브라우저와 서버간 통신할 때를 살펴보면 이벤트-이벤트 리스너 개념이랑 동일하다고 보면 됩니다. 이벤트를 발생시키고, 이벤트를 전달받는 그런 개념이죠.

Socket.IO의 기본 아이디어는 원하는 데이터와 함께 원하는 이벤트를 보내고 받을 수 있다는 것입니다. JSON으로 인코딩할 수 있는 모든 개체가 가능하며 이진 데이터 도 지원됩니다.

사용자가 메시지를 입력하면 서버가 이를 이벤트로 받도록 만들어 보겠습니다.

먼저 클라이언트 측입니다.

// socket.emit('이벤트 명', 넘겨줄 값)
socket.emit('hello', 'world');

다음은 서버 측 코드입니다.

io.on('connection', (socket) => {
  // socket.on('이벤트 명', 넘겨진 값)
  socket.on('hello', (arg) => {
    console.log(arg); // 'world'
  });
});

emit으로 내보내고, on으로 이벤트를 전달받는 구조. 알아보기 쉽죠?

이벤트 브로드캐스트 (broadcast)

방(Room)이라는 개념


Socket.io 실습

Node 서버 세팅

간단한 실습을 위해 노드로 소켓 테스트 서버를 띄우겠습니다. 먼저 필요한 라이브러리를 설치해줍니다.

{
  "name": "socket-server",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "nodemon",
    "build": "rimraf build && tsc",
    "start": "pnpm run build && node build/server.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "cors": "^2.8.5",
    "express": "^4.18.2",
    "socket.io": "^4.7.3",
    "zod": "^3.22.4"
  },
  "devDependencies": {
    "@types/cors": "^2.8.17",
    "@types/express": "^4.17.21",
    "@types/node": "^20.10.8",
    "nodemon": "^3.0.2",
    "rimraf": "^5.0.5",
    "ts-node": "^10.9.2",
    "typescript": "^5.3.3"
  }
}

개발 편의를 위해 nodemon 설정을 해줍니다. nodemon.json 파일을 아래와 같이 만들어줍니다.

{
  "watch": ["src"],
  "ext": ".ts",
  "exec": "ts-node src/server.ts"
}

기본적인 서버를 띄우도록 해봅니다. 아직 socket.io를 사용하지 않은 상태입니다.

import express from "express";
import cors from "cors";
import http from "http";

const app = express();

app.use(cors());

const server = http.createServer(app);

const PORT = process.env.PORT || 3400;

server.listen(PORT, () =>
  console.log(`Server is running on port ${PORT} now!`)
);

마치면서


참고 자료

profile
배움을 좋아합니다. 새로운 것을 좋아합니다.

0개의 댓글