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

클라이언트가 일정한 주기(예: 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();
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);
});
서버와 클라이언트 간에 한 번 연결을 맺으면, 서버가 클라이언트로 데이터를 지속적으로 밀어주는(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(별개 기술)을 고려
| 웹 패킷 분석 Fiddler 사용법 (1) | 2026.01.23 |
|---|---|
| Git 긴급(충돌)할때 사용하는 명령어 (0) | 2025.08.20 |
| 웹소켓 통신 시 1::, h, a와 같은 문자열 (3) | 2025.01.08 |
| java:comp/env/ 규칙은 뭘까? (3) | 2025.01.08 |
| 클래스 불변식(Class Invariant) (3) | 2024.12.31 |