wongakim-99 / websocket-chatting

웹소켓을 활용한 채팅 연습
0 stars 0 forks source link

Stomp로 채팅서버 고도화 #5

Closed wongakim-99 closed 1 month ago

wongakim-99 commented 1 month ago

1,2,3,4 이슈에서 websocket을 통하여 간단산 서버/클라이언트 통신을 구현해 보았다. 메시징 방식을 잘 정의한다면 websocket만으로도 충분히 좋은 서버/클라이언트 소켓 서버를 완성할 수 있다. 하지만 단순한 통신 구조로 인해 websocket만을 이용해 채팅을 구현하면 해당 메시지가 어떤 요청인지, 어떻게 처리해야 되는지에 따라 채팅룸과 세션을 일일이 구현하고 메시지 발송 부분을 관리하는 추가 코드를 구현해 줘야 한다.

이번 이슈에서는 Websocket의 프로세스를 좀 더 고도화하고 메시징에 좀 더 최적화된 방식을 구현하기 위해 Stomp 방식을 적용해 보겠다.

wongakim-99 commented 1 month ago

Stomp란?

Stomp란 메시징 전송을 효율적으로 하기 위해 나온 프로토콜이며 기본적으로 pub/sub 구조로 되어있어 메시지를 발송하고, 메시지를 받아 처리하는 부분이 확실히 정해져 있기 때문에 개발하는 입장에서 명확하게 인지하고 개발할 수 있는 이점이 있다. 또한 Stomp를 이용하면 통신 메시지의 헤더에 값을 세팅할 수 있어 헤더 값을 기반으로 통신 시 인증처리를 구현하는 것도 가능하다.

pub/sub란 메시지를 공급하는 주체와 소비하는 주체를 분리하여 제공하는 메시징 방법이다. 기본적인 콘셉트를 예로 들면 우체통(topic)이 있으면 집배원(publisher)이 신문을 우체통에 배달하는 액션이 있고, 우체통에 신문이 배달되는 것을 기다렸다가 빼서 보는 구독자(subscriber)의 액션이 있다. 여기서 구독자는 여러명이 될 수 있다. pub/sub 컨셉을 채팅룸에 대입하면 아래와 같다.

wongakim-99 commented 1 month ago

Stomp를 사용하기 위해 @EnableWebSocketMessageBroker을 선언하고 WebSocketMessageBrokerConfigure를 상속받아 configureMessageBroker를 구현한다. pub/sub 메시징을 구현하기 위해 메시지를 발행하는 요청의 prefix는/pub로 시작하도록 설정하고 메시지를 구독하는 요청의 prefix는 /sub로 시작하도록 설정. 그리고 stomp websocket의 연결 endpoint는 /ws-stomp로 설정한다. 따라서 개발서버의 접속 주소는 다음과 같이 된다.

ws:.//localhost:8080/ws-stomp

wongakim-99 commented 1 month ago

채팅 방 DTO 수정

pub/sub 방식을 이용하면 구독자 관리가 알아서 되므로 웹소켓 세션 관리가 필요 없어진다. 또한 발송의 구현도 알아서 해결되므로 일일이 클라이언트에게 메시지를 발송하는 구현이 필요 없어진다. 따라서 채팅방 DTO는 다음과 같이 간소화된다.

wongakim-99 commented 1 month ago

채팅방 Repository 생성

채팅방을 생성하고 정보를 조회하는 Repository를 생성한다. 실습에서는 간단하게 만들 것이므로 채팅방 정보를 Map으로 관리하지만, 서비스에서는 DB나 다른 저장 매체에 채팅방 정보를 저장하도록 구현해야 한다. 그리고 ChatService는 ChatRoomRepository가 대체하므로 삭제한다.

ChatController 수정 (publisher 구현)

@MessageMapping을 통해 Websocket으로 들어오는 메시지 발행을 처리한다. 클라이언트에서는 prefix를 붙여서 /pub/chat/message 로 발행 요청을 하면 Controller가 해당 메시지를 받아 처리한다. 메시지가 발행되면 /sub/chat/room/{roomId}로 메시지를 send 하는 것을 볼 수 있는데 클라이언트에서는 해당 주소를 (/sub/chat/room/{roomId}) 구독 (subscribe)하고 있다고 메시지가 전달되면 화면에 출력하면 된다. 여기서 sub/chat/room/{roomId}는 채팅룸을 구분하는 값이므로 pub/sub에서 Topic의 역할이라고 보면 된다.

기존의 WebSockChatHandler가 했던 역할을 대체하므로 WebSockChatHandler는 삭제한다.

구독자(subscriber) 구현

서버단에는 따로 추가할 구현이 없다. 웹뷰에서 stomp 라이브러리를 이용해서 subscriber 주소를 바라보고 있는 코드만 작성하면 된다.

ChatRoomController 생성

Websocket 통신 외에 채팅 화면 View 구성을 위해 필요한 Controller를 생성한다.

채팅 화면(view) 생성

채팅방리스트(생성), 채팅방 상세 화면을 위한 view를 구현한다. /resource/templates 하위에 room.ftl, roomdetail.ftl 두 개 파일을 생성한다. 해당 파일은 freemaker 형식으로 생성(.ftl) 되었지만 껍데기만 그렇게 생성 하고 내부 로직은 vue.js를 통해 구현되었다. 또한 기본 UI는 bootstrap로 구성되어있다.