[TeamBlog] SSE_Streaming_TroubleShooting - 100-hours-a-week/9-team-Devths-WIKI GitHub Wiki

AI 챗봇 SSE 스트리밍 트러블슈팅 정리

AI 채팅 응답을 실시간으로 보여주기 위해 SSE(Server-Sent Events) 스트리밍을 도입한 과정, 겪었던 어려움·해결 방법·현재 상태·추후 고도화 전략을 정리한 문서입니다.


목차

  1. 상황
  2. SSE란?
  3. SSE 스트리밍을 왜 썼는지
  4. 개발한 커밋 링크들
  5. 디스코드 대화들 분석
  6. 어떤 어려움이 있었는지
  7. 어떻게 해결했는지
  8. 현재는 어떤 상태인지
  9. 추후 고도화 전략

1. 상황

  • 배경: AI 챗봇(면접/채팅) 기능에서 LLM 응답을 한 번에 받지 않고, 토큰 단위로 실시간 전달하려는 요구가 있었음.
  • 제약: 프론트 ↔ BE(Spring Boot) ↔ AI 서버(FastAPI) 3단 구조에서, 어디서 스트리밍을 시작·중계할지, 어떤 프로토콜을 쓸지 결정이 필요했음.
  • 목표: 사용자가 질문을 보내면 응답이 순차적으로(스트리밍) 화면에 나타나도록 하고, 504/422 등 오류를 최소화하는 것.

작성 가이드:

  • 프로젝트·서비스 맥락을 2~3문장으로 요약.
  • “언제, 누가, 무엇을 위해 SSE를 도입하기로 했는지”를 한 줄로 적어도 됨.

2. SSE란?

  • 정의: Server-Sent Events. 서버가 클라이언트에게 한 방향(서버 → 클라이언트)으로 이벤트 스트림을 보내는 HTTP 기반 프로토콜.
  • 형식: Content-Type: text/event-stream, event, data, 주석 라인(:) 등으로 이벤트를 구분.
  • 특징:
    • HTTP 위에서 동작하므로 기존 인증·프록시·CORS 설정을 대부분 그대로 사용 가능.
    • 브라우저 EventSource API 또는 fetch + ReadableStream으로 수신.
    • 양방향 통신이 필요 없을 때 적합(채팅처럼 “사용자 → 서버”는 일반 API, “서버 → 사용자”만 스트리밍).

작성 가이드:

  • 팀 내 공용 설명용으로 1~2문단이면 충분. 필요 시 MDN SSE 링크 추가.

3. SSE 스트리밍을 왜 썼는지

3.1 다른 기술과 비교

방식 특징 채팅/면접 스트리밍에 적합한가
SSE 서버→클라이언트 단방향, HTTP 기반, 재연결·이벤트 ID 지원 ✅ 응답만 스트리밍하면 되므로 적합
WebSocket 양방향, 별도 프로토콜, 연결 유지 ⚠️ 필요하지만 구현·인프라 부담 큼
폴링(Polling) 주기적으로 API 호출 ❌ 지연·부하 증가, 실시간성 부족
일반 REST 요청 1회 → 응답 1회 ❌ 전체 응답이 끝날 때까지 대기, 체감 지연 큼

3.2 선택 이유 요약

  • 서버 → 클라이언트만 스트리밍하면 되고, 클라이언트 → 서버는 기존 REST(채팅 메시지 전송 등)로 처리 가능.
  • HTTP 기반이라 방화벽·프록시·Spring/FastAPI 연동이 단순함.
  • WebSocket보다 구현·운영 부담이 적고, “토큰이 조금씩 나오는” UX에 충분함.

작성 가이드:

  • 위 표는 예시. 팀에서 실제로 검토한 내용(WebSocket 제외 이유 등)을 한두 줄씩 보강하면 좋음.

4. 개발한 커밋 링크들

4.1 백엔드 (BE)

대표 커밋 예시

  • f9f0bb4 — feat: 챗봇 응답 API 구현 및 SSE Streaming 적용 (#55)

4.2 AI 서버 (Model)

대표 커밋 예시

  • 9b712c3b — Add SSE headers to chat endpoint
  • 08916a45 — Standardize SSE format and add ChromaDB None filtering

4.3 Notion 정리

  • AI ChatBot SSE Commit — 팀 내 커밋·작업 정리용 Notion 페이지 (위 문서와 연계해 사용).

작성 가이드:

  • 새 커밋이 생기면 위 “상세 이력” 문서와 Notion에 반영하면 일관성 유지에 좋음.

5. 디스코드 대화들 분석

  • 기간: (예: 2026-01-xx ~ 2026-01-xx)
  • 채널/스레드: (예: #ai-chatbot, #backend 등)
  • 주요 논의:
    • 504 타임아웃이 나는 구간(프록시 vs AI 서버 vs BE).
    • 422 검증 오류 원인(스키마·필드 누락).
    • SSE 포맷 불일치로 파싱 실패한 사례.
    • ChromaDB/벡터 검색 오류와 스트리밍 중단 연관성.
  • 결정 사항:
    • SSE heartbeat 도입, 헤더 명시, 404 재시도, 리포트 모드 422 전용 처리 등 (상세는 6·7절과 연결).

작성 가이드:

  • 개인정보·과도한 채팅 내용은 제외하고, “무엇을 논의했고 → 어떤 결론이 났는지” 위주로 1문단씩 정리하면 됨.

6. 어떤 어려움이 있었는지

  1. 504 Gateway Timeout

    • LLM 응답이 늦을 때 중간에 데이터가 없어 프록시/로드밸런서가 연결을 끊음.
  2. 422 Validation Error

    • 채팅/리포트 요청 시 model 등 필드 누락·타입 불일치로 AI 서버에서 검증 실패.
  3. SSE 파싱/연결 문제

    • 포맷 불일치·헤더 미설정으로 클라이언트/프록시가 스트림을 제대로 인식하지 못함.
  4. ChromaDB/RAG 오류

    • metadataNone이 들어가 쿼리 예외 발생 → 스트리밍 중단.
  5. BE ↔ AI 서버 연동

    • 분석 API URI 매핑 실패, 404 미처리, 비동기 task 조회 시점(“비동기 작업을 찾을 수 없습니다”) 등.

작성 가이드:

  • 실제로 겪은 이슈만 남기고, “증상 한 줄 + 원인 한 줄” 형태로 보강하면 좋음.

7. 어떻게 해결했는지

어려움 해결 방향 관련 커밋/문서
504 타임아웃 SSE heartbeat 도입, 로깅 강화 AI: 4a06f0e2, 이력(AI) §4
422 검증 오류 Swagger 예시·스키마 정리, 리포트 모드 전용 처리 AI: 108cbc79, fc88d09b, b38257a1
SSE 파싱/연결 SSE 포맷 표준화, Content-Type 등 헤더 명시 AI: 08916a45, 9b712c3b
ChromaDB None 쿼리 전 None 제거·필터링 AI: 08916a45
BE 분석 연동 URI 매핑 수정, 404 재시도, taskId 통합, DB 커밋 전 task 조회 수정 BE: dc10953, c9f4520, 342aced, 0ca1689, 이력(BE) §5

작성 가이드:

  • “어떤 설정/코드/배포 변경으로 해결했는지” 한 줄씩 추가하면 나중에 재발 방지에 도움됨.

8. 현재는 어떤 상태인지

  • 스트리밍:
    • (예: BE → 프론트 SSE 중계 정상 동작, AI 서버 heartbeat 적용 완료.)
  • API:
    • (예: 채팅/리포트 모드 스키마 정리됨, 분석 API 404 재시도·taskId 통합 반영.)
  • 알려진 제한:
    • (예: Nginx 버퍼링 시 스트리밍 지연 가능성, 특정 브라우저에서 EventSource 재연결 이슈 등.)
  • 모니터링/로깅:
    • (예: taskId 로깅, Log sanitized 적용, 504/422 구간 로그 보강.)

작성 가이드:

  • “지금 기준으로 무엇이 되고 / 무엇이 아직 불안한지”를 2~3문장으로 적으면 됨.

9. 추후 고도화 전략

  1. 안정성

    • 스트리밍 구간 재연결(backoff), 타임아웃 설정 정리, 에러 이벤트 포맷 통일.
  2. 관찰성

    • SSE 이벤트 타입별 메트릭(지연, 실패 횟수), 대시보드/알람 연동.
  3. 프로토콜

    • 필요 시 WebSocket 검토(양방향·저지연 요구 시), SSE와 공존 전략.
  4. 클라이언트

    • EventSource fallback, 네트워크 끊김 시 재연결·메시지 복구 UX.
  5. 문서·운영

    • Runbook(504/422 대응 절차), 신규 멤버용 SSE 연동 가이드.

작성 가이드:

  • 우선순위(예: P0/P1)나 담당 레이어(BE/AI/프론트)를 표시해 두면 실행 계획 세우기 좋음.

문서 이력

날짜 작성/수정 내용
(작성일) 초안 작성, 목차·가이드 확정