피드로 돌아가기
Streaming LLM responses to the browser in Go (Server-Sent Events)
Dev.toDev.to
Backend

SSE 기반 Go 스트리밍으로 LLM 응답 대기 시간을 1초 미만으로 단축

Streaming LLM responses to the browser in Go (Server-Sent Events)

Ayi NEDJIMI2026년 5월 25일10intermediate

Context

LLM 응답 완료 후 전체 데이터를 전송하는 기존 방식의 높은 지연 시간으로 인한 UX 저하 발생. 400토큰 기준 4~8초의 대기 시간이 필수적인 구조적 한계 존재.

Technical Solution

  • WebSocket 대비 오버헤드가 적고 단방향 전송에 최적화된 Server-Sent Events(SSE) 채택
  • text/event-stream 콘텐츠 타입 설정 및 X-Accel-Buffering: no 헤더를 통한 Nginx 프록시 버퍼링 제거
  • Go Fiber의 BodyWriter를 사용하여 LLM API로부터 수신한 토큰을 실시간으로 클라이언트에 push하는 파이프라인 설계
  • HTTP 상태 코드로 변경 불가능한 SSE 특성을 고려하여 애플리케이션 레벨의 Error Event를 통한 In-band 에러 핸들링 구현
  • context.WithTimeoutdefer cancel() 적용으로 클라이언트 연결 종료 시 Goroutine 누수 방지

Impact

  • 응답 시작 시간(First Token)을 4~8초에서 1초 미만으로 단축
  • Goroutine의 낮은 메모리 점유율(4KB)을 통해 단일 서버에서 수만 개의 동시 연결 처리 가능

Key Takeaway

사용자 체감 성능(Perceived Performance) 향상을 위해 데이터 생성과 전송을 분리하는 Streaming 아키텍처 도입 필요. 특히 상태 기반 연결보다 가벼운 SSE를 통해 인프라 복잡도를 최소화하면서 실시간성을 확보하는 설계 원칙 도출.


- Nginx 환경에서 SSE 사용 시 `X-Accel-Buffering` 설정 확인 - 스트림 시작 후 발생하는 런타임 에러는 HTTP Status가 아닌 JSON 데이터 내 error 필드로 정의 - 클라이언트 연결 해제 시 서버 자원 반환을 위한 Context Lifecycle 관리 - 브라우저 EventSource API의 자동 재연결 메커니즘 활용 검토

원문 읽기