LLM 스트리밍 응답의 HTTP Raw 구조 이해하기
대부분의 대형 언어 모델(LLM: Large Language Model) API는 실시간 응답 속도를 높이기 위해 스트리밍 응답(Streaming Response) 방식을 사용합니다. 대표적인 예로 Ollama, OpenAI, Claude 등의 API는 청크 전송 인코딩(Chunked Transfer Encoding)을 통해 응답을 전달합니다. 이 글에서는 스트리밍 응답이 HTTP 레벨에서 어떻게 전달되는지, 그 장단점은 무엇인지, 그리고 curl로 확인하는 방법을 설명합니다.
스트리밍 응답 vs 일반 응답
| 구분 | 일반 응답 | 스트리밍 응답 |
| 응답 방식 | 결과를 완성한 후 한 번에 전송 | 결과를 조각(chunk)으로 나눠 실시간 전송 |
| 헤더 | Content-Length 포함 | Transfer-Encoding: chunked |
| 클라이언트 반응 | 응답 완료까지 대기 | 순차적으로 실시간 처리 가능 |
| 사용 사례 | 검색, 간단한 API | 채팅, 실시간 생성 AI |
스트리밍의 장단점
장점
빠른 사용자 반응성
전체 결과를 기다리지 않고, 생성되는 즉시 전송 가능
사용자에게 실시간 타이핑 효과 등의 자연스러운 경험 제공
낮은 메모리 사용량
- 서버나 클라이언트 모두 결과 전체를 메모리에 저장할 필요 없이 처리 가능
대용량 데이터 전송에 적합
- 수십 MB 이상의 응답을 쪼개서 안정적으로 전송 가능
실시간 처리 가능
- 로그 스트림, AI 생성, 뉴스 피드 등 실시간 처리에 매우 유리
단점
후처리 어려움
- 전체 결과를 한 번에 받지 않으므로, 요약이나 정렬 등 후처리가 어려움
구현 복잡도
- 클라이언트는 스트리밍 조각을 실시간으로 조합하거나 출력해야 하므로 복잡성 증가
중간 끊김에 민감
- 연결 중단 시 복구가 어려울 수 있고, 전체 요청을 다시 보내야 할 수도 있음
디버깅 어려움
- 응답이 점진적으로 오기 때문에 중간 상태를 디버깅하거나 테스트하는 것이 번거로움
Transfer-Encoding: chunked 구조
HTTP/1.1에서 스트리밍 응답을 구현하기 위해 사용하는 표준 방식은 chunked transfer encoding입니다.
구조:
[청크 길이 (16진수)]\r\n
[청크 데이터]\r\n
각 청크는 이렇게 반복되고, 마지막에 0\r\n\r\n을 보내며 스트림 종료를 알립니다.
예시:
HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
1c
{"response":"Black ","done":false}
1a
{"response":"holes are ","done":false}
1b
{"response":"very dense.","done":true}
0
curl로 확인하는 방법
curl을 사용하면 스트리밍 응답을 쉽게 관찰할 수 있습니다.
curl -vN http://localhost:11434/api/generate \
-H "Content-Type: application/json" \
-d '{
"model": "llama3",
"prompt": "Explain black holes.",
"stream": true
}'
-v: HTTP 요청/응답 로그 출력
-N: 출력 버퍼링 비활성화 (stream 대응)
출력은 다음과 같이 한 줄씩 출력됩니다:
{"response":"Black ","done":false}
{"response":"holes are ","done":false}
{"response":"very dense.","done":true}
한번에 받으려면?
스트리밍이 아닌 일반 응답으로 전환하려면 stream 옵션을 false로 설정하면 됩니다.
curl http://localhost:11434/api/generate \
-H "Content-Type: application/json" \
-d '{
"model": "llama3",
"prompt": "Explain black holes.",
"stream": false
}'
이 경우에는 전체 결과가 완성된 후 한 번에 출력됩니다.
마무리
LLM API의 응답을 스트리밍 방식으로 처리할 수 있다는 것은 빠른 사용자 경험과 메모리 효율을 제공하는 강력한 기능입니다. 하지만 이를 제대로 활용하기 위해서는 HTTP 수준의 작동 방식과 스트리밍의 특성을 이해하는 것이 중요합니다. 이 글이 Chunked Transfer Encoding의 구조, 장단점, 활용법에 대한 이해를 높이는 데 도움이 되었기를 바랍니다.