Streaming 은 magic 이 아니라 UX 야. 사용자는 첫 200ms 를 느껴. Non-streaming 3 초 호출은 broken 처럼 느껴지고, streaming 4 초인데 첫 token 이 300ms 에 오면 instant 처럼 느껴져. 사용자 향 텍스트는 항상 stream.
Sync vs Async iter
Sync 는 for chunk in stream:, async 는 async for chunk in stream:. 매 chunk 의 텍스트는 chunk.choices[0].delta.content — None 가능성 항상 체크 (첫 chunk 는 role 만, 마지막 chunk 는 finish_reason 만).
Stream 은 항상 close
Stream object 는 HTTP connection 을 들고 있어. with stream: / async with stream: 쓰거나 try/finally 에서 stream.close(). 여기서 leak 은 3 주 후 'production 이 connection cap 왜 친 거야' 가 됨.
stream 안 할 때
Backend pipeline 이 final string 만 필요하면 stream 안 해. 사람 눈이 wire 를 안 보면 streaming overhead (per-chunk 파싱, accumulator state) 가 buy 하는 게 0.