인공지능(AI)/AI 텍스트
SSE(Server-Sent Events) vs 스트리밍(Streaming) 차이점 알아보니..
프리스케이터
2025. 8. 8. 08:00
"스트리밍(Streaming)"은 데이터를 한 번에 다 받지 않고 조각(chunk)으로 나누어 연속적으로 전송하는 기술 전체를 의미하는 넓은 개념이고, "SSE(Server-Sent Events)"는 이 스트리밍을 구현하는 구체적인 웹 표준 기술 중 하나입니다.
즉, SSE는 스트리밍의 한 종류입니다.
비유하자면, '자동차'가 '스트리밍'이라면, '세단', 'SUV', '트럭' 등은 각각 'SSE', 'WebSocket', 'Chunked Streaming' 같은 구체적인 기술에 해당합니다.
비교 요약표
| 항목 | SSE (Server-Sent Events) | 일반적인 HTTP 스트리밍 (Chunked Transfer Encoding) |
| 핵심 개념 | 웹 표준으로 정의된 서버-클라이언트 간 단방향 스트리밍 프로토콜 | HTTP의 기능을 이용해 응답을 조각내어 보내는 일반적인 기술 |
| 통신 방향 | 단방향 (서버 → 클라이언트) | 단방향 (서버 → 클라이언트) |
| 데이터 형식 | 정해진 규칙이 있음 (data:, id:, event:, retry:) | 규칙 없음. 개발자가 자유롭게 정의 (예: 줄바꿈으로 구분된 JSON) |
| 클라이언트 구현 | 매우 쉬움. 브라우저에 내장된 EventSource API 사용 | 수동 구현 필요. 응답을 텍스트로 받아 직접 파싱하고 연결 관리 |
| 자동 재연결 | 지원함. 연결이 끊기면 브라우저가 자동으로 재연결 시도 | 지원 안함. 클라이언트 측에서 직접 재연결 로직 구현 필요 |
| 주요 사용 사례 | 실시간 알림, 뉴스 피드, 주식 시세, 대시보드 업데이트 | LLM API 응답, 대용량 파일 다운로드, 커스텀 프로토콜 스트리밍 |
1. SSE (Server-Sent Events) - "잘 포장된 규격 방송"
SSE는 W3C 웹 표준으로, 서버가 클라이언트(주로 웹 브라우저)에게 지속적으로 데이터를 보내기 위해 만들어졌습니다.
라디오 방송처럼 서버가 일방적으로 정보를 계속 보내주는 방식입니다.
특징:
- 표준화된 형식: 모든 데이터 조각은 data: 라는 접두사로 시작해야 합니다. 그 외에도 이벤트 종류를 지정하는 event:, 메시지 ID를 부여하는 id:, 재연결 시간을 정하는 retry: 등 명확한 규칙이 있습니다.
- 간편한 클라이언트: 웹 브라우저에는 EventSource 라는 내장 객체가 있어 단 몇 줄의 코드로 SSE 스트림을 구독하고 이벤트를 받을 수 있습니다.
- 자동 재연결: 네트워크 문제로 연결이 끊어지면, 브라우저가 id: 값을 참조하여 마지막으로 받은 데이터 이후부터 자동으로 재연결을 시도합니다. 개발자가 신경 쓸 필요가 없습니다.
예시 응답:
Code
Content-Type: text/event-stream
data: {"message": "첫 번째 메시지입니다."}
event: user-update
data: {"user": "Alice", "status": "online"}
id: 12345
data: 중요한 업데이트입니다.
2. 일반적인 HTTP 스트리밍 - "규칙 없이 보내는 소포 꾸러미"
이는 HTTP/1.1의 Chunked Transfer Encoding 기능을 이용하는 더 일반적인 방식입니다. 서버는 응답의 전체 크기를 미리 알리지 않고, 준비되는 대로 데이터 조각을 계속 보낼 수 있습니다. 이 방식은 SSE처럼 정해진 규칙이 없습니다.
특징:
- 자유로운 형식: 서버와 클라이언트가 서로 약속만 한다면 어떤 형식이든 보낼 수 있습니다. 사용자님이 예시로 보여주신 LLM 응답이 여기에 해당합니다.
- data: {...} 형식은 SSE의 형식을 차용한 것일 뿐, SSE 표준을 완전히 따르는 것은 아닐 수 있습니다. 그냥 개발자들 사이에서 "아, 이건 스트리밍 데이터구나" 하고 알아보기 쉽게 만든 **관례(convention)**입니다.
- 수동 구현: 브라우저에 EventSource 같은 편리한 API가 없습니다. 개발자는 fetch API 등을 사용하여 응답 스트림을 직접 읽고, 텍스트 디코더로 변환하고, 줄바꿈(\n)을 기준으로 데이터를 잘라내고, 각 조각이 유효한 JSON인지 직접 파싱해야 합니다.
- 재연결 로직 필요: 연결이 끊기면 처음부터 다시 요청해야 하며, 이어서 받는 로직을 직접 구현해야 합니다.
예시 응답 (LLM API):
Content-Type: application/json (또는 다른 타입)
{"chunk": 1, "content": "안녕하세요"}
{"chunk": 2, "content": ", 저는"}
{"chunk": 3, "content": " AI입니다."}
[DONE]
위 예시는 줄바꿈으로 구분된 JSON(Newline Delimited JSON, NDJSON) 형식으로, 일반적인 스트리밍에서 흔히 사용됩니다.
핵심 결론
| 구분 | SSE | 일반 스트리밍 |
| 누가 쓰기 편한가? | 웹 프론트엔드 개발자. 브라우저가 대부분의 귀찮은 일을 해준다. | 백엔드/서버 개발자. 데이터 형식을 자유롭게 제어할 수 있다. |
| 언제 쓰는가? | 웹 브라우저 대상의 실시간 알림, 피드 기능 구현 시 | LLM API처럼 특수한 데이터 포맷이 필요하거나, 브라우저가 아닌 클라이언트(예: 다른 서버, 모바일 앱)와 통신할 때 |