SSE with Node.js for Real-Time Text Streaming

실시간 텍스트 스트리밍을 위한 SSE(Node.js) 구현

카테고리

프로그래밍/소프트웨어 개발

서브카테고리

웹 개발

대상자

  • *대상자**: 웹 애플리케이션 개발자, 실시간 데이터 스트리밍 구현에 관심 있는 개발자
  • *난이도**: 중급 이상 (Node.js, NestJS, SSE 기술 이해 필요)

핵심 요약

  • SSE 선택 이유:

- 가볍고 효율적인 프로토콜 (Single HTTP 연결, 낮은 오버헤드)

- 자동 재연결 기능 (built-in retry mechanism)

- 원ative 브라우저 지원 (추가 라이브러리 필요 없음)

  • 핵심 구현 요소:

- NestJS 서버 구현: EventSource 사용, safeWrite 헬퍼 함수, onmessage/onerror 이벤트 처리

- 생산성 측정: 1GB RAM 서버에서 1000~2000개 동시 연결 처리, 평균 지연 시간 100ms

- 보안 강화: JWT 인증, rate-limiter 서비스 통합

섹션별 세부 요약

1. 기술 비교 및 SSE 선택

  • WebSocket vs Long Polling vs SSE:

- WebSocket: 높은 오버헤드, 양방향 통신 가능

- Long Polling: 반복적 HTTP 요청, 높은 메모리 사용

- SSE: 최소한의 오버헤드, 자동 재연결, 모던 브라우저 지원

  • SSE의 적합성:

- 일방향 스트리밍 (AI 텍스트 생성, 뉴스 알림 등)

- 라이브러리 없이도 구현 가능

2. 서버 구현 (NestJS 기반)

  • SSE 라우트 정의:

- /api/run 경로에서 EventSource 헤더 설정

- streamHandler 함수로 OpenAI 스트리밍 API 호출

  • 스트리밍 처리:

- try/catch 블록으로 오류 처리

- done: true 이벤트로 스트리밍 종료 알림

- safeWrite 헬퍼 함수: 스트림 종료 여부 확인

3. 클라이언트 측 처리

  • StreamProcessor 클래스 구현:

- EventSource를 통해 SSE 엔드포인트 연결

- onmessage 이벤트로 JSON 파싱 및 UI 업데이트

- onerror 이벤트로 오류 로깅 및 자원 정리

  • 스트리밍 데이터 예시:

```json

data: {"title":"Summary of the Minisforum UM870 Mini PC","commandId":1749186088941}

data: {"content":"##","commandId":1749186088941}

data: {"done":true,"commandId":1749186088941}

```

4. 생산성 측정 및 성능

  • 메모리 사용량: 약 40KB/연결
  • 동시 연결 수: 1GB RAM 서버에서 1000~2000개 처리 가능
  • 지연 시간: 100ms (AI 토큰 생성 → 브라우저 렌더링)
  • CPU 사용량: 이전 polling 구현 대비 40% 감소

5. 보안 및 확장성 고려

  • 인증: Authorization 헤더의 bearer token으로 JWT 검증

- 실패 시 401 Unauthorized 응답

  • 레이트 제한: 사용자 ID 기반 rate-limiter 서비스 호출

- 429 Too Many Requests 응답 (민감한 타이밍 정보 제외)

  • 연결 종료 처리: close 이벤트 감지 시 AI 스트리밍 요청 중단

6. SSE의 한계와 대안

  • 이진 데이터 전송: WebSocket이 더 적합
  • 양방향 통신: 채팅 애플리케이션은 WebSocket 사용
  • 구형 브라우저 지원: IE11은 폴리필 또는 대체 방식 필요

결론

  • SSE 활용 팁:

- 실시간 텍스트 스트리밍에 SSE를 선택, NestJS로 효율적으로 구현

- safeWrite 함수onmessage/onerror 이벤트 처리로 안정성 확보

- JWT 인증레이트 제한으로 보안 강화

- SSE의 한계를 인지하고, 이진 데이터나 양방향 통신이 필요한 경우 WebSocket을 사용