@Configuration
@EnableWebSocket
@RequiredArgsConstructor
public class WebSocketConfig implements WebSocketConfigurer {
private final SimpleWebSocketHanlder simpleWebSocketHanlder;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// connect url로 websokcet연결 요청이 들어오면,핸들러 클래스가 처리
registry.addHandler(simpleWebSocketHanlder,"/connect")
// securityConfig 에서의 cors 예외 처리는 http요청에 대한 예외, 따라서 websocket 프로토콜에 대한 요청에 대해서는 별도의 cors 설정 필요
.setAllowedOrigins("http://localhost:3000");
}
}
웹소켓은 STOMP 와 달리 /connect url 로 들어오면 핸들러가 처리함
filter 에서 인증객체 만듬을 예외처리해주어야 한다.
1. tokent filter 제외
2.cors 설정 별도
// connect로 웹소켓 요청이 들어왔을 때 이를 처리할 클래스
@Component
public class SimpleWebSocketHanlder extends TextWebSocketHandler {
// 웹소켓 Config 에 핸들러로 등록
//연결된 세션 관리:스레드 safe한 Set 사용
private final Set<WebSocketSession> sessions= ConcurrentHashMap.newKeySet();
// Set 자료구조에다가 사용자의 연결정보를 등록 Session 안에 사용자의 정보가 들어가 있다.
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
sessions.add(session);
System.out.println("Connected: "+session.getId());
}
// 정보를 보냄
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
// 메시지가 들어오면 String 형태로 payload로 꺼냄
String payload=message.getPayload();
System.out.println("received message"+payload);
for (WebSocketSession s : sessions) {
if(s.isOpen()){
s.sendMessage(new TextMessage(payload));
}
}
}
// Set 자료구조에다가 사용자의 연결정보를 해제
// 채팅방은 따로 구현이 필요하다.
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
sessions.remove(session);
System.out.println("");
}
}
Set에다가 연결이 되면 세션을 추가시키고 그리고 payLoad에서 정보를 꺼내다가 정보를 보내고
연결이 끊기면 세션을 제거한다.
순수 웹소켓: 포스트맨,
STOMP : 프론트맨으로 처리를 한다.
웹소켓 (ws:// ) 로 양방향 통신이 매겨진다.
프론트 코드
<template>
<v-container>
<v-row justify="center">
<v-col cols="12" md="8">
<v-card>
<v-card-title class="text-center text-h5">
채팅
</v-card-title>
<v-card-text>
<div class="chat-box">
<div
v-for="(msg, index) in messages"
:key="index"
>
{{ msg }}
</div>
</div>
<v-text-field
v-model="newMessage"
label="메시지 입력"
@keyup.enter="sendMessage"
/>
<v-btn color="primary" block @click="sendMessage">전송</v-btn>
</v-card-text>
</v-card>
</v-col>
</v-row>
</v-container>
</template>
<script>
export default{
data(){
return {
ws: null,
messages: [],
newMessage: ""
}
},
created(){
this.connectWebsocket();
},
beforeUnmount() {
this.disconnectWebSocket();
},
methods: {
// 순수 웹소켓을 위한 자바스크립트 라이브러리
connectWebsocket(){
this.ws = new WebSocket("ws://localhost:8080/connect");
// 연결 성공
this.ws.onopen = () => {
console.log("succeessfully connected!!");
}
this.ws.onmessage = (message) => {
this.messages.push(message.data);
this.scrollToBottom();
}
this.ws.onclose = () => {
console.log("disconnected!!")
}
},
// 전송버튼
sendMessage(){
// 양쪽이 다 짤려있으면 보내고
if(this.newMessage.trim() === "")return;
this.ws.send(this.newMessage);
// newMessage를 다시 비워줌
this.newMessage = ""
},
//
scrollToBottom(){
// 이런 함수가 있다.
this.$nextTick(()=>{
const chatBox = this.$el.querySelector(".chat-box");
// scrollTop 을 Height 만큼 맞추겠다.
chatBox.scrollTop = chatBox.scrollHeight;
})
},
disconnectWebSocket(){
if(this.ws){
// 연결객체가 있으면 연결을 끊겠다.
this.ws.close();
console.log("disconnected!!")
this.ws = null;
}
}
},
}
</script>
<style>
.chat-box{
height: 300px;
overflow-y: auto;
border: 1px solid #ddd;
margin-bottom: 10px;
}
</style>
data() : 처음 데이터 초기화
프론트에서는 메시지가 들어오면 ws 연결객체를 처리를 한다.
메시지를 보내면 ,연결이 끊기면 각각에 대해서 처리를 한다.
전송버튼, 스크롤 버튼, 연결을 끊는 작업이 다 있다.
순수 웹소켓은 postman으로 테스트가 가능하지만 ,STOMP의 테스트는 프론트로 테스트가 필요하다 .
'채팅' 카테고리의 다른 글
채팅방 STOMP + REDIS의 PUB/SUB 기능 구현 (0) | 2025.06.19 |
---|---|
채팅방 ERD 설계 + 구조 (0) | 2025.06.17 |
STOMP (0) | 2025.06.16 |
WebSocket 통신 (1) (0) | 2025.06.16 |
AWS 기본 정리(1) (0) | 2025.03.21 |