채팅

웹소켓 통신

전한준 2025. 6. 16. 18:13
@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