2024 09 20
2024-09-20¶
SSE (Server-Sent Events)¶
참고: https://hyuk0309.tistory.com/24 참고: https://velog.io/@alswn9938/SSE%EB%9E%80 참고: https://developer.mozilla.org/ko/docs/Web/API/Server-sent_events/Using_server-sent_events 참고: https://tecoble.techcourse.co.kr/post/2022-10-11-server-sent-events/
- 개요
- 서버 -> 클라이언트 실시간으로 데이터를 전송하는 기술
- 컨셉: HTTP Connection 길게 유지. 서버 -> 클라이언트 데이터 전송
- 서버 -> 클라 text message를 보내는 브라우저 기반 웹 어플리케이션 기술
- HTTP의 persistence connections 기반 HTML5 표준 기술
- vs Polling
- Short Polling: 주기적으로 API 찔러서 변경사항 확인
- 장: 준 실시간 | 단: 서버 요청수 너무 많아짐
- Long Polling: 데이터 변경이 있을 때 까지 기다리다가 응답
- 장: HTTP 요청 수 감소 | 단: 어쨋든 데이터 변경 시마다, HTTP Connection 맺어야 함
- Short Polling: 주기적으로 API 찔러서 변경사항 확인
- SSE
- HTTP Connection 한번만 맺음
- 잦은 HTTP 요청 X -> 응답시간 Up, 디바이스 배터리 사용률 Low
- SSE 원리
- HTTP Connection 유지
- HTTP/1.0 -> header Connection keep-alive
- HTTP/1.1 -> 트랜잭션 끝나도 연결 유지해서 따로 설정 X
- HTTP/2.0 -> 하나의 HTTP 커넥션에 HTTP 요청 이뤄져서 설정 X
- 그 외 설정
- HTTP Request
- Accept Header: text/event-stream
- HTTP Response
- Content-Type: text/event-stream
- Cache-Control: no-store
- HTTP Request
- HTTP Connection 유지
- SSE Event format
- field/value (field 종류: event/data/id/retry)
- event는
\n\n으로 구분 - 인코딩 UTF-8
-
SSE 통신 과정
-
[Client] SSE Subscribe 요청
- 서버의 이벤트 구독을 위한 요청 보냄
-
[Server] Subscription에 대한 응답
- Response 미디어 타입
text/event-stream
- Response 미디어 타입
- [Server] 이벤트 전달
- 클라이언트에서 Subscribe 하면, 서버는 해당 클라이언트에게 비동기적으로 데이터 전달
- 서로 다른 이벤트
\n\n구분,name:value로 구성
-
- [Client] SSE
// 클라이언트 측은 들어오는 이벤트 처리하는 부분 웹소켓과 거의 유사 const evtSource = new EventSource("/event/sse", { withCredentials: true, }) // event 필드가 없는 메시지는 `message` 이벤트로 수신됨. -> 해당 message 이벤트 수신을 위해서는 핸들러를 추가해야 함 evtSource.onmessage = function (e) { const newElement = document.createElement('li'); const eventList = document.getElementById('list'); newElement.textContent = "message: " + e.data; eventList.appendChild(newElement); } // 사용자 지정 이벤트 수신 -> event 필드를 갖는 서버의 메시지들은 event에 명시된 이름의 이벤트로 수신됨 evtSource.addEventListener('count', (e) => { setCount(e.data); }) evtSource.addEventListener('push', (e) => { const data = JSON.parse(e.data); addPush(data); }) evtSource.onerror = (e) => { alert("failed!"); } // 닫기 evtSource.close();
- vs Websocket
- Websocket: 클라 <-> 서버 양방향, 둘이 프로토콜도 다름
- SSE: 서버 -> 클라 단방향