
백엔드
Long PollingLong Polling
Long Polling은 WebSocket 이전 시대부터 사용된 실시간 통신 기법이다. 클라이언트가 서버에 요청을 보내고, 서버는 새 데이터가 생길 때까지 응답을 보류하다가 데이터가 준비되면 응답한다. 응답 후 클라이언트는 즉시 재요청한다.
동작 흐름
클라이언트 서버
|--- GET /poll ------→ |
| | (데이터 없음 → 대기)
| | (최대 30초 대기)
|← 200 { data } ------| (데이터 생기면 응답)
|--- GET /poll ------→ | (즉시 재요청)
| |서버 구현
javascript
// Express Long Polling
const waitingClients = new Map();
app.get('/poll', async (req, res) => {
const userId = req.query.userId;
const lastEventId = parseInt(req.query.lastId || '0');
// 즉시 사용 가능한 데이터 확인
const newEvents = await getEventsSince(userId, lastEventId);
if (newEvents.length > 0) {
return res.json(newEvents);
}
// 대기 (최대 30초)
const timeout = setTimeout(() => {
waitingClients.delete(userId);
res.json([]); // 빈 응답으로 재요청 유도
}, 30000);
waitingClients.set(userId, { res, timeout });
});
// 새 이벤트 발생 시 대기 중인 클라이언트에 응답
function notifyClients(userId, event) {
const client = waitingClients.get(userId);
if (client) {
clearTimeout(client.timeout);
waitingClients.delete(userId);
client.res.json([event]);
}
}클라이언트 구현
javascript
let lastEventId = 0;
async function poll() {
try {
const response = await fetch(`/poll?lastId=${lastEventId}`);
const events = await response.json();
for (const event of events) {
processEvent(event);
lastEventId = Math.max(lastEventId, event.id);
}
} catch (error) {
await new Promise(resolve => setTimeout(resolve, 5000)); // 오류 시 재시도 지연
}
poll(); // 즉시 재요청
}
poll();