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

SSE Wire Format — 100 줄짜리 spec

~22 min · sse, wire-format, raw

Level 0Tokenizer
0 XP0/54 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

Server-Sent Events 는 100-line spec 이지 100-page 아냐. data: <json>\n\n 이 한 event. 빈 줄이 delimiter. data: [DONE] 이 종료. 끝.

Frame 구조

한 frame = 한 줄 이상의 field: value, 빈 줄로 종료. OpenAI 에서 실제로 보는 field — data: (JSON payload), : (comment, 일부 proxy 가 keep-alive 로 사용 — ignore). Terminator 는 literal line data: [DONE].

왜 직접 알아야

SDK 의 iter_lines() 가 framing 을 처리하지만 — 어느 날 corporate proxy 가 keep-alive comment (':' 시작 줄) 박기 시작하면 hand-rolled parser 가 깨짐. Spec 알면 그 사고 5 분 안에 진단.

Raw 로 parse 해 보기

Raw httpx client.stream 으로 streaming 호출 + iter_lines 로 frame 받아서 직접 parse. data: prefix 분리, JSON load, [DONE] 감지. SDK 가 어떤 일을 하는지 직접 본 사람과 안 본 사람의 디버깅 능력 차이.

Code

httpx.stream 으로 raw SSE 읽기·text
data: {"id":"chatcmpl-...","choices":[{"delta":{"content":"Hello"},"finish_reason":null}]}

data: {"id":"chatcmpl-...","choices":[{"delta":{"content":" world"},"finish_reason":null}]}

data: {"id":"chatcmpl-...","choices":[{"delta":{},"finish_reason":"stop"}]}

data: [DONE]
data: 라인과 [DONE] sentinel parse·text
event: response.created
data: {"type":"response.created","response":{...},"sequence_number":1}

event: response.output_text.delta
data: {"type":"response.output_text.delta","delta":"Hello","sequence_number":5}

event: response.completed
data: {"type":"response.completed","response":{...},"sequence_number":15}

External links

Exercise

Raw httpx.stream 으로 streaming Chat Completions 호출 — SDK 없이. SSE frame 직접 parse. (1) data event 수, (2) keep-alive comment (':' 줄) 수, (3) [DONE] terminator print.

Progress

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

댓글 0

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

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