1. 웹소켓(WebSocket) 자세히 알아보기
✅ 기존 HTTP 방식 vs. 웹소켓 방식
기존 HTTP 요청-응답 방식:
- 클라이언트(브라우저)가 요청을 보내야 서버가 응답을 보냄.
- 서버가 먼저 클라이언트에게 말 걸 수 없음.
- 실시간으로 데이터를 받아야 하면, 주기적으로 요청을 보내야 함(Polling) → 비효율적!
웹소켓 방식:
- 클라이언트와 서버가 한 번 연결되면 유지됨.
- 서버도 원할 때 클라이언트에게 데이터를 보낼 수 있음.
- 클라이언트도 서버에 항상 요청을 보내지 않아도 됨.
✅ 웹소켓이 필요한 이유
웹소켓이 유용한 대표적인 경우들:
- 실시간 채팅 → 메시지를 바로바로 주고받아야 함.
- 알림 시스템 → 친구 요청, 댓글 알림 등 즉시 전달.
- 주식, 환율 차트 → 가격 변동을 실시간으로 보여줌.
- 온라인 게임 → 플레이어들의 상태가 실시간으로 동기화돼야 함.
📌 즉, "서버가 클라이언트에게 즉시 데이터를 보내야 하는 경우" 웹소켓이 필요함!
2. 웹소켓에서 Redis가 필요한 이유
✅ 웹소켓 연결 방식
웹소켓은 연결될 때 각 서버의 메모리에 연결 정보를 저장해.
예를 들어, 서버가 하나라면:
- 사용자가 웹소켓에 연결됨 (ws://server.com)
- 해당 서버가 사용자의 웹소켓 연결을 메모리에 저장.
- 다른 사용자가 메시지를 보내면, 서버가 바로 해당 연결을 찾아 메시지를 전달.
➡️ 문제 없음.
✅ 서버가 여러 개일 때 문제 발생!
만약 웹소켓 서버가 여러 개면?
- A 사용자가 서버 1에 연결됨.
- B 사용자가 서버 2에 연결됨.
- A가 B에게 메시지를 보내면?
이렇게 서버가 여러 개면, 웹소켓 연결 정보가 분산되어 서로 알 수가 없게 됨.
➡️ 해결책: Redis를 사용해 서버 간 소통을 하자!
✅ Redis가 어떻게 해결해 줄까?
Redis는 "Pub/Sub(발행-구독)" 기능을 제공한다.
💡 Pub/Sub(발행-구독) 개념
- 각 웹소켓 서버는 Redis의 특정 채널을 구독(Subscribe)
- 어떤 서버에서든 메시지를 Redis 채널에 발행(Publish)
- 모든 서버가 이 메시지를 받아서 해당 클라이언트에 전달
📌 결과:
- 서버가 여러 개여도 문제 없이 메시지가 전달됨!
- Redis가 웹소켓 서버들 간의 브로커 역할을 해줌.
✅ 실제 동작 방식 예제
- A 사용자가 서버 1에 웹소켓 연결
- B 사용자가 서버 2에 웹소켓 연결
- A가 B에게 메시지를 보냄 → 서버 1에서 처리
- 서버 1이 Redis 채널에 "B에게 메시지"를 Publish
- 서버 2가 Redis 채널을 구독하고 있다가 메시지 수신
- 서버 2가 B에게 웹소켓으로 메시지 전달
➡️ Redis 덕분에 서로 다른 서버에 연결된 사용자끼리도 문제없이 소통 가능!
3. 웹소켓과 동기/비동기의 관계
✅ 동기(Synchronous) vs. 비동기(Asynchronous)
- 동기 방식: 요청을 보내고 응답이 올 때까지 기다림.
- 예) console.log(1); alert("Hello"); console.log(2); → alert가 끝나야 console.log(2); 실행됨.
- 비동기 방식: 요청을 보내고 기다리지 않고 다른 작업 수행, 나중에 응답 처리.
- 예) setTimeout(() => console.log("Hello"), 1000); console.log("World");
- 먼저 "World" 출력되고, 1초 후 "Hello" 출력됨.
✅ 웹소켓이 비동기적으로 동작하는 이유
웹소켓이 실시간으로 데이터를 주고받으려면, 요청을 보낸다고 멈춰 있으면 안 됨!
- 서버는 항상 클라이언트에게 새로운 메시지가 올지 모르는 상태
- 만약 동기 방식이면 → 클라이언트가 응답을 받을 때까지 기다려야 해서 비효율적
- 비동기 방식이면 → 클라이언트가 요청을 보내지 않아도 서버에서 바로 메시지 전송 가능
📌 즉, 웹소켓은 기본적으로 비동기 이벤트 기반(Event-driven)으로 동작해야 실시간 처리가 가능함! (클라이언트와 서버가 메시지를 주고받을 때, 기다리지 않고 이벤트가 발생하면 처리함.)
const socket = new WebSocket("ws://localhost:8080");
// 웹소켓 연결이 열리면 실행되는 이벤트
socket.onopen = () => {
console.log("웹소켓 연결 성공!");
socket.send("안녕, 서버!");
};
// 서버에서 메시지를 받으면 실행되는 이벤트
socket.onmessage = (event) => {
console.log("서버에서 받은 메시지:", event.data);
};
// 웹소켓이 닫히면 실행되는 이벤트
socket.onclose = () => {
console.log("웹소켓 연결 종료");
};
- onopen: 연결이 완료되면 실행
- onmessage: 메시지를 받으면 실행
- onclose: 연결이 끊어지면 실행
즉, 웹소켓은 클라이언트가 요청을 보낸 후 응답을 기다리는 것이 아니라, 서버에서 메시지가 오면 자동으로 실행됨(비동기 이벤트 기반).
📌 즉, 웹소켓은 비동기 방식으로 동작하기 때문에 실시간 데이터 전송이 가능함!
1️⃣ 웹소켓은 서버와 클라이언트가 실시간으로 양방향 통신하는 프로토콜.
- HTTP보다 빠르고, 서버에서 클라이언트에게 직접 메시지를 보낼 수 있음.
- 실시간 채팅, 알림, 주식 차트, 온라인 게임 등에 활용됨.
2️⃣ Redis는 여러 웹소켓 서버가 메시지를 공유하도록 도와줌.
- 서버가 여러 개일 때, 각 서버가 모든 클라이언트의 연결을 알지 못함.
- Redis의 Pub/Sub 기능을 이용하면, 서버 간 메시지 공유 가능!
3️⃣ 웹소켓은 비동기적으로 동작해야 실시간 처리가 가능함.
- 동기 방식이면 서버가 요청을 기다리느라 멈춰야 해서 비효율적.
- 비동기 방식이면 서버와 클라이언트가 서로 독립적으로 동작 가능.
📌 결론: 웹소켓 + Redis + 비동기 처리를 조합하면, 고성능 실시간 애플리케이션을 만들 수 있다