실시간 텍스트 스트리밍을 위한 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을 사용