0. 개요
- 폴링은 주기적으로 서버에 요청해서 데이터가 있는지 혹은 변했는지 체크하는 방식이다.
- 근데 poll은 "투표"라는 뜻을 가지고 있는데 왜 polling은 SW에서 투표와 무관해 보이는 뜻을 가지게 된 것일까?
- GTP와 Copilot에 의하면 정확한 기원은 기록이 없지만, 반복적인 확인(정기적으로 사람들에게 질문하여 의견을 확인)하거나 투표에서 일정 시간 동안 개표를 진행하는 주기적인 활동에서 비롯된것 같다고 한다.
- 폴링은 특수한 연결 유지가 없다. 그래서 클라이언트에서 지속적으로 요청을 보내서 확인하는 방식이다.
술만 마시면 전 애인에게 카톡을 남기는 누군가와 비슷하다. 물론 응답이 올 수도 안올 수도 있고, 응답이 와도 원하지 않았던 응답일 수 도 있다. 주기적으로 요청하는 것 까지 비슷하다.
1. 폴링(Regular Polling)
- 주기적으로 일정 시간 마다 요청을 보내서 확인한다.
- 아래 코드를 보면 직관적으로 이해가 가능하다.
// 클라이언트 측: 폴링을 통해 주기적으로 서버에 데이터를 요청
const pollServer = async () => {
try {
const response = await fetch('http://localhost:3000/api/polling');
if (response.ok) {
const data = await response.json();
console.log('Received data:', data);
} else {
console.error('Server returned an error:', response.status);
}
} catch (error) {
console.error('Error fetching data:', error);
} finally {
// 5초 후 다시 요청
setTimeout(pollServer, 5000);
}
};
// 폴링 시작
pollServer();
--------
// 백엔드 측
const express = require('express');
const app = express();
const PORT = 3000;
// 임의 데이터 생성
let currentData = { message: 'Hello, this is your data!' };
// 주기적으로 데이터를 업데이트 (10초마다 변경)
setInterval(() => {
currentData = { message: `Updated data at ${new Date().toISOString()}` };
}, 10000);
// 폴링 엔드포인트
app.get('/api/polling', (req, res) => {
res.json(currentData);
});
// 서버 시작
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
2. 롱 폴링(Long Polling)
- 폴링에 비해 불필요한 요청 횟수를 줄일 수 있다.
- 데이터가 변경될 때만 클라이언트와 서버 간 네트워크 활동이 발생한다.
- 한번 요청을 보내면 응답이 올 때 까지 진득하게 기다린다.
// 클라이언트 측: 롱 폴링을 통해 서버에서 새 데이터를 기다림
const longPollServer = async () => {
try {
const response = await fetch('http://localhost:3000/api/long-polling', {
method: 'GET',
});
if (response.ok) {
const data = await response.json();
console.log('Received data:', data);
} else {
console.error('Server error:', response.status);
}
} catch (error) {
console.error('Error during long-polling:', error);
} finally {
// 서버 응답 후 즉시 다시 요청
longPollServer();
}
};
// 롱 폴링 시작
longPollServer();
--------------
// 백엔드 코드
const express = require('express');
const app = express();
const PORT = 3000;
let listeners = []; // 현재 기다리고 있는 클라이언트를 저장
// 롱 폴링 엔드포인트
app.get('/api/long-polling', (req, res) => {
console.log('Client connected for long-polling');
// 새로운 클라이언트를 리스트에 추가
listeners.push(res);
// 요청이 30초 후에도 응답을 받지 못하면 타임아웃
setTimeout(() => {
if (listeners.includes(res)) {
listeners = listeners.filter(listener => listener !== res);
res.status(204).send(); // No Content
}
}, 30000);
});
// 주기적으로 데이터 업데이트
setInterval(() => {
if (listeners.length > 0) {
const newData = { message: `New data at ${new Date().toISOString()}` };
console.log('Sending data to clients:', newData);
// 모든 대기 중인 클라이언트에 데이터 전송
listeners.forEach(res => res.json(newData));
listeners = []; // 전송 후 대기 클라이언트 초기화
}
}, 10000); // 10초마다 데이터 갱신
// 서버 시작
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
3. 결론
- 폴링과 롱 폴링의 차이
- 폴링 : [있나요? -> 없어요!, 있나요? -> 없어요!, 있나요? -> 있어요! ] 의 반복이다.
- 롱폴링 : [있나요------------------------------------------------------> 있어요! ] 의 반복이다.
- 그렇다면 여기서 의문점이 몇개 있다.
- 롱 폴링은 정말 무한정 기다려 주는가?
- 클라이언트에서 별다른 세팅을 안해준다면 브라우저에 따라서 2~5분 정도 기다렸다가 강제로 종료될 수 있다. 또는 당연한 얘기지만 네트워크가 불안정하거나 끊어지면 실패한다. 재요청 로직까지 클라이언트에서 고려해줘야한다.
- 그리고 서버측에서도 연결을 유지하면 비용이 들기 때문에 보통 타임아웃 시간을 설정한다.
- 롱 폴링은 정말 무한정 기다려 주는가?
- 다른 방식들과의 차이는 어떤가?
특징 | 폴링 (Polling) | 롱 폴링 (Long Polling) | SSE | WebSocket |
통신 방식 | 주기적 요청 | 요청 후 응답 지연 | 서버 → 클라이언트 (단방향) | 양방향 통신 |
실시간성 | 낮음 | 중간 | 높음 | 매우 높음 |
리소스 효율성 | 비효율적 | 중간 | 효율적 | 매우 효율적 |
사용 사례 | 간단한 상태 확인 | 알림, 데이터 푸시 | 실시간 알림, 이벤트 스트림 | 채팅, 게임, 실시간 협업 도구 |
설치/설정 | 간단 | 비교적 간단 | 간단 | 복잡 (특히 서버 설정) |
방화벽 호환성 | 우수 | 우수 | 우수 | 제한적 (프록시/방화벽 문제) |
HTTP 지원 | 완전 지원 | 완전 지원 | HTTP 기반 | 초기 연결 이후 WebSocket으로 변경 |
4. 참고
1. JS LongPolling : https://ko.javascript.info/long-polling