Skip to content

WebSocket과 Socket.io에 대해 간단히 알아보기

Hyunjun KIM edited this page Nov 12, 2024 · 1 revision

웹소켓(WebSocket) 이란 무엇일까?

  • 웹소켓(WebSocket)은 웹 브라우저와 서버 간 양방향 통신을 위한 프로토콜
  • 클라이언트가 서버에 처음 연결을 시도할 때는 HTTP 프로토콜을 사용하지만, 연결이 완료되면 HTTP가 아닌 독립적인 프로토콜인 웹소켓을 통해 통신
  • 즉, HTTP ≠ WebSocket. 둘은 TCP 소켓으로 구현되는 독립적인 프로토콜임
  • 웹소켓은 실시간으로 데이터를 주고받아야 하는 애플리케이션(예: 채팅, 게임, 금융 트레이딩 시스템 등)에 적합
  • 웹소켓의 가장 큰 장점은 서버가 클라이언트에게 실시간으로 데이터를 푸시할 수 있다는 점. 오버헤드를 줄여 효율적인 실시간 통신을 가능하게 함.

세부 동작 원리

  • RFC 6455는 웹소켓 프로토콜의 표준 규격을 정의한 문서로, 웹소켓이 초기 핸드셰이크(Handshake) 과정과 메시지 프레임 구조를 설명
  1. 핸드셰이크(Handshake):

    • 웹소켓은 HTTP 프로토콜을 사용하여 연결을 시작. 이 과정에서 클라이언트는 서버에 Upgrade 헤더를 포함하여 웹소켓으로 프로토콜을 업그레이드하도록 요청.

    • 클라이언트의 요청에 응답하여 서버가 101 Switching Protocols 상태 코드를 반환하면, HTTP 연결은 웹소켓 연결로 전환.

    • 클라이언트 요청 예시

      GET /chat HTTP/1.1
      Host: server.example.com
      Upgrade: websocket
      Connection: Upgrade
      Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
      Sec-WebSocket-Version: 13
      
      • Sec-WebSocket-Key는 클라이언트가 서버로 전달하는 랜덤 키로, 서버는 이 키를 바탕으로 Sec-WebSocket-Accept 응답을 생성하여 보안을 확보함.
    • 서버 응답 예시

      HTTP/1.1 101 Switching Protocols
      Upgrade: websocket
      Connection: Upgrade
      Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
      
  2. 프레임 기반 통신:

    • 핸드셰이크가 완료되면, 클라이언트와 서버는 프레임(frame) 단위로 데이터를 주고받음.
    • 프레임 구조에는 메시지의 시작과 끝을 표시하는 비트, 데이터 유형, 마스킹, 그리고 페이로드 데이터(전송할 데이터)가 포함
    • 프레임 구조
      • FIN: 메시지 종료 여부를 나타내는 비트
      • Opcode: 메시지의 유형. 텍스트(1), 바이너리(2), 핑(9), 퐁(10) 등이 있음.
      • Masking Key: 보안상 이유로, 클라이언트에서 서버로 보내는 데이터는 반드시 마스킹이 적용됨.
      • Payload Data: 실제 전송할 메시지의 데이터

실제 프레임 구조

0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len |    Extended payload length    |
|I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
|N|V|V|V|       |S|             |   (if payload len==126/127)   |
| |1|2|3|       |K|             |                               |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
|    Extended payload length continued, if payload len == 127   |
+ - - - - - - - - - - - - - - - +-------------------------------+
|                               | Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued)       |          Payload Data         |
+-------------------------------- - - - - - - - - - - - - - - - +
:                     Payload Data continued ...                :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
|                     Payload Data continued ...                |
+---------------------------------------------------------------+
  • FIN (1 bit): 마지막 프레임 여부
  • RSV1-3 (3 bits): 예약된 비트, 일반적으로 0
  • Opcode (4 bits): 프레임 타입 (0x1: 텍스트, 0x2: 바이너리, 0x8: 연결 종료 등)
  • MASK (1 bit): 페이로드 마스킹 여부
  • Payload length (7 bits + 16/64 bits): 페이로드 길이
  • Masking-key (32 bits): 마스킹에 사용되는 키
  • Payload: 실제 데이터

WebSocket vs. HTTP

특징 HTTP WebSocket
통신 방식 클라이언트가 요청하면 서버가 응답 양방향 통신, 서버에서 클라이언트로 푸시 가능
연결 지속성 요청마다 새로운 연결을 수립 초기 연결 후 지속적 연결 유지
오버헤드 요청마다 헤더 포함 초기 연결 이후에는 헤더 오버헤드 없음
실시간성 서버가 클라이언트로 푸시 불가 실시간 데이터 푸시 가능

ws vs. wss

  • ws://: 보안이 적용되지 않은 웹소켓 연결로, HTTP와 유사한 방식
  • wss://: 보안 웹소켓 연결로, 데이터를 암호화함. HTTPS와 유사하며, SSL/TLS 암호화가 적용

번외) 실시간성 구현을 위한 프로토콜

  1. MQTT (Message Queuing Telemetry Transport): 퍼블리셔/서브스크라이버 구조를 사용하며, 낮은 대역폭에서도 실시간 데이터 전송이 가능하다. IoT 애플리케이션에서 많이 사용된다.
  2. SSE (Server-Sent Events): 서버에서 클라이언트로 데이터를 지속적으로 푸시할 수 있지만, 단방향 통신만 지원한다.
  3. XMPP (Extensible Messaging and Presence Protocol): 메시징과 상태 업데이트가 필요한 실시간 애플리케이션에 사용된다.

https://www.wallarm.com/what/xmpp-vs-websocket-which-to-use-for-applications

Socket.io

Node.js 환경에서 WebSocket 통신을 간편하게 사용할 수 있도록 도와주는 라이브러리

Socket.io는 왜 필요한 것일까?

  • 호환성: 모든 브라우저가 WebSocket을 지원하는 것은 아니며, 네트워크 방화벽이나 프록시가 WebSocket을 차단하는 경우도 있다. 이때, Socket.io는 다양한 폴백 옵션으로 안정적인 통신을 지원한다.
  • 다양한 기능 제공: 재연결, 자동 연결 복구, 네임스페이스, 룸(room) 관리 등 WebSocket 단독으로 구현하기 복잡한 기능을 쉽게 제공한다.
  • 편리한 API: 클라이언트와 서버 모두 간단하게 사용할 수 있는 API를 제공해 실시간 통신 애플리케이션을 쉽게 구축할 수 있다.

주요 기능과 API 소개

  • 네임스페이스: 네임스페이스는 서로 다른 경로로 실시간 통신을 구성할 수 있게 해준다. 예를 들어, /chat, /news와 같은 네임스페이스를 만들어서 채팅과 뉴스 업데이트를 별도로 관리할 수 있다.

    // 서버
    const chat = io.of('/chat');
    const news = io.of('/news');
    
    chat.on('connection', (socket) => {
      console.log('Chat 네임스페이스 연결됨');
    });
    
    news.on('connection', (socket) => {
      console.log('News 네임스페이스 연결됨');
    });
  • 룸(Room): 같은 네임스페이스 내에서도 특정 그룹에만 데이터를 전송할 수 있다. 예를 들어, 특정 채팅방에 속한 사용자에게만 메시지를 전송할 수 있다.

    // 특정 방에 사용자 추가
    socket.join('room1');
    // 특정 방에 있는 사용자에게만 메시지 전송
    io.to('room1').emit('message', '이 메시지는 room1에만 전달됨');
  • 이벤트 기반 통신: Socket.io는 이벤트 기반으로 통신이 이루어진다. 서버와 클라이언트는 서로 이벤트를 정의하고 해당 이벤트가 발생할 때 데이터를 전송할 수 있다.

    // 서버에서 이벤트 정의
    socket.on('chat message', (msg) => {
      console.log('메시지 수신:', msg);
      io.emit('chat message', msg);
    });
    
    // 클라이언트에서 이벤트 트리거
    socket.emit('chat message', 'Hello, world!');
  • 이벤트 미들웨어

    // 서버 측 미들웨어 예시
    io.use((socket, next) => {
        // 인증 미들웨어
        const token = socket.handshake.auth.token;
        verifyToken(token)
            .then(user => {
                socket.user = user;
                next();
            })
            .catch(err => next(new Error('Authentication error')));
    });
    
    // 특정 이벤트에 대한 미들웨어
    socket.use(([event, ...args], next) => {
        // 이벤트 로깅
        console.log(`Event: ${event}`, args);
        next();
    });
    
    // nest는 기존 데코레이터를 활용하면 됨
  • 휘발성 메시지와 신뢰성 메시지

    // 휘발성 메시지 전송
    socket.volatile.emit('position', { x: 10, y: 20 });
    
    // 신뢰성 있는 메시지 전송 (기본값)
    socket.emit('important', { data: 'must be delivered' }, (ack) => {
        if (ack) {
            console.log('메시지가 성공적으로 전달됨');
        }
    });
  • 재연결: Socket.io는 연결이 끊어졌을 때 자동으로 다시 연결을 시도한다. 개발자는 별도로 신경 쓸 필요 없이 안정적인 연결을 유지할 수 있다.

  • Redis 붙여서 웹소켓만을 위한 수평적 확장도 가능

  • 클러스터링 / 배치 처리 / 디바운싱도 가능

개발 문서

⚓️ 사용자 피드백과 버그 기록
👷🏻 기술적 도전
📖 위키와 학습정리
🚧 트러블슈팅

팀 문화

🧸 팀원 소개
⛺️ 그라운드 룰
🍞 커밋 컨벤션
🧈 이슈, PR 컨벤션
🥞 브랜치 전략

그룹 기록

📢 발표 자료
🌤️ 데일리 스크럼
📑 회의록
🏖️ 그룹 회고
🚸 멘토링 일지
Clone this wiki locally