이전까지는 메세지가 들어오면 콘솔창에 메세지를 보여주었지만, 이제 화면에 보여주도록 할 것!
html파일, 현재 프로젝트 기준으로는 home.pug파일에 ul에 li를 추가해서 메세지가 들어가도록 만들 것이다!
// 소켓에 메세지가 들어오면
socket.addEventListener("message", (message) => {
// console.log("New message:", message.data);
// console창말고 프론트에 메세지 띄워주기
const li = document.createElement("li");
li.innerText = message.data;
messageList.append(li);
});
/src/views/home.pug
main
form#nick
input(type="text", placeholder ="choose a nickname", required)
button Save
ul
form#message
input(type="text", placeholder ="write a msg", required)
button Send
/src/public/js/app.js
const nickForm = document.querySelector("#nick");
const messageForm = document.querySelector("#message");
//받은 메세지를 객체로 만들고 string화
function makeMessage(type, payload) {
const msg = { type, payload };
return JSON.stringify(msg);
}
//프론트엔드에서 백엔드 그러니까 서버로 값을 보내주기
function handleSubmit(event) {
//preventDefault 를 해주지 않으면 submit 됨과 동시에 창이 다시 실행됨.
event.preventDefault();
const input = messageForm.querySelector("input");
socket.send(makeMessage("new_message", input.value));
// 보내줬으니까 비워주기(안해줘도 되던데...?)
input.value = "";
}
//닉네임
function handleNickSubmit(event) {
event.preventDefault();
const input = nickForm.querySelector("input");
socket.send(makeMessage("nickname", input.value));
}
messageForm.addEventListener("submit", handleSubmit);
nickForm.addEventListener("submit", handleNickSubmit);
=>
backend에 JSON.stringify로 변환시켜준 값을 보내주고 그대로 받아옴!
backend에 javascript object를 보내지 않는 이유는 연결하고 싶은 frontend와 backend서버가 javascript서버가 아닐 수도 있기 때문!
backend에서는 다양한 프로그래밍 언어를 사용할 수 있음. websocket은 브라우저에 있는 API인데 이 API가 어떠한 판단도 하면 안되기 때문에 string타입으로만 보내줌!
지금은 string으로 백에보내주고 다시 받아오는데, 이제 backend에서 이 string을 javascript object로 바꿔주는 작업을 할 것!
src/server.js
socket.on("message", (message) => {
// string => object
const parsed = JSON.parse(message);
switch (parsed.type) {
case "new_message":
// 각각의 연결된 소켓 모두에게 메세지 전달(보낸 나도 포함)
sockets.forEach((aSocket) => aSocket.send(parsed.payload));
case "nickname":
console.log(parsed.payload);
}
// switch를 if대신에사용
// if (parsed.type === "new_message") {
// // 각각의 연결된 소켓 모두에게 메세지 전달(보낸 나도 포함)
// sockets.forEach((aSocket) => aSocket.send(parsed.payload));
// } else if (parsed.type === "nickname") {
// console.log(parsed.payload);
// }
});
=>여기서 더 나아가서 닉네임과 메시지를 같이 보여주고 싶음!!
wss.on("connection", (socket) => {
//연결되는 socket을 db에 저장
sockets.push(socket);
socket["nickname"] = "unknown";
console.log("Connected to Browser");
//브라우저가 닫혔을때
socket.on("close", onSocketClose);
// 브라우저가 서버에 메세지 보냈을때 다시 그 값을 브라우저에 보내주기
socket.on("message", (msg) => {
const message = JSON.parse(msg);
switch (message.type) {
case "new_message":
// 각각의 연결된 소켓 모두에게 메세지 전달(보낸 나도 포함)
sockets.forEach((aSocket) =>
//닉네임과 메세지 같이 불러와주기
aSocket.send(`${socket.nickname}: ${message.payload}`)
);
break;
case "nickname":
//닉네임 저장해주고
socket["nickname"] = message.payload;
break;
}
});
});
각각의 case에 break 해주지 않으면 전에 보낸 메시지를 닉네임에 저장해서 나타나게 됨!
그 이유가 아니더라도 각각의 case가 아니라면 볼 필요가 없기 때문에 break를 해주는게 맞음!!
- 메세지를 보냈을때 나를 제외한 인원에게 메시지를 보여주고싶음!
/src/public/js/app.js
function handleSubmit(event) {
//preventDefault 를 해주지 않으면 submit 됨과 동시에 창이 다시 실행됨.
event.preventDefault();
const input = messageForm.querySelector("input");
socket.send(makeMessage("new_message", input.value));
const li = document.createElement("li");
li.innerText = `You: ${input.value}`;
messageList.append(li);
input.value = "";
}
=>
- function사용해서 stringify와 parse를 이용해서 type을 변경해주는 방법이 일반적이지 않음
이러한 점들을 개선하기 쉬운 방법이 socket.io framework를 사용하는 것!!
이미 다 구현이 되어있어서 갖다 쓰면 됨!