폴링을 실시간 업데이트로 바꾸기
몇 초마다 API에 묻는 일을 멈추세요. 변화는 한 번만 보내 요청과 서버 부하를 줄이고, 생기는 즉시 화면에 보여 줍니다.
많은 앱은 '물어봐서' 변화를 알아냅니다. 열려 있는 모든 페이지가 몇 초마다 API를 호출해 주문, 티켓, 리포트가 바뀌었는지 확인하는 것이죠. 대답은 거의 항상 '새로운 것 없음'인데도, 매번 요청 하나, 데이터베이스 쿼리 하나, 사용자 휴대폰의 배터리를 씁니다. 실제로 바뀐 내용도 다음 간격이 올 때까지 화면에 나오지 않습니다. Hibira를 쓰면 변화가 생길 때 서버가 한 번만 보내고, 그 데이터를 보여 주는 모든 페이지가 몇 밀리초 안에 갱신됩니다.
사용자가 얻는 것
- 최대 5초를 기다리지 않고, 변화가 생긴 순간 화면에 반영.
- 새로고침 없이 모든 탭이 항상 최신 상태.
- 휴대폰이 몇 초마다 쓸데없이 네트워크를 깨우지 않음.
폴링의 비용
1,000명이 페이지를 열어 두고 5초마다 폴링하면 한 시간에 720,000개의 요청이 됩니다. 그 한 시간 동안 데이터가 200번만 바뀌었다면, 요청의 99.97%는 새로운 내용이 없습니다. 푸시로 바꾸면 같은 한 시간이 200개의 메시지로 끝나고, API는 각 페이지의 첫 로딩만 처리하면 됩니다.
사용하는 기능
- 비공개 채널(
private-order-42): 페이지가 보여 주는 대상마다 하나씩 만들고 서버가 인가하므로, 사용자는 자기 데이터만 받습니다. - 공식 서버 SDK의
trigger: 변경을 저장한 직후에 호출합니다. pusher:subscription_succeeded: 첫 연결과 재연결 때마다 발생하므로, 현재 상태를 불러오기에 딱 맞는 시점입니다.
폴링
푸시
trigger() 한 번1단계: 폴링 루프 찾기
보통 이런 모양입니다:
setInterval(async () => {
render(await fetch('/api/orders/42').then((r) => r.json()));
}, 5000);2단계: 한 번 불러오고, 그다음엔 듣기
JavaScript 가이드대로 연결하고, 비공개 채널용 채널 인가 엔드포인트를 준비합니다. 구독이 준비되면 현재 상태를 불러오고, 이후에는 변화가 도착할 때마다 반영합니다:
const load = async () => render(await fetch('/api/orders/42').then((r) => r.json()));
const channel = pusher.subscribe('private-order-42');
channel.bind('pusher:subscription_succeeded', load);
channel.bind('updated', (order) => render(order));3단계: 저장할 때 변화 보내기
데이터가 바뀌는 곳(API 라우트, 워커, 관리자 작업, 웹훅)에서 쓰기가 성공한 뒤 발행합니다:
app.patch('/api/orders/:id', requireLogin, async (req, res) => {
const order = await db.orders.update(req.params.id, req.body);
await pusher.trigger(`private-order-${order.id}`, 'updated', order);
res.json(order);
});4단계: 가벼운 안전장치 두기
재연결 후 구독이 다시 발생하므로, 연결이 끊겼던 동안의 빈틈은 load()가 이미 채워 줍니다. 브라우저가 백그라운드 탭을 멈추기도 하므로, 탭이 다시 보일 때 한 번 더 불러옵니다:
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') load();
});