Spring Websocket & STOMP - 실시간 채팅 기능

한동훈·2022년 8월 30일
0

항해99

목록 보기
28/29
post-thumbnail

WebSocket으로 채팅서버 구현하기

 WebSocket : 

    기존의 단방향 HTTP 프로토콜과 호환되어 양방향 통신을 제공하기 위해 개발된 프로토콜.

    일반 Socket통신과 달리 HTTP 80 Port를 사용하므로 방화벽에 제약이 없으며 통상 WebSocket으로 불린다.

    접속까지는 HTTP 프로토콜을 이용하고, 그 이후 통신은 자체적인 WebSocket 프로토콜로 통신하게 된다.

Sever-Sent Event : 서버에서 일방적으로, 단방향

STOMP : Simple Text Oriented Messaging Protocol의 약자.

     STOMP 는 원래 Ruby, Python 및 Perl과 같은 스크립팅 언어가 엔터프라이즈 메시지 브로커에 연결하기 위해 생성된 간단한 텍스트 지향 메시징 프로토콜입니다. 
     WebSocketHandler를 직접 구현할 필요 없이, @MessaingMapping 같은 어노테이션을 사용해서, 메시지 발행 시 엔드포인트를 별도로 분리해서 관리할 수 있다.
     pub/sub 기반으로 동작한다.

나의 생각 정리:

기본적으로 폴링기술_사용자가 서버에 정보를 요청하고 서버에서 그에 맞게 정보를 응답해주는 이런 반복적인 방법

SSE(Sever-SentEvent)기술_주식사이트,날씨등 업데이트가 필요한 정보들을 계속적으로 서버에서 클라이언트쪽으로 보내주는 단방향적인 기술. 
 
또한 채팅과 같이 양방향 통신이 필요하여, 웹소켓(Websocket)기술의 등장_기본적으로 TCP(1:1연결을 지향하며, 각각 클라이언트와 서버를 뜻한다.)연결을 통해서 양방향 통신 채널을 제공하는 기술이다. 
 
웹소켓은 HTTP로 Handshake_(직역하면 '악수'라는 뜻이다. 마치 우리가 다른 사람과의 첫 만남에서 만나서 악수를 요청하고 악수를 받듯이,정상적인 통신을 하기 전에, 일련의 과정을 거쳐 연결을 성립시키는 것을 말한다) 를 통해, 초기 통신을 시작한 후, 웹소켓 프로토콜로 변환하여, 데이터를 전송한다. 

ws 와 wss 차이점은?

일반적으로 우리는 보안을 위해서 HTTP 통신이 아닌 HTTPS을 해야 한다. 
웹소캣 통신시 ws가 아닌 wss로 통신해야 시큐어 통신이 가능하다. 
회사 업무에서는 반드시 wss로 구축해야한다.

스프링부트에서 웹소켓 연동하는 방법

의존성을 추가
implementation 'org.springframework.boot:spring-boot-starter-websocket'

외부 메시지 브로커가 필요한 이유

여러개의 서버를 이용하고 있다면, 위와 같은 상황에서 
발행자가 메시지를 보내면 사용자3은 메시지를 받지 못할 것이다.


위와 같은 상황을 개선하기 위해서, 외부 메시지 브로커가 필요하다.

발행자가 서버1에 메시지를 보냈을때, 서버1에서는 메시지 브로커의 exchange에 메시지를 전달한다. 외부메시지 브로커에 바인딩 되어 있는 사용자1,2,3큐에 메시지를 전달하게 되며, 다른 서버인 서버2에 연결중인 사용자3에게도 메시지를 보낼 수 있게 된다. 즉, 웹소켓 서버에 관계없이 구독중인 채널의 메시지를 받을 수 있게 된다.

외부 브로커 연동을 위한 RabbitMQ 사용

(RabbitMQ 를 사용하기 위해서는 Erlang 이라는게 먼저 설치가 되어 있어야 한다. 왜냐? RabbitMQ가 Erlang이라는 언어로 만들어서 그렇다고 한다. 
출처: https://oingdaddy.tistory.com/165 [SI Supply Depot:티스토리])

RabbitMQ는 오픈 소스 메시지 브로커 소프트웨어로서, AMQP를 구현하였으며 그 이후로 STOMP, MQTT 등의 프로토콜을 지원하기 위해 플러그인 구조와 함께 확장되고 있다.

인메모리 기반 시스템 : 메시지 유실 가능성이 있음, 메시지 모니터링이 쉽지 않음. 

외부 브로커 연동의 단점 : 인프라 비용이 증가.

RabbitMQ 이용방법 :

1) Erlang을 먼저 설치
2) RabbitMQ Windows에 맞게 설치
3) cmd 키고, RabbitMq 설치경로로 지정한 곳의 sbin 폴더로 진입한다.(cmd 창에서 cd 경로입력)
4) cmd창에 rabbitmq-plugins enable rabbitmq_management 입력
5) 아래와 같은 로그들이 나온다.

  Enabling plugins on node rabbit@HANDONGHUN:
  rabbitmq_management
  The following plugins have been configured:
    rabbitmq_management
    rabbitmq_management_agent
    rabbitmq_web_dispatch
  Applying plugin configuration to rabbit@HANDONGHUN...
  The following plugins have been enabled:
    rabbitmq_management
    rabbitmq_management_agent
    rabbitmq_web_dispatch

  set 3 plugins.
  Offline change; changes will take effect at broker restart.
  
 6) RabbitMQ Management 접속방법http://localhost:15672 로 할 수 있다. 
 접속을 하면, 로그인창이 나타나는데 guest / guest 로 접속할 수 있다. 
  
관련 설명 : https://www.rabbitmq.com/management.html

Troubleshooting :

1. 에러 : 
    RabbitMQ management 사용시 cmd 창에서 실행을 위한 rabbitmq-plugins enable rabbitmq_management 코드 입력 시, 
    계속적인 아래와 같은 Plugin configuration unchanged 가 발생 

    에러 관련 코드 :
        Enabling plugins on node rabbit@HANDONGHUN:
        rabbitmq_management
        The following plugins have been configured:
          rabbitmq_management
          rabbitmq_management_agent
          rabbitmq_web_dispatch
        Applying plugin configuration to rabbit@HANDONGHUN...
        Plugin configuration unchanged.

    해결방법 :
    1) 재시작 코드 : net stop rabbitmq && net start rabbitmq >> 이래도 계속 문제발생...
    2) 삭제 후, 재 설치 >> 바뀌는건 없음 ... 계속 Plugin configuration unchanged
    3) https://blog.katastros.com/a?ID=01700-63e94fd9-f75b-4939-8d57-c1f62984fee9 참조하여, 순서대로 따라하기 
    4) rabbitmq-plugins.bat list 입력후, 플러그인이 enable되었다는것을 확인 후에, 다시 재시작을 하니깐 정상적으로 작동한다....왜 갑자기 되는지 모르겠다...

2. 에러 : RabbitMQ서버가 연결되지 않는 문제

에러 관련 코드 : 
2022-09-01 17:25:46.961  INFO 2924 --- [ient-loop-nio-7] o.s.m.s.s.StompBrokerRelayMessageHandler : TCP connection failure in session _system_: Failed to connect: Connection refused: no further information: localhost/127.0.0.1:61613
io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: no further information: localhost/127.0.0.1:61613
Caused by: java.net.ConnectException: Connection refused: no further information
    at java.base/sun.nio.ch.SocketChannelImpl.checkConnect(Native Method) ~[na:na]
    at java.base/sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:777) ~[na:na]
    at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:337) ~[netty-transport-4.1.79.Final.jar:4.1.79.Final]
    at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:334) ~[netty-transport-4.1.79.Final.jar:4.1.79.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:710) ~[netty-transport-4.1.79.Final.jar:4.1.79.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658) ~[netty-transport-4.1.79.Final.jar:4.1.79.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584) ~[netty-transport-4.1.79.Final.jar:4.1.79.Final]
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496) ~[netty-transport-4.1.79.Final.jar:4.1.79.Final]
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) ~[netty-common-4.1.79.Final.jar:4.1.79.Final]
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.79.Final.jar:4.1.79.Final]
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.79.Final.jar:4.1.79.Final]
    at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]


해결방법 :
        1) rabbitmq-plugins enable rabbitmq_web_stomp
        2) rabbitmq-plugins enable rabbitmq_web_stomp_examples
       	3) 순서대로 RabbitMQ Service - start에 입력을 하니 제대로 실행 됨.

위와 같이 다 하고 나니, 아래와 같이 Connections이 잘 이루어짐.

Apic에서 Queue를 생성 하기.

Queue생성을 확인 할 수 있다.


새로운 크롬을 실행해서 메세지를 발행 해주면, 아래와 같이 서로 통신이 되는 모습을 볼 수 있다.

Mygithub

https://github.com/hdonghun/-RabbitMQ-

References :

https://brunch.co.kr/@springboot/695#comment
https://oingdaddy.tistory.com/165
https://blog.csdn.net/weixin_45410882/article/details/114742310

profile
돌덩이

0개의 댓글