HTTP 는 stateless!
{유저-request-> 서버
서버->response->유저 } 가 끝나면 유저를 잊는다. (쿠키를 보내야 함)
서버는 request를 받을때에만 response를 준다.
웹소켓도 HTTP처럼 프로토콜이다!
다만, https://www.google.com/이 아니라 wss://www.google.com/
유저의 request에 수락한다면 연결 성립! Bi-directional!
연결된다면, 유저를 계속 기억하고 메세지를 보낼 수 있음. 유저<->서버 양방향
import express from "express";
import http from "http";
import {WebSocketServer} from "ws"; // "ws"현재버전은 import 방식 이렇게!
const server = http.createServer(app); // http서버!
//ws
const wss = new WebSocketServer({server }); //웹소켓 서버!
server.js
wss.on("connection",(socket)=>{ //에서 socket:연결된 브라우저
app.js 프론트에서도 연결해주어야 함
const socket = new WebSocket(`ws://${window.location.host}`); //서버로의 연결
wss.on("이벤트",콜백함수)
프로토콜은 ws! 모바일은 localhost가 안되기 때문에 브라우저 옵션을 이용하자!
연결되면 콜백함수 실행
인자 socket : 백엔드에 연결된 상대. 서버와 브라우저사이의 연결임. 인자로 쓸수있음. 저장해두어야함!
server.js
socket:연결된 브라우저
socket.on : 브라우저로부터 발생된 이벤트에 대해 실행
- 브라우저를 닫거나 서버를 kill 했을 때
socket.on("close", ()=>{});- 브라우저로 데이터 보내기
socket.send()여기서 socket은 브라우저니까 브라우저로 보내는것
** 브라우저로부터 메세지를 받았을 때
socket.on("message", (message)=>{}_;
app.js
socket : 서버
socket.addEventListener : 서버로부터 발생된 이벤트에 대해 실행
프론트에선 .on 대신 .addEventListener (기존JS처럼)
- 서버로부터 메세지를 받았을 때
socket.addEventListener("message", (message) => {- 서버로 메세지 보내기
socket.send("보낼메세지");
- sockets.push(socket);
연결된 브라우저를 sockets array에 넣는다는것. 받은 메세지를 모든 socket에 전달 가능.
app.js
socket.addEventListener("message",(message)=>{ console.log("New message : ",message.data); const li = document.createElement("li"); li.innerText = message.data; messageList.append(li); }) function handleSubmit(event) { event.preventDefault(); const input = messageForm.querySelector("input"); socket.send(input.value); input.value = ""; } messageForm.addEventListener("submit", handleSubmit);
- form에 메세지를 작성하고 submit 하면 socket.send 에 의해 서버로 메세지 보냄.
- (chat 단락 코드처럼) 서버에선
sockets.forEach(aSocket => aSocket.send(message.toString()));
에 의해 브라우저로 메세지를 보냄
- 브라우저가 서버로부터 메세지를 받으면 addEventListener("message")에 의해 li 요소를 만들고 해당 메세지를 요소 값으로 지정
socket.send(data)에서 data로는 string만 가능함
{ type:"nickname", payload :"hi"} 를 object형으로 보내고 싶다면 ??
형 변환 !!
JSON.stringify({ type:"nickname", payload :"hi"})
>>> '{"type":"nickname","payload":"hi"}'
app.js
- form에 값을 입력하여 1submit 하면 지정한 type과 입력한 값을 object형으로 변수 msg에 저장
- 그걸 string으로 변환하여 백에 send
왜? 프론트와 백엔드 서버가 js서버가 아닐수도 있으니까! GO서버, 자바 서버등일 수도 있음.
JSON.parse('{"type":"nickname","payload":"hi"}')
>>> { type:"nickname", payload :"hi"}
server.js
- 전달받은 string 형의 데이터를 object형으로 변환하여 저장.
- switch-case : if-else if 여러번 사용 보다 효율적!
닉네임과 채팅 함께 보여주기socket["nickname"] = "Anonymous"; // 닉네임 아이템 미리 초기화 socket.on("message", (message)=>{ const parsedMessage = JSON.parse(message); switch(parsedMessage.type){ case "new_message": sockets.forEach(aSocket => aSocket.send(`${socket.nickname} : ${parsedMessage.payload}`)); case "nickname": socket["nickname"] = parsedMessage.payload; } })
- socket에게 닉네임도 알려주기 위해서 아이템 추가
- 소켓은 객체라 아이템 추가할수있음