C.W.K.
Stream
Lesson 04 of 06 · published

SSE 스트리밍 — 토큰 단위로 브라우저까지

~15 min · sse, streaming

Level 0호기심
0 XP0/65 lessons0/17 achievements
0/100 XP to next level100 XP to go0% complete

WebSocket 대신 SSE 인 이유

SSE (Server-Sent Events) 는 단방향: server push, client listen. WebSocket 은 양방향. client 가 prompt 하나 보내고 server 가 token 을 stream 하는 chat 에선 SSE 가 정답 모양 — 더 단순, HTTP middleware 와 잘 어울림, reconnect 무료.

wire format

SSE 는 HTTP 위 text/event-stream 일 뿐. 각 event 는 data: <payload>\n\n. browser 의 EventSource API 또는 fetch + ReadableStream reader 가 parse.

Async 제너레이터 → SSE

FastAPI 의 StreamingResponse 가 어떤 iterable 든 받음. async 제너레이터가 string yield, FastAPI 가 각각을 network 로 flush. event loop 는 yield 사이 다른 작업 자유.

Write before show: browser 로 yield 되는 모든 chunk 가 이미 JSONL ground truth 에 영속화돼야 해. JSONL append 실패 시 yield X. 이게 '아빠한테 깨진 채팅 보여드리지 마' 의 코드 표현 (Truth track, lesson 1).

Code

Server side — SSE event yield 하는 async generator·python
async def event_stream(req: ChatRequest):
    yield f"data: {json.dumps({'type':'session','id':session_id})}\n\n"
    async for chunk in adapter.stream(req.prompt):
        # eager append to JSONL ground truth — must succeed before yield
        await jsonl_logger.append(conversation_id, chunk)
        yield f"data: {json.dumps(chunk)}\n\n"
    yield f"data: {json.dumps({'type':'done'})}\n\n"
Client side — ReadableStream parser (TypeScript)·ts
async function* parseSSE(response: Response): AsyncGenerator<SSEEvent> {
  const reader = response.body!.getReader();
  const decoder = new TextDecoder();
  let buf = '';
  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    buf += decoder.decode(value, { stream: true });
    const lines = buf.split('\n\n');
    buf = lines.pop()!;
    for (const line of lines) {
      if (line.startsWith('data: ')) {
        yield JSON.parse(line.slice(6));
      }
    }
  }
}

Progress

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

댓글 0

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

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