- 이번 우리 스쿼드의 3분기 목표는
유저끼리 실시간 대화가 가능하게 만들자!
였기 때문에 채팅 서비스를 준비하게 되었다
채팅의 특성상실시간성
보장이 필요하므로실시간 통신
에 대해 먼저 파악해보았다
Http로 가능한 실시간 통신 방법
기본적으로 Http protocol은 단방향 프로토콜이면서 stateless의 특징이 있어 실시간 통신에 적합하지 않지만, 현재 우리 서비스는 Http만 사용중이기 때문에 Http로 가능한 실시간 통신 방법을 먼저 파악해보았다
Http Polling
polling
은 web browser가 주기적으로 server에게 이벤트가 발생했는지 확인
하는 방식이다
이벤트가 발생한 경우에만 response에 이벤트 정보가 포함되며, 발생하지 않았다면 response에는 이벤트 정보가 포함되지 않는다
이벤트 발생여부 확인을 위해 주기적인 요청, 응답이 오가기 때문에 time interval을 어떻게 잡느냐에 따라 서버의 부하가 증가하거나 실시간성이 떨어지는 trade off를 가진다
Long Polling
long polling은 기존 polling의 실시간성을 보완한 방식이다
web browser 요청 시, 이벤트가 발생하기 전까지는 response를 보내지 않고
, 이벤트가 발생할 때만 response에 이벤트 정보를 포함해 보낸다
server의 이벤트가 자주 발생하는 경우
라면 오히려 비효율적
인 트래픽이 발생할 수 있다
Socket
web socket을 사용하면 web browser에서도 socket 통신처럼 실시간으로 데이터를 주고 받을 수 있다
HTTP 통신과의 차이점으로는 HTTP는 client가 server에 요청하는 것이지만, Web Socket은 양방향 요청
이 가능하다
HTTP와 동일하게 80, 443 port를 사용할 수 있다
동작 과정
- web socket 연결을 위해
http 통신
을 한다 handshake
과정을 성공하면 http -> web socket protocol로 변경하는protocol switching
이 이루어진다- web socket을 위한
socket이 생성
된다
실시간성에서 HTTP vs Web Socket
- HTTP는 client가 응답을 원하는 경우, 항상 서버에 먼저 요청을 보내야한다 = 단방향 통신
-
web socket은 연결이 계속 유지되고 있는 상태이다 = 양방향 통신
=> 채팅에서 상대방의 메시지가 도착했는지 계속해서
server에게 확인해보지 않아도
된다
- Http는 요청 시마다 header 정보를 보내야한다
-
web socket은 최초 접속 시에만 http protocol 위에서 handshaking을 하기때문에 header 정보를 보낸다
=> 자주 통신을 해야하는 실시간 서비스이기 때문에
네트워크 비용
에서 이득이다
-
web socket은 client와 server가 한번 연결되면 같은 라인으로 통신한다 한번 연결이 수립된 후로는 간단한 메시지만 오가는 방식이다
=> Http 사용 시 발생되는
불필요한 Http와 TCP 연결 트래픽을 피할
수 있다
처음에 얕은 지식으로 예상했었는데, 역시 web socket이 실시간 통신에 있어서 더 유리해보인다
polling은 실시간 통신이라 부르기엔 좀 애매한듯한 느낌
그럼 이제는 web socket과 관련된 내용들을 더 자세히 알아봐야지
Web Socket의 한계와 관련사항
Socket.io
최근에는 대부분의 web browser가 websocket 프로토콜을 지원하지만, 일부 환경(사파리, 익스플로어, 파이어폭스와 같은 구버전)에서는 지원하지 않는다
Socket.io는 nodejs 기반의 실시간 이벤트 서버를 개발할 수 있는 오픈소스 라이브러리로,
요청을 보낸 web browser가 web socket을 지원하는지 확인해보고, 지원하지 않는다면 실시간성을 제공
해주는 라이브러리이다
스프링의 경우 SocketJS를 지원한다
STOMP
web socket
은 기본적으로 text와 binary 타입의 메시지만을 양방향으로 주고받을 수 있는 protocol이다
그 메시지를 어떤식으로 주고받을지는 따로 정해진 것이 없으
며, 주고받을 수 있게 해줄 뿐 그 이상의 일을 하지 않는다 주고 받은 문자열의 해독은 application에 맡긴다
Http는 형식을 정해두어서 모두가 약속을 따르기만 하면 해석할 수 있지만, web socket은 형식이 정해져 있지않아 application에서 해석이 쉽지 않다
그래서 web socket 방식은 STOMP 등의 sub protocol을 사용해 주고받는 메시지의 형태를 약속
하는 경우가 많다
해당 메세지가 어떤 요청인지, 어떻게 처리해야 하는지에 따라 채팅방과 세션을 일일이 구현하고 메세지 발송 부분을 관리하는 추가 코드를 구현할 필요가 줄어든다
STOMP(Simple Text Oriented Message Protocol)
란 web socket 위에서 동작하는 간단한 텍스트기반 message protocol로,
client와 server가 전송할 메시지의 유형, 형식, 내용들을 정의
하는 매커니즘이다
TCP와 web socket과 같은 신뢰할 수 있는 양방향 streaming network protocol에서 사용할 수 있고,
기본적으로 pub/sub 구조
로 되어있어 메세지를 전송하고 받아 처리하는 부분이 확실히 정해져있다
pub/sub 구조이기 때문에 broker를 통해
다른 사용자들에게 메세지를 보내거나 서버가 특정 작업을 수행하도록 메세지를 보낼 수 있다
Http와 마찬가지로 frame을 사용해 전송하는 프로토콜이다
Frame
STOMP는 COMMAND, header, Body
라는 형식으로 골격이 정의되어 있다
COMMAND
header1:value1
header2:value2
Body^@
따라서 web socket만 사용했을 때는 서버에서 보는 그냥 날 것의 메시지만 오고가지만, STOMP를 사용하면 command, header, body의 형태로 메시지가 오고간다
통신 흐름
- 구독자들은
/topic
경로를 구독하고 있다 - 발신자는 서버를 통한 가공 및 처리를 위해
/app
주소로 메시지를 송신한다 - 가공을 마친 메시지를
/topic
이라는 경로에 담아서 전송하면 그 메시지를 message broker가 전달받는다 - message broker는 그 메시지를
/topic
을 구독중인 구독자들에게 최종적으로 전달한다
장점
- messaging protocol과 messaging 형식을 개발할 필요가 없다
- 하위 protocol과 message convention을 정의할 필요가 없다
- 형식을 고민하고, 파싱하는 코드를 구현할 필요가 없다
- 연결 주소마다 새로운 handler를 구현하고 설정해줄 필요가 없다
- message broker를 사용하면 구독을 관리하고 메시지를 broadcast 하는데에 사용할 수 있다
- 외부 messaging queue 를 사용할 수 있다 ex) RabbitMQ, Kafka 등
Pub/Sub
pub/sub은 메세지를 공급하는 주체
와 소비하는 주체
를 분리해 제공
하는 메세징 방법이다
우체통에 빗대어보자면
-
우체통 = 채팅방 생성 = pub/sub 구현을 위한
topic 생성
-
신문 구독 신청 = 채팅방 입장 =
topic 구독
-
구독한 신문이 우체통에 오면 봄 = 채팅방에서 메세지를 송수신 = 해당 topic으로
메세지를 송신(pub)
,메세지를 수신(sub)
- 우체통(topic)이 있다면 집배원(publisher)이 신문을 우체통에 배달
- 구독자(subscriber)는 우체통에 신문이 배달되는 것을 기다렸다가 빼서 봄
구독자는 다수
가 될 수 있음
Spring에서 지원하는 STOMP
Spring에서 지원하는 STOMP를 사용하면 spring websocket application
은 STOMP broker로 동작
한다
Spring에서 지원하는 STOMP는 Simple In-Memory Broker
를 이용해 subscribe 중인 다른 client들에게 메세지를 보내
주며,
이 때 Simple In-Memory Broker는 client의 subscribe 정보를 자체적으로 메모리에 유지
하고 있다
또한 RabbitMQ, ActiveMQ, Kafka 같은 외부 메세징 시스템을 STOMP broker로 사용
할 수 있도록 지원한다
Spring은 메세지를 외부 broker에게 전달하고, broker는 websocket으로 연결된 client에게 메세지를 전달한다
이 구조로 Http 기반의 보안 설정과 공통된 검증 등을 적용할 수 있다
SpringBoot 사용중이니까 STOMP, SocketJS 그리고 broker로 RabbitMQ 적용하기로!
RabbitMQ 정리도 부지런히 해두어야쥐
Reference
Web socket
Socket.io
STOMP
실시간 서비스 경험기(배달운영시스템)
웹소켓과 STOMP, Spring Messaging을 통한 실시간 통신 이해하기
Web Polling, Long Polling, Server-sent Events, WebSocket