Post

(TIL) 2024-12-09

웹 소켓


웹 소켓은 클라이언트와 서버 간의 지속적인 연결을 제공하는 프로토콜이며 양방향 통신이 가능하다. HTTP는 클라이언트의 요청(Request)에 의해 서버는 응답(Response)을 하는 단방향 통신이다.
채팅 프로그램 기준으로 A사용자와 B사용자가 있다고 가정해보자. A사용자가 B사용자에게 메세지를 보낸 후 B사용자는 A사용자의 메세지를 알기 위해서는 서버에 요청을 하여 전달 받아야 한다. 그런데 이걸 실시간으로 하게 된다면 양쪽에서 지속적으로 서버에 요청하여 추가로 전달되는 메세지가 있는지를 요청을 해야만 응답을 받을 수 있다. 초단위로 어떤 데이터나 리소스가 변경되는 서비스라면 무의미하다고는 볼 수 없겠지만 전혀 그렇지 않은 서비스인 경우엔 비효율적이다. 이를 위해 사용되는 것이 웹 소켓 프로토콜이다.

사용 사례: 실시간 채팅 애플리케이션(Discord),실시간 데이터 시각화(주식 시장),멀티플레이어 게임,알림 서비스 등

웹소켓과 HTTP 비교

특성HTTPWebSocket
연결 방식요청/응답 반복지속 연결
데이터 흐름단방향 (Client → Server)양방향 (Full-duplex)
프로토콜 오버헤드높음낮음
주요 사용 사례정적 웹 페이지, API 호출실시간 데이터, 채팅, 알림

즉 HTTP의 한계를 극복하고 지속적인 연결을 제공하여, 실시간 데이터를 처리하는 데 유리

특징

  1. 양방향 통신 (Full-duplex) 클라이언트와 서버가 동시에 메시지를 주고받을 수 있다. 채팅 애플리케이션에서 클라이언트가 메시지를 보내는 동시에 서버에서도 새 메시지를 보낼 수 있다.

  2. 지속적인 연결 (Persistent Connection) 웹소켓은 초기 핸드셰이크(HTTP 요청 기반)를 통해 연결을 설정한 후, 지속적으로 연결된 상태를 유지한다. HTTP처럼 요청/응답을 반복하지 않아 네트워크 오버헤드가 줄어든다.

  3. 경량 메시징 (Lightweight Messaging) 웹소켓은 텍스트 또는 바이너리 데이터를 송수신할 수 있으며, HTTP 헤더와 같은 부가적인 데이터가 없어 효율적이다

  4. 이벤트 기반 프로토콜 메시지 전송, 연결 열기/닫기 등 다양한 이벤트를 처리할 수 있는 API를 제공한다.

동작 원리

  1. 핸드셰이크: 클라이언트는 서버에 HTTP 요청을 보내어 웹소켓 연결을 요청. 서버는 HTTP 101 응답을 보내며 연결을 업그레이드.
  2. 연결 설정 후: 웹소켓 연결이 열리면, 클라이언트와 서버는 데이터를 자유롭게 주고받을 수 있음.
  3. 연결 종료: 클라이언트나 서버에서 연결 종료 요청을 보내면 연결이 닫힘.

장점 단점

  1. 장점
    • 실시간 통신 가능
    • 네트워크 효율성 (오버헤드 감소)
    • 다용도 API (텍스트/바이너리 데이터)
  2. 단점
    • HTTP보다 복잡한 설정
    • 연결 유지 비용 발생
    • 브라우저와 서버 모두 지원 필요

서버코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
```javascript
import express from 'express';
import { createServer } from 'http';
import { Server as SocketIO } from 'socket.io';
import initSocket from './init/socket.js';

const app = express();
const server = createServer(app);

const PORT = 3000;

app.use(express.json());
app.use(express.urlencoded({ extended: false }));

const initSocket = (server) => {
  const io = new SocketIO();
  io.attach(server);

  // 서버 수신
  io.on('chat-message', (data) => {
    // 서버 발신
    io.emit('chat-message', { id: socket.id, msg: data });
  });

  // 클라이언트 발신
  socket.emit('chat-message', message); // 서버로 메시지 전송

  // 클라이언트 수신
  socket.on('chat-message', ({ id, msg }) => {
    // ... 비즈니스 로직
  };
};

app.get('/', (req, res) => {
  res.send('<h1>Hello World</h1>');
});

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

결론

웹소켓은 실시간 양방향 통신을 필요로 하는 애플리케이션에서 필수적인 기술이다. 효율적이고 빠른 데이터 전송을 제공하며 실시간 서비스 개발에 매우 적합하지만 보안과 서버 자원 관리에 주의하며 사용해야 한다.

This post is licensed under CC BY 4.0 by the author.