보통 서버에게 정보를 요청할 때 http/https 통신을 거치게 된다. 이것은 클라이언트가 서버에게 요청을 했을 때 서버가 해당하는 정보를 응답해주는 구조이다
그러나 채팅은 누군가 대화를 보내면 내가 서버에게 요청을 보내지 않아도 서버가 나 자신에게 정보를 주어야한다 이럴 때 웹소켓을 사용한다
stomp 는 tcp 또는 websocket 같은 양방향 네트워크 프로토콜 기반으로 동작(신뢰성 프로토콜 )
stomp 는 text 지향 프로토콜이나 message payload 에는 text or binary 데이터를 포함할 수 있다.
stomp 는 pub/sub 란 메시지를 공급하는 주체와 소비하는 주체를 분리해 제공하는 메시징 방법
stomp 는 http 에서 모델링되는 Frame 기반 프로토콜이다 Frame 은 몇 개의 text line 으로 지정된 구조
COMMAND
header1: value1
header2: value2
(공백)
Body
COMMAND : SEND ,SUBSCRIBE 지시
header 의 destination 을 사용해서 이 헤더로 메시지를 보내거나 구독할 수 있음
/sub/chat/room/
+ roomId, callback함수) 를 통해 구독한 채팅방이 보낸 메시지 받음@EnableWebSocketMessageBroker
@Configuration
public class StompWebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/stomp/chat")
// 도메인허용 .setAllowedOrigins("http://api.tildp.shop","http://www.tildp.shop","http://localhost:8080")
.withSockJS();
}
/*어플리케이션 내부에서 사용할 path를 지정할 수 있음*/
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/pub");
registry.enableSimpleBroker("/sub");
}
}
채팅방 입장 부분 코드
@MessageMapping 을 통해 웹소켓으로 들어오는 메세지 발행을 처리한다. 클라이언트에서는 "/pub/chat/enter" 로 발행 요청을 하면 Controller가 해당 메세지를 받아 해당 주소를 구독하고 있는 사용자에게 메시지 발행
=> 메세지가 발행되면 "/sub/chat/room/[roomId]"로 메세지가 전송되는 것을 볼 수 있다.
=> Client 에서는 해당 주소를 구독하고 있다가 메시지가 전달되면 화면에 출력한다 .
=> 기존의 핸들러 ChatHandler 의 역할을 대신 해줌 핸들러 필요 없어짐
@MessageMapping(value = "/chat/enter")
public void enter(ChatMessageDTO message) {
String id = message.getRoomId();
Long room_id = Long.valueOf(id);
// chat user 정보 저장 (채팅유저 , 채팅방)
ChatRoom chatRoom = chatRoomRepository.findByRoomId(room_id).orElseThrow(
() -> new NullPointerException("해당 채팅방이 존재하지 않습니다."));
User user = userRepository.findByUsername(message.getWriter()).orElseThrow(
() -> new NullPointerException("해당 사용자가 존재하지 않습니다."));
if (!(chatUserRepository.findByChatRoomAndUser(chatRoom, user).isPresent())) { //채팅방 처음입장
ChatUser chatUser = new ChatUser(user, chatRoom);
chatUserRepository.save(chatUser);
int count =chatUserRepository.countByChatRoom(chatRoom);
chatRoom.setCount(count);
chatRoomRepository.save(chatRoom);
message.setMessage("채팅방에 참여하였습니다.");
template.convertAndSend("/sub/chat/room/" + message.getRoomId(), message);
}
else
{
message.setMessage("채팅방에 재입장하였습니다.");
template.convertAndSend("/sub/chat/room/" + message.getRoomId(), message);
}
}
https://velog.io/@dltndudvlzm/%EB%82%B4%EC%9D%BC%EB%B0%B0%EC%9B%80%EC%BA%A0%ED%94%84-211215-TIL
내가 오늘 잘 정리해놓은 글이다 . 참고바람 >_<