상세 컨텐츠

본문 제목

Polling (Short Polling), Long Polling, Stream API (Server-Sent Events, SSE)

개발자를위한다양한이야기

by codeon 2026. 1. 22. 20:12

본문

반응형

웹 애플리케이션에서 서버로부터 데이터를 실시간으로 가져오기 위한 방법들은 서비스의 요구사항과 자원 효율성에 따라 여러 가지가 있습니다. 가장 대표적인 **Polling, Long Polling, 그리고 Stream API (Server-Sent Events)**에 대해 자세히 설명해 드리겠습니다.

요약 및 비교

 

웹 애플리케이션에서 서버로부터 데이터를 실시간으로 가져오기 위한 방법

1. Polling (Short Polling)

클라이언트가 일정한 주기(예: 5초마다)로 서버에 "새로운 데이터가 있나요?"라고 물어보는 방식입니다. 가장 고전적이고 구현이 쉬운 방법입니다.


작동 원리: 주기적으로 HTTP 요청을 보내고 응답을 받으면 연결을 종료합니다.
장점: 구현이 매우 간단하며, 서버 상태를 유지하지 않아도 됩니다.
단점: 데이터가 없어도 계속 요청을 보내므로 서버 및 네트워크 리소스 낭비가 심합니다. 실시간성이 떨어집니다.

 

Client 예시:

// 클라이언트 코드
function startPolling() {
    setInterval(async () => {
        try {
            const response = await fetch('/api/data');
            const data = await response.json();
            console.log("데이터 수신:", data);
        } catch (error) {
            console.error("에러 발생:", error);
        }
    }, 5000); // 5초마다 요청
}

startPolling();

 

2. Long Polling

Polling의 비효율성을 개선한 방식입니다. 클라이언트가 요청을 보내면 서버는 새로운 데이터가 생길 때까지 연결을 열어두고 기다립니다.


작동 원리:
클라이언트가 서버로 요청을 보냅니다.
서버는 새로운 데이터가 생길 때까지 응답을 보내지 않고 대기합니다.
데이터가 생기거나 타임아웃이 발생하면 응답을 보냅니다.
클라이언트는 응답을 받자마자 다시 서버에 요청을 보냅니다.
장점: 일반 Polling보다 실시간성이 높고, 데이터가 없을 때의 불필요한 트래픽을 줄입니다.
단점: 다수의 클라이언트가 연결될 경우, 서버가 많은 대기 요청을 유지해야 하므로 부담이 될 수 있습니다.

 

Client 예시:

async function longPoll() {
    try {
        const response = await fetch('/api/long-poll');
        if (response.status === 200) {
            const data = await response.json();
            console.log("새 데이터:", data);
        }
        // 응답을 받으면 즉시 다시 요청
        longPoll();
    } catch (error) {
        setTimeout(longPoll, 5000); // 에러 발생 시 5초 후 재시도
    }
}
longPoll();

 

Server (Express 예시):

app.get('/api/long-poll', (req, res) => {
    // 데이터가 생길 때까지 기다리는 로직 (예: EventEmitter)
    newDataEmitter.once('update', (data) => {
        res.json(data);
    });
    
    // 타임아웃 설정 (예: 30초 후 응답)
    setTimeout(() => {
        if (!res.writableEnded) res.status(204).end();
    }, 30000);
});

 

3. Stream API (Server-Sent Events, SSE)

서버와 클라이언트 간에 한 번 연결을 맺으면, 서버가 클라이언트로 데이터를 지속적으로 밀어주는(Push) 단방향 스트리밍 방식입니다.

 

작동 원리: HTTP 연결을 유지한 채로 text/event-stream 형식을 사용하여 데이터를 전송합니다.
장점: 연결 재수립 비용이 들지 않아 매우 효율적이며 실시간성이 매우 높습니다. HTTP 프로토콜을 그대로 사용하므로 호환성이 좋습니다.
단점: 서버에서 클라이언트로만 보내는 단방향 통신입니다. (클라이언트에서 서버로 보낼 때는 별도의 HTTP 요청 필요)

 

예제 (Node.js & JavaScript)
Server (Express 예시):

app.get('/api/stream', (req, res) => {
    // SSE를 위한 헤더 설정
    res.setHeader('Content-Type', 'text/event-stream');
    res.setHeader('Cache-Control', 'no-cache');
    res.setHeader('Connection', 'keep-alive');

    // 데이터를 2초마다 전송
    const interval = setInterval(() => {
        const data = { message: '실시간 알림', time: new Date() };
        res.write(`data: ${JSON.stringify(data)}\n\n`); // 규격: "data: 내용\n\n"
    }, 2000);

    // 연결 종료 시 처리
    req.on('close', () => {
        clearInterval(interval);
        res.end();
    });
});

 

Client 예시:

function startSSE() {
    const eventSource = new EventSource('/api/stream');

    eventSource.onmessage = (event) => {
        const data = JSON.parse(event.data);
        console.log("스트림 데이터 수신:", data);
    };

    eventSource.onerror = (error) => {
        console.error("SSE 에러:", error);
        eventSource.close();
    };
}
startSSE();

 

 

결론

단순함이 제일 중요하고 실시간성이 낮아도 된다면 -> Polling
실시간성이 필요하지만, 양방향(WebSocket)까지는 필요 없다면 -> SSE
오래된 브라우저를 지원해야 하거나 SSE 설정이 어려운 환경이라면 -> Long Polling
만약 채팅처럼 서버-클라이언트 간 양방향 실시간 통신이 매우 빈번하다면 -> WebSocket(별개 기술)을 고려

반응형

관련글 더보기