WebSocket

2024. 7. 30. 12:13·TIL(Today I Learned)

WebSocket은 무엇인가

클라이언트와 서버 간의지속적인 전이중 연결을 제공하는 통신 프로토콜입니다. HTTP 프로토콜과 달리, WebSocket은 한번 연결이 설정되면 양방향으로 데이터를 자유롭게 교환할 수 있습니다. 이는 실시간 업데이트와 즉각적인 데이터 전송을 필요로 하는 애츨리케이션에 이상적입니다.

WebSocket의 원리

OSI 7계층과 WebSocket

OSI 모델은 네트워크 통신을 7계층으로 나눈 모델입니다. WebSocket은 주로 전송계층(TCP)과 응용계층(HTTP/HTTPS)에서 작동합니다. 초기 연결설정은 HTTP/HTTPS 프로토콜을 통해 이루어지고, 연결이 설정되면 전송계층의 TCP를 통해 양방향 통신이 이루어집니다.

참고: https://kellis.tistory.com/65

 

WebSocket의 동작 원리

  1. 핸드쉐이크: 클라이언트는 HTTP 요청을 사용하여 서버에 WebSocket 연결을 요청합니다.
  2. 프로토콜 업그레이드: 서버는 연결 요청을 수락하고, HTTP 프로토콜에서 WebSocket 프로토콜로 업그레이드 합니다.
  3. 양방향 통신: 연결이 설정되면 클라이언트와 서버는 양방향 통신을 수행할 수 있습니다. 이는 풀 이중(Full-Duplex) 통신을 의미합니다.
  4. 데이터 전송: 클라이언트와 서버는 테그스 또는 바이너리 데이터를 프레임 형태로 교환합니다.

 

WebSocket의 초기 연결 설정(HTTP 핸드쉐이크)

1. 클라이언트 요청

클라이언트는 HTTP 요청을 사용하여 WebSocket 연결을 요청합니다. 이 요청은 특별한 Upgrade 헤더를 포함하여 서버에 WebSocket 연결을 요청하는데, 이는 HTTP 1.1 프로토콜을 사용합니다.

  • Upgrade: websocket: HTTP 프로토콜을 WebSocket 프로토콜로 업그레이드하도록 요청
  • Connection: Upgrade: 연결을 업그레이드할 것을 명시
  • Sec-WebSocket-Key: 클라이언트가 생성한 랜덤 키로, 서버는 이 키를 기반으로 응답 키를 생성합니다.
  • Sec-WebSocket-Version: 클라이언트가 지원하는 WebSocket 프로토콜의 버전을 명시

2. 서버 응답

서버는 클라이언트의 요청을 수락하고, HTTP 응답을 통해 WebSocket 연결을 설정합니다.

  • 101 Switching Protocols: HTTP 상태 코드로, 프로토콜을 WebSocket으로 전환하고 있음을 나타냅니다.
  • Upgrade: websocket: 프로토콜을 WebSocket으로 업그레이드한다는 것을 명시
  • Connection: Upgrade: 연결이 업그레이드된다는 것을 명시
  • Sec-WebSocket-Accept: 서버가 클라이언트의 Sec-WebSocket-Key를 기반으로 생성한 응답 키로, 클라이언트는 이를 검증하여 연결이 성공적으로 설정되었는지 확인합니다.

3. WebSocket 데이터 전송 (WebSocket 프로토콜)

초기 연결이 설정되면, WebSocket 프로토콜로 전환되어 양방향 통신이 가능해집니다. 이 단계에서는 HTTP가 더이상 사용되지 않으며, WebSocket 프레임을 사용하여 데이터를 주고받습니다.

  • 프레임 구조: WebSocket은 데이터 전송을 위해 프레임을 사용합니다. 각 프레임은 데이터의 유형(텍스트, 바이너리 등), 길이, 데이터 자체 등을 포함합니다.
  • 양방향 통신: 클라이언트와 서버는 동일한 연결을 통해 주유롭게 데이터를 주고받을 수 있습니다. 이는 풀 이중(Full-Duplex)통신을 가능하게 합니다.

 

 WebSocket 예시

클라이언트 측

const socket = new WebSocket('ws://example.com/socket');

socket.onopen = function(event) {
  console.log('Connected to the WebSocket server');
  socket.send('Hello Server!');
};

socket.onmessage = function(event) {
  console.log('Received message from server: ', event.data);
};

socket.onclose = function(event) {
  console.log('WebSocket connection closed');
};

socket.onerror = function(error) {
  console.error('WebSocket error: ', error);
};

 

서버측

const WebSocket = require('ws');

const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', function(socket) {
  console.log('Client connected');

  socket.on('message', function(message) {
    console.log('Received message from client: ', message);
    socket.send('Hello Client!');
  });

  socket.on('close', function() {
    console.log('Client disconnected');
  });
});

 

y-websocket은 무엇인가

Yjs는 실시간 협업을 가능하게 하는 Javascript 라이브러리입니다. Yjs는 CRDT(Conflit-free-Replicated Data Type)을 기반으로 하여 여러 사용자가 동시에 문서를 편집할 수 있도록 합니다. y-websocket은 Yjs와 함께 사용되는 WebSocket 프로바이더로, 여러 클라이언트 간의 상태 동기화를 관리합니다.

 

y-websocket의 기능

  • 실시간 협업: 여러 클라이언트가 동시에 문서를 편집할 수 있으며, 각 클라이언트의 변경 사항이 즉시 다른 클라이언트에 반영됩니다.
  • 자동 병합: Yjs는 CRDT 알고리즘을 사용하여 충돌 없이 데이터 병합을 처리합니다.
  • 쉽고 효율적: y-websocket을 사용하면 WebSocket을 통해 Yjs 문서를 쉽게 동기화 할 수 있습니다.

y-websocket의 예시

클라이언트 측

import * as Y from 'yjs';
import { WebsocketProvider } from 'y-websocket';

// Yjs 문서를 생성
const ydoc = new Y.Doc();

// WebSocket 서버에 연결
const provider = new WebSocketProvider('wss://demos.yjs.dev', 'my-roomname', ydoc);

// Yjs의 텍스트 타입을 생성합니다.
const ytext = ydoc.getText('my-text');

// 텍스트 변경 사항을 처리하는 이벤트 리스너를 추가합니다.
ytext.observe(event => {
	console.log('텍스트 변경:', ytext.toString());
});

// 텍스트를 변경합니다.
ytext.insert(0, 'Hello, Yjs!');

이 예제는 Yjs 문서를 생성하고, y-websocket을 통해 서버에 연결한 후, 텍스트를 변경하고 이를 실시간으로 동기화하는 기본적인 흐름을 보여줍니다.

 

서버 측

y-websocket은 클라이언트 측 라이브러리이므로, 서버 측에서는 WebSocket 서버를 구현하고 이를 y-websocket과 연결하여 사용해야 합니다.

const WebSocket = require('ws');
const http = require('http');
const { setupWSConnection } = require('y-websocket/bin/utils');

const port = 1234;
const server = http.createServer();
const wss = new WebSocket.Server({ server });

wss.on('connection', (ws, req) => {
  setupWSConnection(ws, req);
});

server.listen(port, () => {
  console.log(`WebSocket server is running on port ${port}`);
});

'TIL(Today I Learned)' 카테고리의 다른 글

[git] rebase  (0) 2024.07.24
[JS]전역객체와 Node객체  (0) 2023.03.19
React에서 함수형 컴포넌트를 장려하는 이유  (0) 2023.03.15
[예외 처리3]new Error() vs new Promise.reject()  (0) 2023.03.11
[예외발생2]Error() vs new Error()  (0) 2023.03.11
'TIL(Today I Learned)' 카테고리의 다른 글
  • [git] rebase
  • [JS]전역객체와 Node객체
  • React에서 함수형 컴포넌트를 장려하는 이유
  • [예외 처리3]new Error() vs new Promise.reject()
JoyYellow
JoyYellow
  • JoyYellow
    JoyYellow
    JoyYellow
  • 전체
    오늘
    어제
    • 분류 전체보기 (128)
      • Vue (7)
      • React (10)
      • 알고리즘 풀이 (29)
      • 타입스크립트 (2)
      • Microsoft (4)
      • TIL(Today I Learned) (16)
      • Devops (4)
      • CS(Computer Science) (2)
      • Spring (1)
      • Incomplete (0)
      • JS소스모듈 (10)
      • TDD (2)
      • 스프링부트 (0)
      • CSS (8)
      • Next.js (0)
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    노마드코더
    개발자북클럽
    노개북
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
JoyYellow
WebSocket
상단으로

티스토리툴바