✨WebSocket이란?
웹 애플리케이션에서 클라이언트와 서버 간의 상호작용을 실시간으로 처리할 수 있게 해주는 통신 프로토콜
기존의 HTTP와 비교할 때, WebSocket은 양방향 통신을 지원하고, 더 낮은 지연시간으로 데이터를 주고받을 수 있어
실시간 데이터 전송에 매우 적합합니다.
✨WebSocket vs HTTP
통신방식
HTTP
- 요청-응답 모델
- HTTP는 클라이언트가 서버에 요청을 보내고, 서버가 이에 대한 응답을 보내는 요청-응답 모델을 따른다.
- 각 요청마다 새로운 연결을 맺고 끊기 때문에, 많은 요청을 처리할 때 오버헤드가 발생할 수 있다.
- 단방향 통신
- 클라이언트가 요청을 보내기 전까지는 서버가 클라이언트에 데이터를 보낼 수 없다.
- 즉, 서버에서 클라이언트로의 데이터 전송이 제한적이다.
WebSocket
- 양방향 통신
- WebSocket은 클라이언트와 서버가 양방향으로 데이터를 주고받을 수 있는 지속적인 연결을 제공한다.
- 초기 핸드셰이크 과정 이후, 동일한 연결을 통해 양방향 통신이 가능하다.
- 지속적 연결
- 연결이 되면 클라이언트와 서버는 지속적으로 데이터를 주고받을 수 있고 HTTP와 달리 매번 새로운 연결을 설정하지 않아도 된다.
성능과 효율성
HTTP
- 높은 오버헤드
- 매 요청마다 새로운 TCP 연결을 설정하고 끊는 과정에서 오버헤드가 발생한다.
특히, 실시간 데이터 전송이 필요한 애플리케이션에서는 비효율적!!! - 헤더 데이터
- 각 요청마다 HTTP 헤더를 포함하여 데이터를 전송하기 때문에, 작은 데이터 전송에도 불필요한 정보가 추가된다.
WebSocket
- 낮은 오버헤드
초기 연결 설정 이후에는 지속적으로 데이터를 주고받을 수 있기 때문에, 연결 설정에 대한 오버헤드가 줄어든다. - 헤더 최소화
핸드셰이크 이후에는 데이터 프레임의 헤더가 최소화되어 있어, 데이터 전송의 효율성이 높다.
사용하는 곳
HTTP
정적 콘텐츠을 제공하거나 요청-응답 기반의 데이터 전송이 주로 필요할 때 사용한다.
클라이언트가 서버에 요청을 보내고, 서버가 응답하는 구조로 설계된 애플리케이션에서 사용한다. = RESTful API
WebSocket
채팅, 게임, 라이브 등 실시간 데이터 전송이 필요한 애플리케이션에서 사용된다.
실시간 알림의 경우 서버에서 클라이언트로 실시간 알림을 전송해야하기에 사용된다.
✨WebSocket을 이용한 서버와 통신 [ feat. NodeJs ]
시작하기 전 해야할 설정
- folder 생성 후 vsc코드로 해당 폴더를 열기
- npm init -y
- npm i nodemon -D
- babel.config.json 생성 후 다음과 같은 내용 추가
{ "presets": ["@babel/preset-env"] } - src 생성하기 + server.js만들기
- git init . 후 bable설치
npm i @babel/core -D npm i @babel/cli -D npm i @babel/node -D - nodemon.json 생성 후 추가
{ "ignore":["src/public/*"], //서버가 바뀔때만 새로고침하도록 함 "exec" : "babel-node src/server.js" //server.js에 대해 babel-node 명령문 실행 }
- npm i @babel/preset-env -D 실행
- package.json에 "scripts":{ "dev": "nodemon" } 추가
- npm i express
- npm i pug
- 다음과 같은 구조를 가지도록 public/js/app.js, views/home.pug 생성하기

핵심코드
<!-- home.pug -->
doctype html
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title Zoome Clone
link(rel="stylesheet" href="https://unpkg.com/mvp.css")
body
script(src="../public/js/app.js")
//server.js
import http from "http";
import WebSocket from "ws";
import express from "express";
const app = express();
const PORT = 3000;
app.set("view engine", "pug");
app.set("views",__dirname+"/views");
//유저가 볼 수 있는 폴더를 따로 지정 --> 서버코드를 보이지않게해 보안상 단점을 극복
app.use('/public', express.static(__dirname + '/public'));
app.get("/",(req,res)=>res.render("home"));
app.get("/*",(req,res)=>res.redirect("/"));
const handleListen = () =>{
console.log(`Server Listening...: : http://localhost:${PORT}`)
}
//서버 생성
const server = http.createServer(app);
const wss = new WebSocket.Server({server});
//연결하기
wss.on("connection",(socket)=>{
console.log("Connected To Browser");
//socket에서 제공하는 메서드로 wss아님
//연결이 끊겼을 때
socket.on("close",()=>{console.log("Disconnected To Browser");});
//브라우저로부터 메세지가 왔을 때
socket.on("message",(message)=>{
console.log(message.toString('utf8'));
})
//브라우저로 메세지 보내기
socket.send("Hello~"); // -> message event
});
server.listen(3000,handleListen);
//app.js
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.data," from the Server")
})
//서버와 연결이 끊겼을 때
socket.addEventListener("close",()=>{
console.log("Disconnected From Server");
})
//서버로 메세지 보내기
setTimeout(()=>{
socket.send("Hello from the browser");
},5000);
실행결과

