C.W.K.
Stream
Lesson 03 of 08 · published

Long Polling: 좀 더 영리한 hack

~12 min · foundations, long-polling

Level 0Poller
0 XP0/60 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

트릭: 응답을 잡고 있어

Long polling 은 request 모양은 그대로 두고 타이밍을 뒤집어. 서버가 'no news' 라고 즉시 답하지 않고, 할 말이 생기거나 자기 timeout 이 끝날 때까지 connection 잡고 있어. 클라는 즉시 push 받은 것처럼 보이고, 다음 request 를 즉시 보내서 채널 살려놔.

2010년대를 이긴 이유

Long polling 은 HTTP 외엔 다 싫어하는 corporate firewall 과 proxy 를 뚫고 다녔어. Gmail 이 몇 년 썼어. Facebook chat 도 썼어. WebSocket 막혔을 때 Socket.IO 가 떨어지는 안전망이 여전히 long polling 이야.

여전히 hack 인 이유

응답마다 connection 닫혀. TCP handshake 다시 내야 해. proxy 가 1-2분 idle 후 죽이니까 서버 timeout 을 proxy threshold 아래로 맞춰야 해. 대기 중인 request 마다 서버 worker 잡아먹어. 그리고 일방향이야: 서버는 push 잘 하지만, 클라가 보내려면 별도 request 또 쓰는 거.

Code

FastAPI long-poll endpoint·python
from fastapi import FastAPI
import asyncio

app = FastAPI()
queue: asyncio.Queue = asyncio.Queue()

@app.get('/api/messages')
async def long_poll():
    try:
        # Wait up to 25s for something — under most proxy idle limits.
        msg = await asyncio.wait_for(queue.get(), timeout=25.0)
        return {'messages': [msg]}
    except asyncio.TimeoutError:
        # Empty response triggers the client to reconnect immediately.
        return {'messages': []}
브라우저 long-poll loop·javascript
async function longPoll() {
  while (true) {
    try {
      const res = await fetch('/api/messages');
      const { messages } = await res.json();
      if (messages.length) renderMessages(messages);
    } catch (err) {
      console.warn('long poll failed, backing off', err);
      await new Promise(r => setTimeout(r, 2_000));
    }
  }
}

longPoll();

External links

Exercise

위 FastAPI long-poll endpoint 를 uvicorn main:app 으로 띄워. 한 터미널에서 /admin/push 같은 endpoint 직접 짜서 queue 에 message 넣어. 다른 터미널에서 GET /api/messages 때려서 message 가 push 될 때만 응답 떨어지는 거 확인. 안 push 했을 땐 25초 기다렸다가 빈 응답 떨어지는 것도 봐.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.