📚 자료실

WebSocket과 socket.io의 기본 개념

hjinn0813 2025. 1. 14. 12:17
728x90

회사에서 새로운 프로젝트에 socket.io를 사용할 예정이니까 미리 공부해두라고 해서 기록하는 글.

socket.io를 알기 전에 먼저 WebSocket이 뭔지부터 공부해봤다.


웹소켓(WebSocket)

실시간 양방향 데이터 전송을 위한 기술로, 'WS 프로토콜' 이라고도 부른다.

TCP를 기반으로 하는 "전송 계층 프로토콜"이다.

※ OSI 7계층 설명은 여기 참고 - https://hjinn0813.tistory.com/133

 

프로토콜의 개념과 종류, OSI 7계층, TCP/IP 4계층

데이터 전송 절차와 관련해서 공부를 하다보니, 올해 상반기 정보처리기사 준비하면서 봤던 OSI 7계층을 다시 보게 됐다.

hjinn0813.tistory.com


실시간 통신을 위해, 가장 초기에는 폴링(polling)이라는 방식을 사용했다. 클라이언트가 주기적으로 업데이트를 확인해달라고 요청하고, 서버는 요청을 받을 때마다 데이터를 응답해야 하니까 서버에 부담으로 이어질 수 밖에 없었다. 또한 http 요청이 클라이언트 → 서버로만 가능해서, 서버에 변화가 있어도 클라이언트가 물어보기 전까지는 알 수 없어 실시간 통신을 구현하는데 한계가 있었다.

그래서 이후에 등장한게 Server Sent Event(SSE)라는 기술이다. 서버가 주체적으로 클라이언트에게 데이터를 전송할 수 있는 기술인데, 이건 클라이언트가 서버에서 받기만 할 수 있어서 양방향 통신이 불가능했다.

반면에 웹소켓은 이벤트 방식으로 동작하여 한번만 연결해놓으면 지속적으로 실시간 양방향 데이터 전송이 가능하기 때문에, 불필요한 요청이나 리소스 낭비가 없어서 최신 브라우저는 대부분 웹소켓을 지원한다. 그러나 모든 사용자가 최신 브라우저를 사용한다는 보장이 없으므로 socket.io 같은 JS 라이브러리를 사용한다.

WS 프로토콜의 특징
- 실시간 양방향 통신 방식으로, 클라이언트 ↔ 서버가 동시에 데이터를 주고받을 수 있다.
- 연결을 유지하므로, 반복적인 HTTP 요청/응답 없이 데이터 전송이 가능하다.
- 프로토콜 표기는 https와 같이 ws, wss로 나뉜다.
.
WS 프로토콜의 작동 방식
1. 초기엔 HTTP 요청으로 연결 시작
2. 연결 성공하면 WebSocket 프로토콜로 업그레이드되어 지속적인 연결 유지
3. 이후 클라이언트와 서버는 같은 연결을 통해 데이터를 자유롭게 주고받음

WS 작동원리


WebSocket을 사용한 실시간 알림 예시 코드

ChatGPT가 만들어준 예시 코드를 여기에 참고용으로 기록해본다.

서버는 Node.js + WebSocket을 사용했고, 클라이언트는 HTML + JavaScript를 사용했다.

/* 서버 (Node.js + WebSocket) */
const WebSocket = require('ws'); // ws에서 요청받겠다는 의미
const wss = new WebSocket.Server({ port: 8080 });
// 웹소켓 서버 번호 8080으로 통신하겠다는 의미

/* 클라이언트가 연결되었을 때 */
wss.on('connection', (ws) => {
  console.log('클라이언트가 연결됨');
  // on()을 통해서 연결하기

  /* 클라이언트로부터 메시지를 받을 때 */
  ws.on('message', (message) => {
    console.log(받은 메시지: ${message});

    /* 모든 클라이언트에게 실시간 알림 보내기 */
    wss.clients.forEach((client) => {
      if (client !== ws && client.readyState === WebSocket.OPEN) {
        client.send('새로운 알림: ' + message);
       // send()를 통해서 알림 보내기
      }
    });
  });

  /* 클라이언트에게 초기 메시지 전송 */
  ws.send('서버에 연결되었습니다. 알림을 기다려주세요!');
});

console.log('웹소켓 서버가 8080 포트에서 실행 중...');
<!-- 클라이언트 (HTML + JS) -->
<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>웹소켓 실시간 알림</title>
  <style>
    #messages { border: 1px solid #ccc; 
      padding: 10px; 
      margin-top: 10px; 
      height: 200px; 
      overflow-y: auto; }
    #input { width: 100%; padding: 10px; }
  </style>
</head>

<body>
  <h1>실시간 알림</h1>
  <div id="messages"></div>
  <input type="text" id="input" placeholder="알림 메시지 입력..." />
  <script>
    const socket = new WebSocket('ws://localhost:8080');  // 웹소켓 서버에 연결

    const messagesDiv = document.getElementById('messages');
    const inputField = document.getElementById('input');

    // 서버로부터 메시지를 받을 때
    socket.addEventListener('message', (event) => {
      const newMessage = document.createElement('p');
      newMessage.textContent = event.data;
      messagesDiv.appendChild(newMessage);
    });

    // 메시지 보내기
    inputField.addEventListener('keyup', (event) => {
      if (event.key === 'Enter' && inputField.value) {
        socket.send(inputField.value);  // 서버에 메시지 전송
        inputField.value = '';  // 입력 필드 초기화
      }
    });
  </script>
</body>
</html>

Socket.io

WebSocket 프로토콜 기반으로 하는 JavaScript 라이브러리.

실시간 양방향 통신이 가능한 웹 애플리케이션을 쉽게 만들 수 있도록 도와주며, 웹소켓이 지원되지 않는 환경에서는 HTTP 폴링과 같은 다른 방법으로 연결을 처리할 수 있다.

socket.io 특징

  • 실시간 양방향 통신: 서버와 클라이언트가 동시에 데이터를 주고받을 수 있음
  • 다양한 전송 방법 지원: WebSocket을 사용하지만, WebSocket을 지원하지 않는 환경에서는 폴링(HTTP 기반) 등으로 자동으로 폴백(fallback) 되어 통신할 수 있음
  • 자동 재연결: 연결이 끊기면 자동으로 다시 연결 시도
  • 네임스페이스와 룸: 특정 클라이언트들끼리만 소통할 수 있는 환경 제공
  • 방대한 기능 제공: 메시지 브로드캐스팅, 그룹 채팅, 이벤트 기반 메시지 처리 등 다양한 기능 내장

socket.io 장단점

장점 - 쉽고 빠른 설정: 기본적인 실시간 통신을 빠르게 구현 가능
- 다양한 환경 지원: WebSocket을 지원하지 않는 브라우저에서도 동작 가능
- 확장성: 이벤트 기반 시스템을 통해 복잡한 기능도 손쉽게 추가 가능
단점 - 서버 부하: 연결을 계속 유지하는 방식이어서, 많은 클라이언트를 처리하려면 서버 자원이 많이 필요함
- 상대적으로 높은 오버헤드: WebSocket에 비해 socket.io는 추가적인 기능을 제공하는 만큼 더 많은 리소스를 소모할 수 있음
- 의존성 문제: socket.io 라이브러리를 사용해야 하기 때문에, 기본 WebSocket 기능을 이용하는 것보다 좀 더 복잡할 수 있음

socket.io 사용 전 반드시 알아야하는 개념

기본 개념

  • 소켓 (Socket)
    네트워크 통신을 위한 연결 지점. 클라이언트와 서버 간에 데이터를 주고받기 위한 양방향 채널 제공.
    소켓은 하나의 IP 주소와 포트 번호로 식별되며, 이를 통해 연결된 두 장치 간에 통신을 할 수 있다.
  • 클라이언트 (Client)
    socket.io 클라이언트는 웹 브라우저에서 실행되는 JS 라이브러리로, 서버와의 실시간 연결을 관리한다.
    클라이언트는 이벤트를 서버로 전송하거나, 서버로부터 받은 메시지를 처리할 수 있다.
    이벤트 기반으로 데이터를 주고받으며, 서버와의 연결이 끊어지지 않고 유지된다.
    이 클라이언트는 socket.io-client 라이브러리로 구현된다.
  • 서버 (Server)
    socket.io 서버는 Node.js 서버로, 클라이언트와의 실시간 연결을 관리한다.
    서버는 클라이언트로부터의 연결을 수신하고, 연결 후 이벤트를 발생시키거나 메시지를 전송한다.
    여러 클라이언트를 동시에 처리하며, 클라이언트의 상태를 관리한다.
    서버는 socket.io 라이브러리를 사용하여 구현된다.

트래픽 격리

  • 이벤트 (Event)
    클라이언트와 서버 간의 실시간 통신 단위로, 서로 간에 특정 동작이나 메시지를 전달할 때 사용된다.
    각 이벤트는 특정 이름을 가지고 있어, 해당 이벤트가 발생하면 연결된 다른 클라이언트/서버가 해당 동작을 수행한다.
    socket.emit()을 통해 이벤트를 발생시키고, socket.on()을 통해 이벤트를 수신한다.
  • 네임스페이스 (Namespace)
    클라이언트와 서버 간의 논리적 구분을 의미한다.
    여러 네임스페이스를 생성하여 같은 서버 내에서도 서로 다른 기능을 담당하는 클라이언트들끼리 독립적인 연결을 유지할 수 있다. 예를 들어, /chat 네임스페이스는 채팅 기능을 담당하고, /news 네임스페이스는 뉴스 관련 서비스를 담당할 수 있다. 각 네임스페이스는 독립된 이벤트 처리와 클라이언트 연결을 갖는다.
  • 룸 (Room)
    네임스페이스 내에서 클라이언트들끼리 그룹화하여 소통할 수 있게 해주는 기능.
    하나의 네임스페이스 내에서 여러 개의 방을 만들 수 있으며, 클라이언트는 자유롭게 해당 방에 출입할 수 있다.
    예를 들어, 카톡에서 채팅방에 들어가서 대화하는 것처럼, 각 방마다 독립적인 메시지 흐름을 관리할 수 있다.

이벤트 송수신 방식

  • Public
    모든 클라이언트에게 메시지를 보내는 방식이다.
    특정 클라이언트나 룸에 제한되지 않고, 연결된 모든 클라이언트에게 동일한 메시지를 전송할 수 있다.
    socket.emit()을 통해 이벤트를 전송하면, 연결된 모든 클라이언트가 해당 이벤트를 수신한다.
    예를 들어, 모든 사용자에게 공지사항을 보낼 때 사용된다.
  • Private
    특정 클라이언트에게만 메시지를 보내는 방식이다. 메시지는 오직 지정된 클라이언트만 받을 수 있다.
    socket.emit()을 사용하여 특정 소켓에 이벤트를 전송하고, socket.on()을 사용하여 클라이언트가 이를 수신한다.
    예를 들어, 서버가 "사용자 A가 메시지를 보냈습니다."라는 알림을 특정 사용자에게만 보낼 때 사용된다.
  • Broadcasting
    서버가 특정 클라이언트 제외한 나머지 클라이언트들에게 메시지를 보내는 방법이다.
    예를 들어, 서버에서 새로운 메시지를 보낼 때 자신을 제외한 모든 클라이언트에게 알릴 수 있다.
    socket.broadcast.emit()을 사용하여 자신을 제외한 다른 클라이언트들에게 메시지를 전달한다.
    예시: "사용자 A가 입장하였습니다"라는 메시지를 모든 클라이언트에게 전달하지만, 사용자 A에게는 전달되지 않도록 할 때 유용하다.

socket.io 기본 구조

/* 서버 */
const io = require('socket.io')(3000);

io.on('connection', (socket) => {
  socket.emit('메시지 이름', '실제 출력값');
  // 서버에서 메시지 보내기
});

/* 클라이언트 */
const socket = io('http://localhost:3000');

socket.on('메시지 이름', (변수명) => {
  console.log(변수명);
  // on() 메서드로 서버에서 메시지 받아오기
});

참고한 글

https://inpa.tistory.com/entry/SOCKET-%F0%9F%93%9A-WS-%EC%9B%B9%EC%86%8C%EC%BC%93-%EC%82%AC%EC%9A%A9%ED%95%B4%EB%B3%B4%EA%B8%B0

 

[SOCKET] 📚 WS 웹소켓 사용해보기

WS (Web Socket) [WEB] 🌐 웹 소켓 (Socket) 역사부터 정리 ​ 웹 개발을 처음 배우기 시작했다면 서버와 클라이언트의 통신은 모두 HTTP 프로토콜만 이용해서 이루어진다고 생각할 수 있습니다.

inpa.tistory.com

https://velog.io/@fejigu/Socket.IO-client

 

Socket.IO - client(주요 개념, 작동방식, 트래픽 격리 구분, 이벤트 송수신)

→ Socket.IO는 웹 소켓 연결을 통해 클라이언트와 서버간에 실시간 양방향 통신을 가능하게하는 JavaScript 라이브러리입니다.

velog.io

728x90