본문 바로가기
카테고리 없음

[Polling] 폴링과 롱 폴링 (feat. SSE와 Socket)

by hbIncoding 2024. 11. 28.

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

 

롱 폴링

 

ko.javascript.info