본문 바로가기
C.W.K.
Stream
Lesson 04 of 08 · published

Server-Sent Events (SSE)

~14 min · foundations, sse

Level 0Poller
0 XP0/60 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

서버만 보내면 되는 길

Server-Sent Events 는 long polling 을 표준화하고 다듬은 방식이야. 클라이언트가 특별한 엔드포인트로 HTTP 요청 1개를 열면 서버는 Content-Type: text/event-stream 으로 응답한 뒤 연결을 닫지 않아. 알려줄 일이 생길 때마다 data: ...\n\n 덩어리를 이어서 써.

SSE 를 너무 쉽게 지나쳐

팀들은 ‘실시간이 필요해’라는 말만 나오면 SSE 를 보지도 않고 WebSocket 으로 달려가곤 해. 하지만 요즘 가장 흔한 실시간 사례인 AI 토큰 스트리밍 에는 SSE 가 딱 맞아. OpenAI, Anthropic, Google 의 주요 LLM API 도 채팅 응답 스트리밍에 SSE 를 써. 브라우저의 EventSource 는 재연결을 알아서 처리하고, 평범한 HTTP 라 프록시도 잘 통과해. 클라이언트도 자주 보내야 할 때에야 SSE 를 벗어날 이유가 생겨.

cwkPippa 도 이렇게 흘려

cwkPippa 의 Claude, Codex, Gemini, Ollama 채팅 엔드포인트는 모두 SSE 로 응답해. 턴마다 HTTP POST 를 한 번 보내면 답이 data: 덩어리로 이어져 와. WebSocket 은 정말 양방향 통신이 필요한 자리에만 남겨뒀어. AI 를 스트리밍한다는 이유만으로 더 멋있어 보이는 WebSocket 을 고르지 마.

Code

브라우저 EventSource — 세 줄이면 끝·javascript
const source = new EventSource('/api/stream');

source.onmessage = (e) => {
  const data = JSON.parse(e.data);
  console.log('chunk:', data);
};

source.onerror = () => {
  // Browser will auto-reconnect with backoff.
  console.log('disconnected, will retry');
};
FastAPI SSE 엔드포인트·python
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import asyncio, json

app = FastAPI()

async def event_generator():
    while True:
        data = await get_next_event()  # your source
        # SSE wire format: 'data: <payload>\n\n'
        yield f'data: {json.dumps(data)}\n\n'

@app.get('/api/stream')
async def stream():
    return StreamingResponse(
        event_generator(),
        media_type='text/event-stream',
    )

External links

Exercise

위 FastAPI SSE 엔드포인트를 만들어 1초마다 심박 신호({ ts: ... }) 를 보내. 브라우저 개발자 도구에서 EventSource 를 열고 신호가 바로 들어오는지 확인해. 노트북 덮개를 30초 닫았다가 열어서, 재연결 코드를 쓰지 않았는데도 브라우저가 다시 붙는 모습까지 봐.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.