서버 클라이언트 통신

특징

  • 서버쪽에서 클라이언트에게 지속적으로 스트리밍 하는 기술
  • HTTP 1.1 에 Persistent Connections Chunked Transfer Encoding, 기술 이용
    • Persistent Connections:
      • 지속연결기능 (Connection: keep-alive 해더)
    • Chunked Transfer Encoding:
      • 서버에서 데이터를 여러번 걸쳐서 보낼 수 있게 해주는 기술

WebSocket 대비 장 단점

결론적으로 SSE는 최적화, 안정성, 베터리 소모 부분에서 우월함을 가진다.
따라서 굳이 구현하려는게 서버쪽에서만 데이터를 보내줘야하는 서비스는 SSE 로 구현 하자

단점

  • 서버 쪽 단방향 통신
    • 요청 시 데이터를 보내는건 가능
  • 바이너리 데이터 전송 불가 (Base64로 변환 해야함)

장점

  • WebSocket 은 전용 서버를 따로 구축해야한다는 문제가 있는데
    SSE는 해더 설정 한번이면 끝
  • 서버와 연결이 끊길이 3초마다 재접속 시도
  • 최적화 배터리 소모량 부분에서 좋음

구현

서버

  • 보낼 때 아예 응답을 보내서 커넥션을 종료하면 안되고
    일부 데이터 스트림을 보내주는 함수를 쓰자

해더 구성

  • Content-Typetext/event-stream 으로 설정 하기만 하면됨
    GET /SSE HTTP/1.1
    Content-Type: text/event-stream
    Cache-Control: no-cache
    Connection: keep-alive
    • Connection: keep-alive: 커넥션 유지
    • Cache-Control: no-cache 브라우저에서 케싱 하지 않게끔

메시지 구조

event: message\n\n
 
data: 보낼데이터\n\n
 
 
  • event: 기본값 (message)
    • 클라이언트에 보낼 이벤트 지정
    • 클라이언트는 해당 이벤트에 맞춰 이벤트 리스너를 구성
  • data:
    • 해당 부분에 보낼 메시지 입력하면됨
    • UTF-8 만 지원
  • \n\n:
    • 줄바꿈을 두 번 한걸 표현하기 위해서 둠
    • 실제 코드짤때 표현 한 것처럼 \n\n 으로 줄바꿈 두번 해야함

클라이언트

  • 여기선 js로 구현
// SSE 클라이언트 객체 생성
const eventSource = new EventSource(`/sse`);
 
// 서버로부터 데이터가 오면
eventSource.addEventListener("message", (e) => {
    console.log(e.data);
});
 
// 만일 서버쪽에서 event: notification 으로 설정하면 해당 리스너에서 받을 수 있다
/* eventSource.addEventListener("notification", (e) => {
    console.log(e.data);
}); */
 
// connection되면
eventSource.addEventListener("open", (e) => {
    console.log("SSE 서버연동");
});
 
// error 나면
eventSource.addEventListener("error", () => {
    if (e.readyState === EventSource.CLOSED) {
        console.log("서버 중단");
    }
});

사용 예

  • 주식 실시간 호가
    • 클라이언트 쪽에서는 종목 코드 하나만 보내주면 따로 보낼 데이터는 없기에
  • 실시간 채팅
    • 채팅방 아이디를 식별자로 가져서 요청하여 모든 메시지를 서버쪽에서 스트리밍 받게 설계