회사 신규 중계 플랫폼을 개발하면서 쪽지가 오면 실시간 알람 기능이 필요하다는 요청사항이 존재했다, 해당 서비스를 구성하기 위해서
처음에는 WebSocket를 생각했지만 추후에 SSE(Server Sent Events)
라는 기술이 존재함을 알게 되어 개발 방향의 포커스를 두었다
HTTP의 주요 특징은 비연결성이다, 따라서 SSE 참고 사진과 같은 통신을 위해서는 Client와 지속적으로 연결이 되어 있어야 한다
이를 해결 방식으로는 Polling, Long Polling, Socket, SSE방식이 존재한다 해당 방식의 대해 먼저 공부해보자
클라이언트가 주기를 갖고 Http Request를 서버로 전송하여 이벤트 내용을 수신하는 방식
클라이언트가 계속적으로 요청을 보내기 때문에 클라이언트의 수가 증가하면 서버의 부하가 걸림
실시간 정도의 빠른 응답을 수신하기는 어려움
Http OverHead가 발생함
데이터 갱신이 일정한 주기를 갖고, 실시간성이 중요하지 않다면 고려해볼수 있는 방법
유지 시간을 길게 갖는다는 점에서 Polling 방식과의 차이점이 존재함
서버에서 클라이언트에게 요청을 보내고 서버에서 변경이 일어날 때까지 대기하는
서버에서 변화가 일어나면 클라이언트로 response를 전송 ( 이벤트 캐치 )
클라이언트 요청이 주기를 갖고 반복적으로 일어나지 않기 때문에 서버에 부하가 Polling 방식보다 감소함
하지만 이벤트의 주기가 잦다면 Polling과의 큰 차이점을 얻을 수 없음
Long Polling 방식은 실시간 전달이 중요하지만 상태가 빈번히 갱신되지 않는 경우
WebScokt은 HTTP와 같은 프로토콜의 일종, 양방향 실시간 통신을 실현하기 위한 구조
최초 접속은 일반 HTTP 요청을 이용한 handshaking으로 이루어짐
한번 접속된 Socket은 HTTP 통신과 같이 연결을 종료하는것이 아니라 접속을 유지함
웹소켓을 활용하면 용량이 큰 Http Header를 최초 접속시에만 보내고 더이상 보내지 않아 리소스면에서 이득을 볼 수 있음
웹소켓 포트에 접속해있는 모든 클라이언트에게 이벤트 방식으로 응답이 가능함
SSE도 WebScokt과 같이 HTTP 요청을 이용하여 handshaking 통하여 connection을 맺음
WebScokt과 같이 양방향 통신이 아닌 오직 Server가 Client로만 전송
WS와 같은 별도의 프로토콜이 아닌 HTTP로 통신하기 때문에 구현의 용이성이 존재함
접속에 문제가 있으면 자동으로 재연결을 시도하지만, 클라이언트가 close해도 서버에서 감지하기 어려움
SSE를 채택한 이유는 아래와 같다
Data는 오직 서버에서 클라이언트로 한방향으로 통신한다
Letter가 생성된 시점에 수신하는 유저에게 새로운 메세지의 팝업을 띄우긴 위한 데이터를 실시간으로 송수신한다
클라이언트는 서버에게 데이터를 송신할 필요가 없다
SSE의 통신 과정을 위에서 설명을 했다 싶이 Client는 SSE와 TCP 통신을 통해 connection을 맺어야 한다
Node.js, JAVA 에선 이벤트 타입을 text/event-stream
을 표준으로 지정해주어야 된다고 하는데
NestJS 프레임워크에서는 @SSE()
컨트롤러 데코레이터 하나로 처리가 가능하다 즉 Subscription을 하게 되는 셈이다
NestJS에서 데이터의 수신과 송신은 RXJS로 진행된다 쪽지를 송신하는 부분에서 해당 Objervable한 Subject에 next(push)하게 된다
해당 Subject를 Observable한 상태로 변환후에 해당 데이터를 filter와 pipe를 통하여 알맞은 유저에게 전송한다
추가로 유저의 행동을 감시해 클라이언트가 close해도 서버에서 감지하기 어려움
의 단점을 해결하기 위해서
해당 유저는 Stream에서 제거하게 된다
위와 같은 과정으로 나는 SSE subscription 과정을 마무리했다, 다음 본문에는 내가 기억하기 위한 예제 코드를 작성할 예정이다
회사 코드를 그대로 갖고 올수는 없으니 간단한 예제 코드로 변형할 예정이다