서론
프로젝트를 진행하다보면 단순 HTTP를 통한 API 구현이 아닌 웹소켓을 통한 구현이 필요한 기능들이 있다.
그 기능들로는 실시간 채팅 앱, 실시간 알림 시스템, 실시간 주식/코인 가격, 실시간 협업 툴(노션)등이 있다.
본인의 경우 웹소켓 연결을 통해 실시간 주식 가격을 차트에 보여주거나 가격을 보여준 경험이 있다.
해당 프로젝트를 진행할 때, 웹소켓에 대한 이해를 제대로 하지 못한채로 주먹구구식으로 기능구현에만 관심이 치우쳤던 것 같다.
이번 기회에 웹소켓에 대해 제대로 이해해보려한다.
WebSocket과 HTTP
어째서 위에서 언급한 실시간과 관련된 기능들은 우리가 주로 사용하는 HTTP를 통해 구현할 수 없는 것일까?
HTTP
HTTP의 특성으로 요청-응답을 기반으로 클라이언트가 요청을 보내야 서버가 응답하고, 무상태성을 가진다고 하는데
여기서 HTTP의 무상태성이란 각 요청은 독립적이기에 이전 요청에 대한 정보를 기억하지 않는다.
그래서 댓글 작성 같은경우 매번 서버는 요청만을 보고 응답을 만들어낸다. 이전에 어떤 요청을 했는지 요청하는 사용자가 어떤 상태인지를 알 수 없다.
그래서 상태라는 개념은 없지만 상태를 유지하고자 쿠키, 세션, JWT를 통해 HTTP로 이전 요청에 연관된 요청을 보내야하는 이슈를 해결한다.
WEBSOCEKT
웹소켓은 양방향 통신으로 상태유지가 가능하기에 위에서 말한 실시간 채팅, 주식 시세 등 요청이 가능한 것이다.
WebSocket의 경우 초기 연결은 HTTP로 시작해 Upgrade 헤더를 통해 WebSocket 프로토콜 전환을 요청한다.
서버가 이를 승인한다면 그때부터 WebSocket연결이 수립된다. 이때부터는 Websocket프로토콜로 전환되어 양방향 지속적 통신이 가능해진다.
WebSocket 구현
먼저 서버쪽 코드부터 보겠다. 강의에서 pug와 express 그리고 자체 제공하는 ws의 WebSocket을 사용했다.
import express from "express";
import http from "http";
import WebSocket from "ws";
const app = express();
// HTTP 서버 생성 (Express를 바탕으로)
const server = http.createServer(app);
// WebSocket 서버 생성, HTTP 서버와 함께 사용
const wss = new WebSocket.Server({ server });
// WebSocket 연결이 이루어졌을 때의 콜백
wss.on("connection", (socket) => {
// 클라이언트 연결이 끊겼을 때 실행
socket.on("close", () => console.log("Disconnected from the browser"));
// 클라이언트로부터 메시지를 받았을 때 실행
socket.on("message", (message) => {
console.log(message.toString()); // 메시지는 Buffer 형태로 오기 때문에 toString()
});
// 연결되자마자 클라이언트에게 메시지 보내기
socket.send("hello!");
});
server.listen(3000, handleListen);
1. Express 앱을 HTTP서버에 연결하고, HTTP서버를 웹소켓 서버와 같은 포트를 통해 처리하도록 했다.
2. 생성된 wss 웹소켓 서버를 통해 클라이언트의 접속을 감지 및 다양한 상태를 처리한다.
3. 그다음은 연결이 이루어진 경우 socket.on을 통해 close, message를 선언해 각 상황별 어떤 콜백함수가 실행되어야하는지 명시해두었다.
클라이언트 쪽 코드는 다음과 같다.
// 현재 페이지의 호스트를 기준으로 WebSocket 연결 생성
const socket = new WebSocket(`ws://${window.location.host}`);
// 서버에 연결되었을 때 실행
socket.addEventListener("open", () => {
console.log("Connected to Server");
});
// 서버에서 메시지를 받을 때 실행
socket.addEventListener("message", (message) => {
console.log("New message: ", message);
});
// 서버와의 연결이 끊겼을 때 실행
socket.addEventListener("close", () => {
console.log("Disconnected from Server");
});
// 연결된 후 100ms 후에 메시지를 서버로 전송
setTimeout(() => {
socket.send("hello from browser");
}, 100);
클라이언트의 경우 브라우저를 통해 Websocket서버에 연결을 하고, 생성된 socket을 통해 서버쪽과 유사하게, socket.addEventListener을 통해 연결된 경우, 끊기는 경우 등 상황별 실행될 콜백함수를 지정해 두었다.
마지막으로 웹소켓과 HTTP의 차이를 간단히 정리해보았다.
HTTP | WebSocket | |
통신 방식 | 단방향 (Request → Response) | 양방향 (Full Duplex) |
연결 방식 | 매 요청마다 새 연결 | 한 번 연결되면 계속 유지 |
프로토콜 | http://, https:// | ws://, wss:// |
지속성 | 비연결형 (Stateless) | 연결형 (Persistent) |
서버 → 클라이언트 메시지 전송 | 불가능 (폴링 필요) | 가능 (언제든 push) |
용도 | 문서, API 요청 등 | 채팅, 실시간 게임, 주식 차트 등 |
헤더 | 많은 헤더 포함 (오버헤드 큼) | 초기 요청만 헤더, 이후 가볍고 빠름 |
기반 | TCP 위에서 HTTP 프로토콜 사용 | TCP 위에서 WebSocket 프로토콜 사용 |
줌 클론코딩 – 노마드 코더 Nomad Coders
WebSockets, SocketIO, WebRTC
nomadcoders.co
https://yozm.wishket.com/magazine/detail/1911/
웹소켓으로 개발하기 전 알아야 할 것들 | 요즘IT
웹소켓(Web Socket) 프로토콜은 HTTP와는 다른 통신 프로토콜로 웹 서버와 웹 브라우저가 서로 실시간 메시지를 교환하는 데에 사용된다. 최근 웹소켓을 활용해 소규모 메타버스 서비스를 개발하는
yozm.wishket.com
'코딩' 카테고리의 다른 글
Tailwind 4.0 새로워진 점 (0) | 2025.04.16 |
---|---|
Tailwind V4.1 달라진 점 (0) | 2025.04.10 |
Tailwind V 4.0 config.js 어디로? (2) | 2025.04.08 |
불변객체와 순수 컴포넌트 (0) | 2025.03.29 |
엔터 이벤트가 두 번 발생하는 경우 (0) | 2025.02.28 |