AmberAx

SSE (Server-Sent Events): 실시간 웹 개발

· 4 min read
SSE (Server-Sent Events): 실시간 웹 개발

웹 애플리케이션에서 서버와 클라이언트 간의 실시간 데이터 통신은 중요한 요구사항입니다.

과거에는 폴링(polling)과 롱 폴링(long polling) 같은 방법이 주로 사용되었지만, 더 효율적인 대안으로 SSE(Server-Sent Events) 가 등장했습니다. 이번 글에서는 SSE의 개념, 유래, 동작 방식, 그리고 실전 예제를 소개합니다.


SSE란? #

SSE (Server-Sent Events) 는 서버가 클라이언트에게 일방향으로 데이터를 스트리밍 하는 기술입니다. HTTP 프로토콜 위에서 동작하며, 클라이언트가 서버와의 연결을 유지하면서 실시간 데이터를 받을 수 있도록 설계되었습니다. SSE는 HTML5 표준의 일부로, 브라우저와 서버 간의 실시간 데이터 교환을 간단히 구현할 수 있는 방법을 제공합니다.

SSE는 과거의 폴링(polling) 방식이 가진 한계를 해결하기 위해 등장했습니다. 폴링은 구현이 단순하다는 장점이 있지만, 시간이 지날수록 코드가 복잡해지고 서버 리소스를 비효율적으로 소모하는 문제가 있습니다. 반면 SSE는 클라이언트-서버 간의 연결을 유지한 채 서버가 필요한 데이터만 전송하도록 설계되어 효율적이고 직관적입니다. 이러한 매력 덕분에 실시간 데이터가 필요한 다양한 애플리케이션에서 활용되고 있습니다.

주요 특징

  1. 단방향 스트리밍: 서버에서 클라이언트로만 데이터가 전송됩니다.
  2. HTTP 기반: 별도의 프로토콜 없이 HTTP/1.1로 동작합니다.
  3. 자동 재연결: 연결이 끊어지면 클라이언트가 자동으로 재연결을 시도합니다.
  4. 간단한 구현: 클라이언트는 EventSource API를 사용하며, 서버는 text/event-stream MIME 타입을 사용합니다.

SSE의 유래 #

SSE는 2009년 HTML5 초안에서 처음 등장했으며, 2014년 HTML5가 W3C 권고안(Recommendation) 으로 발표되면서 표준의 일부로 자리 잡았습니다.

과거 웹에서는 클라이언트와 서버 간 실시간 통신을 구현할 때 주로 폴링(polling)롱 폴링(long polling) 을 사용했습니다.

  • 폴링은 클라이언트가 일정 간격으로 서버에 요청을 보내는 방식으로, 구현이 단순하지만 지연이 발생하고 불필요한 리소스 소모가 큽니다.
  • 롱 폴링은 서버가 새로운 데이터를 준비할 때까지 응답을 지연시키는 방식으로, 효율적이지만 여전히 클라이언트가 주기적으로 요청을 보내야 한다는 단점이 있습니다.

이러한 기존 방식의 단점을 보완하기 위해 SSE가 도입되었습니다. SSE는 서버가 클라이언트에 실시간 데이터를 푸시(push)할 수 있는 기능을 제공하면서도 HTTP 프로토콜 위에서 동작하므로 기존의 방화벽이나 네트워크 환경에서도 원활하게 작동합니다. 또한, 브라우저에서 기본적으로 지원되기 때문에 클라이언트 구현이 간단합니다. 이 모든 점에서 SSE는 효율성과 간결함을 모두 만족시키는 기술로 자리 잡았습니다.


SSE 동작 방식 #

SSE는 클라이언트가 서버에 지속적인 연결을 열고, 서버가 데이터를 실시간으로 스트리밍하는 방식으로 작동합니다.

클라이언트 동작

클라이언트는 EventSource API를 사용해 SSE 연결을 시작합니다:

const eventSource = new EventSource('/events');

// 메시지 수신 처리
eventSource.onmessage = (event) => {
    console.log('New message:', event.data);
};

// 에러 처리
eventSource.onerror = (err) => {
    console.error('Connection error:', err);
};

서버 동작

서버는 HTTP 응답을 유지하면서 데이터를 스트리밍합니다. 각 메시지는 data:로 시작하며, \n\n으로 종료됩니다.

res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive'
});

res.write('data: Hello, Client!\n\n');

SSE와 다른 기술 비교 #

기술 특징 사용 사례
SSE 단방향 스트리밍, HTTP 기반, 자동 재연결 실시간 알림, 주식 시세, 실시간 로그 뷰어
WebSocket 양방향 통신, TCP 기반, 더 복잡한 상호작용에 적합 채팅 애플리케이션, 게임 실시간 데이터
폴링 클라이언트가 주기적으로 서버에 요청 간단한 상태 확인
롱 폴링 서버가 새로운 데이터를 준비할 때까지 요청을 대기 과거의 실시간 데이터 구현 방법

SSE 예제 #

클라이언트 코드

아래는 간단한 HTML과 JavaScript로 구현한 SSE 클라이언트입니다:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SSE Example</title>
</head>
<body>
    <h1>Server-Sent Events Example</h1>
    <div id="messages">
        <p>Waiting for messages...</p>
    </div>

    <script>
        const eventSource = new EventSource('http://localhost:3000/events');

        eventSource.onmessage = (event) => {
            const messagesDiv = document.getElementById('messages');
            const newMessage = document.createElement('p');
            newMessage.textContent = `Message: ${event.data}`;
            messagesDiv.appendChild(newMessage);
        };

        eventSource.onerror = (err) => {
            console.error('SSE connection error:', err);
        };
    </script>
</body>
</html>

서버 코드

Node.js를 사용해 SSE 서버를 구현한 예제입니다:

const http = require('http');

const server = http.createServer((req, res) => {
    if (req.url === '/events') {
        res.writeHead(200, {
            'Content-Type': 'text/event-stream',
            'Cache-Control': 'no-cache',
            'Connection': 'keep-alive'
        });

        let counter = 0;
        const intervalId = setInterval(() => {
            counter++;
            res.write(`data: Message #${counter}\n\n`);
        }, 2000);

        req.on('close', () => {
            clearInterval(intervalId);
            console.log('Client disconnected');
        });
    } else {
        res.writeHead(404);
        res.end('Not Found');
    }
});

server.listen(3000, () => {
    console.log('Server is running at http://localhost:3000');
});

결론 #

SSE는 단방향 실시간 데이터 스트리밍을 간단히 구현할 수 있는 강력한 기술입니다. HTTP 기반으로 동작하며, 설정이 간단하고 브라우저가 자동 재연결을 지원하는 등 실시간 알림, 로그 스트리밍 등 다양한 용도로 활용될 수 있습니다.

폴링은 단순한 구현 방식 덕분에 과거에 많이 사용되었지만, 시간이 지날수록 코드 복잡성과 효율성 문제가 드러났습니다. 반면 SSE는 이러한 단점을 해결하며 실시간 기능 구현의 매력적인 대안이 됩니다.

하지만 SSE는 양방향 통신이 필요한 경우에는 적합하지 않으며, 이럴 땐 WebSocket과 같은 기술을 고려해야 합니다.

SSE를 활용해 실시간 기능이 필요한 프로젝트에 효율적이고 간단한 솔루션을 제공해보세요!

Did you find this post helpful?
Share it with others!