10일차
2024. 8. 1. 18:44ㆍFCB2O4
오늘은 저번에 얻은 채팅 프로그램을 리액트로 변환하고자 한다.
먼저 백엔드 쪽에서의 설정
WebConfig
package b2o4.common.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*");
}
}
리액트와 연결할 때 리액트의 로컬호스트3000을 받아들임을 명시하는 설정을 작성하고
WebSocketConfig
package b2o4.common.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws").setAllowedOrigins("http://localhost:3000").withSockJS();
// registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS();
}
}
엔드포인트와 메시지 발신지점을 설정
ChatController
package b2o4.controller;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RestController;
import b2o4.vo.ChatMessage;
@RestController
public class ChatController {
@MessageMapping("/chat.send")
@SendTo("/topic/messages")
public ChatMessage send(ChatMessage message) {
return message;
}
}
컨트롤러에서 리액트와 연결할 부분을 매핑해준 후
리액트를 작성.
먼저 package.json 에서
{
"name": "b2o4-frontend",
"version": "0.1.0",
"private": true,
"proxy": "http://localhost:9001",
"dependencies": {
"@stomp/stompjs": "^7.0.0",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^13.0.0",
"@testing-library/user-event": "^13.2.1",
"axios": "^1.7.2",
"bootstrap": "^5.3.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.25.1",
"react-scripts": "5.0.1",
"sockjs-client": "^1.6.1",
"web-vitals": "^2.1.0"
},
npm i @stomp/stompjs
npm i web-vitals
npm i sockjs-client
등 필요한 것들을 모두 설치 한 후
LiveChat
import React, { useState, useEffect } from 'react';
import { Client } from '@stomp/stompjs'; // Client from 'stomp/stompjs' -> @stomp/stompjs
import SockJS from 'sockjs-client';
const LiveChat = () => {
const [messages, setMessages] = useState([]);
const [message, setMessage] = useState('');
const [stompClient, setStompClient] = useState(null);
const [connected, setConnected] = useState(false);
useEffect(() => {
const socket = new SockJS('http://localhost:9001/ws'); // java 쪽의 서버포트 설정과 맞춰서 작성
const client = new Client({
webSocketFactory: () => socket,
connectHeaders: {},
debug: function (str) {
console.log('STOMP Debug:', str);
},
onConnect: function (frame) {
console.log('STOMP Connected:', frame);
setConnected(true);
client.subscribe('/topic/messages', (response) => { // java 쪽의 컨트롤러(@SendTo)와 맞춰서 작성
const newMessage = JSON.parse(response.body);
setMessages((prevMessages) => [...prevMessages, newMessage]);
});
},
onStompError: function (frame) {
console.error('STOMP Error:', frame);
},
onWebSocketError: function (error) {
console.error('웹소켓 에러:', error);
}
});
client.activate();
setStompClient(client);
return () => {
if (client) {
client.deactivate();
}
};
}, []);
const sendMessage = () => {
if (stompClient && connected && message) {
stompClient.publish({
destination: '/app/chat.send', //java 쪽의 컨트롤러(@MessageMapping)와 맞춰서 작성
body: JSON.stringify({ sender: 'User', content: message })
});
setMessage('');
} else if (!connected) {
console.error('연결이 안됩니다. 관리자에 문의하세요.');
}
};
return (
<div>
<div>
{messages.map((msg, index) => (
<div key={index}>
<strong>{msg.sender}</strong>: {msg.content}
</div>
))}
</div>
<input
type="text"
value={message}
onChange={(e) => setMessage(e.target.value)}
disabled={!connected}
/>
<button onClick={sendMessage} disabled={!connected}>
Send
</button>
{!connected && <p>서버 연결중...</p>}
</div>
);
};
export default LiveChat;
이제 시현
일단은 성공