Spring의 Stomp를 이용하여 채팅방 구현
WebSocket을 좀 더 효율적으로 다룬 프로토콜로서, 기존에 사용했던 WebSocket보다 더 편리하다.
기존의 WebSocket은 일일히 Handler로 코드를 작성해야 했는데 ,STOMP를 사용하면 메시지를 전송하는 상황에서, subscriber와 publisher(sender)를 지정하여 편리하게 이용하도록 한다.

<aside> 💡 동작 원리
클라이언트(Sender)가 메시지를 보내면 stomp통신으로 서버에 메세지가 전달된다.
Controller의 @MessageMapping에 의해 메시지를 받는다.
Controller의 @SendTo으로 특정 topic을(/1) 구독(/room)하는 클라이언트에게 메세지를 보낸다. (구독은 /room으로 보면 되고 특정 topic은 채팅 방 id인 /1로 보면 된다. →/room/1}
</aside>
implementation 'org.springframework.boot:spring-boot-starter-websocket'
implementation 'org.webjars:webjars-locator-core'
implementation 'org.webjars:sockjs-client:1.0.2'
implementation 'org.webjars:stomp-websocket:2.3.3'
implementation 'org.webjars:bootstrap:3.3.7'
implementation 'org.webjars:jquery:3.1.1-1'
@Configuration
@EnableWebSocketMessageBroker
@RequiredArgsConstructor
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws-stomp")
.setAllowedOriginPatterns("*")
.withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
// 서버가 클라이언트로 메시지를 보낼 때 사용하는 경로(prefix)를 설정하는 부분
// 서버에서 특정 방의 모든 클라이언트에게 메시지를 보내고 싶을 때, "/room/{roomId}"와 같은 형식의 주소를 사용
config.enableSimpleBroker("/room");
// 프론트엔드에서 서버로 메시지를 보낼 때 사용하는 경로(prefix)를 설정
config.setApplicationDestinationPrefixes("/send");
}
}
@EnableWebSocketMessageBroker으로 webSocket 관련 설정을 작동시킨다.
그리고 WebSocketMessageBrokerConfigurer를 implements하고 위와 같은 메서드를 오버라이딩해서 작성한다.
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Chat {
@Id @GeneratedValue
@Column(name = "chat_id")
private Long id;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "room_id")
private Room room;
private String sender;
@Column(columnDefinition = "TEXT")
private String message;
@CreatedDate
@Column(updatable = false)
private LocalDateTime sendDate;
@Builder
public Chat(Room room, String sender, String message){
this.room = room;
this.sender = sender;
this.message = message;
this.sendDate = LocalDateTime.now();
}
public static Chat createChat(Room room,String sender,String message){
return Chat.builder()
.room(room)
.sender(sender)
.message(message)
.build();
}
}
@Entity
@Setter
@Getter
@NoArgsConstructor()
public class Room {
@Id
@GeneratedValue
@Column(name ="room_id")
private Long id;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name="final_match_id")
private FinalMatch finalMatch;
}
Room은 채팅방에 대한 엔티티이고, Chat는 채팅 기록을 저장하는 엔티티이다. 간단하게 편의상 지연 로딩 X