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 사이 다른 작업 자유.
여기서 reconnect를 공짜라고 오해하면 안 돼. transport가 다시 붙는 것과 application state가 이어지는 건 다른 문제야. client는 마지막으로 완전히 처리한 event가 뭔지 알아야 하고, server는 중복 delivery가 와도 같은 chunk를 두 번 확정하지 않게 설계해야 해. stream은 길게 열린 HTTP response일 뿐, 기억까지 대신해 주진 않아.
또 한 가지. token 하나씩 바로 그린다고 항상 UX가 좋아지는 건 아니야. 너무 잘게 render하면 layout과 Markdown parser가 매 token마다 흔들려. wire에서는 세밀하게 받아도 UI에서는 짧게 batch해서 그릴 수 있어. durability boundary, transport boundary, presentation cadence를 같은 것으로 뭉개지 마. 셋은 서로 다른 책임이야.
사실 SSE의 장점은 기능이 적다는 데 있어. 이 흐름에 client-to-server 실시간 제어나 다중 channel multiplexing이 정말 필요해질 때만 WebSocket을 검토해. 이름이 더 강해 보여서 protocol을 키우면, heartbeat부터 reconnect까지 운영 책임도 함께 커져.