1. Controller작성
✔️kafkaTemplate.send메서드를 통해 메시지가 전송됨
@Slf4j
@CrossOrigin
@RestController
@RequestMapping(value = "/kafka")
public class ChatController {
@Autowired
private KafkaTemplate<String, Message> kafkaTemplate;
@PostMapping(value = "/publish")
public void sendMessage(@RequestBody Message message) {
log.info("Produce message : " + message.toString());
message.setTimestamp(LocalDateTime.now().toString());
try {
kafkaTemplate.send(KafkaConstants.KAFKA_TOPIC, message).get();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@MessageMapping("/sendMessage")
@SendTo("/topic/group")
public Message broadcastGroupMessage(@Payload Message message) {
return message;
}
}
2. React 프로젝트 생성
create-react-app을 이용해 만들어주었음
추가로 설치해야 할 모듈
npm install axios react-stomp sockjs
3. 컴포넌트 작성
✔️pages폴더 - view 담당.. 원래는 components폴더를 따로 나누고 해야되는데 지금은 생략
✔️services폴더 - api와 소통하는 서비스 코드들을 작성할 곳
3-1. Login.js
간단히 사용자 이름만 입력받는 형식
import React, { useState } from "react";
function Login({ handleOnSubmit }) {
const [name, setName] = useState("");
const handleOnChange = (e) => {
setName(e.target.value);
};
const handleSubmit = () => {
handleOnSubmit(name);
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
placeholder="사용할 닉네임을 입력하세요."
value={name}
onChange={handleOnChange}
/>
<button type="submit">Go!</button>
</form>
</div>
);
}
export default Login;
3-2. Chat.js, Input.js
침착하게 작성해줍니다.. 👇
import React from "react";
function Chat({ messages, currentUser }) {
const formattingTimestamp = (timestamp) => {
const date = new Date(timestamp);
let hour = date.getHours() < 10 ? `0${date.getHours()}` : date.getHours();
let min =
date.getMinutes() < 10 ? `0${date.getMinutes()}` : date.getMinutes();
return `${hour}:${min}`;
};
return (
<div className="chat-middle">
{messages.map((msg) => (
<li
className={`chat-bubble ${
msg.author === currentUser.name ? "send" : "receive"
}`}
>
<span>{msg.author}</span>
<p>{msg.content}</p>
<span>{formattingTimestamp(msg.timestamp)}</span>
</li>
))}
</div>
);
}
export default Chat;
import React, { useState } from "react";
function Input({ handleOnSubmit }) {
const [msg, setMsg] = useState("");
const handleOnChange = (e) => {
setMsg(e.target.value);
};
const handleSubmit = async (e) => {
e.preventDefault();
handleOnSubmit(msg);
setMsg("");
};
return (
<div className="chat-bottom">
<form onSubmit={handleSubmit}>
<input
placeholder="내용을 입력하세요."
value={msg}
onChange={handleOnChange}
onKeyPress={(e) => {
if (e.key === "Enter") {
handleSubmit(e);
}
}}
/>
<button type="submit">전송</button>
</form>
</div>
);
}
export default Input;
3-3. App.js
일단 import
import React, { useState } from "react";
import SockJsClient from "react-stomp";
import chatApi from "./services/chatapi";
messages는 대화 목록이 담길 리스트, user는 말그대로 유저..
const [messages, setMessages] = useState([]);
const [user, setUser] = useState(null);
onMessageReceived는 메시지가 도착하면 messages에 도착한 값을 더해줌 (concat을 이용해 뒤에 계속 추가됨)
handleMessageSubmit은 Input.js에 넘겨주는 함수... 서버로 전송
const onMessageReceived = (msg) => {
console.log("New Message Received!!", msg);
setMessages(messages.concat(msg));
};
const handleLoginSubmit = (name) => {
setUser({ name: name, color: randomColor() });
};
const handleMessageSubmit = (msg) => {
chatApi
.sendMessage(user.name, msg)
.then((res) => {
console.log("sent", res);
})
.catch((e) => {
console.log(e);
});
};
user값이 null이면 로그인을 먼저 하게 되어있음..
SockJsClient를 이용해서 소켓통신을 하게되는 것
✔️url - 서버의 웹 소켓 통신 url Spring Boot에서 WebSocketConfiguration작성할 때 적었던 endpoint값을 적어주면 됨
*포트번호를 임의로 수정하였음. 기본 포트는 8080
✔️onConnect / onDisconnect - 소켓 연결, 연결해제되었을 때 실행되는 콜백함수
✔️onMessage - 메시지를 받음
return (
<>
{user !== null ? (
<div className="chat-container">
<SockJsClient
url={"http://localhost:6002/my-chat/"}
topics={["/topic/group"]}
onConnect={console.log("connected!")}
onDisconnect={console.log("disconnected!")}
onMessage={(msg) => onMessageReceived(msg)}
debug={false}
/>
<Chat messages={messages} currentUser={user} />
<Input handleOnSubmit={handleMessageSubmit} />
</div>
) : (
<Login handleOnSubmit={handleLoginSubmit} />
)}
</>
);
전체코드👇
import React, { useState } from "react";
import SockJsClient from "react-stomp";
import chatApi from "./services/chatapi";
import "./styles.css";
import Chat from "./pages/Chat";
import Input from "./pages/Input";
import Login from "./pages/Login";
function App() {
const [messages, setMessages] = useState([]);
const [user, setUser] = useState(null);
const onMessageReceived = (msg) => {
console.log("New Message Received!!", msg);
setMessages(messages.concat(msg));
};
const handleLoginSubmit = (name) => {
setUser({ name: name, color: randomColor() });
};
const handleMessageSubmit = (msg) => {
chatApi
.sendMessage(user.name, msg)
.then((res) => {
console.log("sent", res);
})
.catch((e) => {
console.log(e);
});
};
const randomColor = () => {
return "#" + Math.floor(Math.random() * 0xffffff).toString(16);
};
return (
<>
{user !== null ? (
<div className="chat-container">
<SockJsClient
url={"http://localhost:6002/my-chat/"}
topics={["/topic/group"]}
onConnect={console.log("connected!")}
onDisconnect={console.log("disconnected!")}
onMessage={(msg) => onMessageReceived(msg)}
debug={false}
/>
<Chat messages={messages} currentUser={user} />
<Input handleOnSubmit={handleMessageSubmit} />
</div>
) : (
<Login handleOnSubmit={handleLoginSubmit} />
)}
</>
);
}
export default App;
4. chatapi.js
baseURL.. kafka/~~~로 가게됩니다..
sendMessage가 /kafka/publish로 전송(produce)됨
import Axios from "axios";
const api = Axios.create({
baseURL: "http://localhost:6002/kafka",
});
const chatAPI = {
getMessages: (groupId) => {
console.log("Calling get messages from API");
return api.get(`/messages/${groupId}`);
},
sendMessage: (username, text) => {
let msg = {
author: username,
content: text,
};
return api.post(`/publish`, msg, {
headers: { "Content-Type": "application/json" },
});
},
};
export default chatAPI;
5. 채팅!!!
뭔가 설명을 놓친게 있는 기분인데... 혹시 빠진게 있는 것 같다믄 댓글주세요...
'STUDY > Spring' 카테고리의 다른 글
Spring Boot | REST API 만들기 ( + IntelliJ Lombok추가) (0) | 2021.03.04 |
---|---|
Spring Boot | S3 Pre-Signed URL 생성 (0) | 2021.01.28 |
Spring Boot | Kafka를 이용한 채팅 (2) Kafka 연동 설정 (0) | 2021.01.13 |
Spring Boot | Kafka를 이용한 채팅 (1) Kafka설치 및 프로젝트 생성 (1) | 2021.01.12 |
Spring Boot | S3파일 업로드 후 CloudFront SignedURL 생성하기 (0) | 2020.12.24 |