1. Short Polling — "계속 물어보기"
실시간 통신의 가장 원시적인 형태입니다. 클라이언트가 일정 간격으로 서버에 새 데이터가 있는지 반복 요청합니다.
// 3초마다 새 메시지 확인
setInterval(async () => {
const res = await fetch('/api/messages/latest');
const data = await res.json();
if (data.new) render_messages(data.messages);
}, 3000);
단점: 새 데이터가 없어도 서버에 요청이 쏟아집니다. 1,000명이 동시에 사용하면 초당 333번의 불필요한 요청이 발생합니다.
2. Long Polling — "대기하다 응답하기"
Polling의 낭비를 줄이기 위해 등장했습니다. 클라이언트가 요청을 보내면 서버는 새 데이터가 생길 때까지 연결을 유지하다가 응답합니다.
// 서버 (Laravel)
public function wait_for_message($last_id) {
$timeout = time() + 30; // 30초 대기
while (time() < $timeout) {
$msg = Message::where('id','>',$last_id)->first();
if ($msg) return response()->json($msg);
sleep(1);
}
return response()->json(null, 204);
}
한계: HTTP 연결 하나가 30초씩 점유됩니다. 동시 접속자 수만큼 서버 스레드가 블로킹됩니다. Node.js 이전 시대에는 서버 확장의 악몽이었습니다.
3. SSE (Server-Sent Events) — "서버가 먼저 보내기"
2004년 등장한 HTML5 표준입니다. 클라이언트가 한 번 연결을 열면 서버가 일방적으로 데이터를 스트리밍합니다.
// 서버 (PHP)
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
while(true) {
echo "data: " . json_encode(['time' => date('H:i:s')]) . "\n\n";
flush();
sleep(1);
}
// 클라이언트
const source = new EventSource('/events');
source.onmessage = (e) => console.log(JSON.parse(e.data));
장점: HTTP/2와 완벽 호환, 자동 재연결 내장, 방화벽 통과 우수.
한계: 단방향(서버→클라이언트)만 가능. 채팅처럼 클라이언트도 데이터를 보내야 하면 별도 API 요청이 필요합니다.
4. WebSocket 등장 — "양방향 실시간 통신"
2011년 IETF RFC 6455로 표준화됩니다. HTTP 핸드셰이크 후 TCP 연결을 업그레이드하여 양방향 지속 연결을 유지합니다.
// HTTP Upgrade 핸드셰이크
GET /chat HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
// 서버 응답 후 TCP 연결 유지
// 이후 HTTP 프로토콜 오버헤드 없이 프레임 단위 통신
// 클라이언트
const ws = new WebSocket('wss://example.com/chat');
ws.onopen = () => ws.send(JSON.stringify({ msg: 'Hello!' }));
ws.onmessage = (e) => console.log(JSON.parse(e.data));
HTTP 헤더가 매번 붙지 않아 오버헤드가 극적으로 줄어듭니다. 지연시간도 Long Polling 대비 10배 이상 감소합니다.
5. Socket.io — "WebSocket의 현실적 래퍼"
2010년 Node.js 생태계에서 등장했습니다. WebSocket을 기반으로 하되, 연결이 실패할 경우 자동으로 Long Polling으로 폴백합니다.
// 서버 (Node.js)
const io = require('socket.io')(server);
io.on('connection', (socket) => {
socket.on('chat:message', (msg) => {
io.to(msg.room).emit('chat:message', msg); // 룸에 브로드캐스트
});
});
// 클라이언트
const socket = io('https://example.com');
socket.emit('chat:message', { room: 'general', text: '안녕하세요' });
socket.on('chat:message', (msg) => append_message(msg));
룸 관리, 이벤트 네임스페이스, 자동 재연결이 내장되어 채팅 앱의 표준이 됩니다. 단, 별도 Node.js 서버 운영이 필요합니다.
6. Laravel Echo + Pusher — "PHP 생태계의 WebSocket"
Laravel은 Broadcasting API로 WebSocket 이벤트를 쉽게 관리합니다. Pusher는 WebSocket 인프라를 SaaS로 제공합니다.
// 서버: 이벤트 발행
class MessageSent implements ShouldBroadcast {
public function broadcastOn() {
return new Channel('room.' . $this->room_id);
}
}
event(new MessageSent($message, $room_id));
// 클라이언트: Laravel Echo로 구독
const echo = new Echo({
broadcaster: 'pusher',
key: import.meta.env.VITE_PUSHER_APP_KEY,
});
echo.channel('room.1').listen('MessageSent', (e) => {
append_message(e.message);
});
자체 WebSocket 서버를 운영하려면 Reverb(Laravel 공식, 2024년 출시)를 사용할 수 있습니다.
7. 기술 비교 & 선택 기준
| 기술 | 방향 | 연결 지속 | 적합한 사례 |
|---|---|---|---|
| Short Polling | 양방향 | ❌ 없음 | 단순 상태 확인 (업데이트 빈도 낮음) |
| Long Polling | 양방향 | △ 단발 | 구형 브라우저 지원 필요 시 폴백 |
| SSE | 서버→클 | ✅ 지속 | AI 스트리밍 응답, 알림, 주가 피드 |
| WebSocket | 양방향 | ✅ 지속 | 채팅, 협업 도구, 멀티플레이어 게임 |
| Laravel Echo | 양방향 | ✅ 지속 | Laravel 기반 실시간 기능 (채팅·알림) |