실시간 채팅, 실시간 업데이트 등을 구현할 때 서버와 클라이언트 간 실시간 소통을 위해 WebSocket 또는 Socket.IO를 사용한다.
일반적인 HTTP 프로토콜은 클라이언트가 서버로 요청을 보냈을 때, 서버가 그 요청에 응답하는 구조다.
클라이언트의 요청 없이는 서버에서 클라이언트로 데이터를 전송할 수 없다.
하지만 WebSocket과 Socket.IO는 클라이언트와 서버 간에 한 번 연결이 성사되면 클라이언트의 요청 없이도 서버가 아무 때나 클라이언트로 데이터를 전송할 수 있다.
그렇다면 WebSocket과 Socket.IO는 뭐가 다를까?
웹소켓은 특수 프로토콜 wss
를 사용해 연결을 생성할 수 있다.
ws
프로토콜도 있는데, 이를 사용하면 암호화되지 않은 패킷이 전송되므로 반드시 wss
를 쓰는 것을 권장한다.
통신은 on
, send
, close
메서드를 기반으로 이루어진다.
on
메서드의 'connection' 이벤트를 통해 소켓을 열고, 'message' 이벤트의 콜백으로 데이터를 받는다.
전달하는 객체의 키값으로 데이터를 구분해야 한다.
// back
import { WebSocketServer } from "ws";
const server = new WebSocketServer({ port: 3000 });
// 웹소켓 서버 실행
server.on("connection", (socket) => {
// 클라이언트로 메세지 전송
socket.send(JSON.stringify({
type: "hello from server",
content: [ 1, "2" ]
}));
// 클라이언트로부터 메세지 수신
socket.on("message", (data) => {
const packet = JSON.parse(data);
switch (packet.type) {
case "hello from client":
// ...
break;
}
});
});
// front
const socket = new WebSocket("ws://localhost:3000");
socket.addEventListener("open", () => {
// 서버로 메세지 전송
socket.send(JSON.stringify({
type: "hello from client",
content: [ 3, "4" ]
}));
});
// 서버로부터 메세지 수신
socket.addEventListener("message", ({ data }) => {
const packet = JSON.parse(data);
switch (packet.type) {
case "hello from server":
// ...
break;
}
});
Socket IO는 Web Socket을 부분적으로 사용하는 프레임워크다.
프로토콜이 아닌, 프레임워크다.
여러 통신 기술들을 쉽게 사용할 수 있게 해주는 프레임워크다.
Web Socket과 달리 브라우저, 디바이스에 상관 없이 모든 환경에서 양방향 실시간 통신이 가능하다.
브라우저가 Web Socket을 지원할 경우 Web Socket을 사용하고,
지원하지 않을 경우 HTTP Long Polling 등 기타 통신을 지원한다.
또한, 연결이 끊길 경우에도 자동으로 재연결을 시도한다.
// back
import { Server } from "socket.io";
const io = new Server(3000);
io.on("connection", (socket) => {
// send a message to the client
socket.emit("hello from server", 1, "2", { 3: Buffer.from([4]) });
// receive a message from the client
socket.on("hello from client", (...args) => {
// ...
});
});
// front
import { io } from "socket.io-client";
const socket = io("ws://localhost:3000");
// send a message to the server
socket.emit("hello from client", 5, "6", { 7: Uint8Array.from([8]) });
// receive a message from the server
socket.on("hello from server", (...args) => {
// ...
});
WebSocket에서는 "message"이벤트를 통해서만 데이터를 주고받을 수 있었다.
하지만 Socket IO는 사용자 정의 이름의 이벤트를 발생시키고, 매개변수 또한 갯수와 타입에 관계없이 주고받을 수 있다.
참고 자료
🎥 https://nomadcoders.co/noom/lectures/3099
📄 https://socket.io/docs/v4/
📄 https://ko.javascript.info/websocket