📂 오늘 배운 내용
Node.js와 WebSocket(ws) 라이브러리를 이용한 간단한 실시간 채팅 서버
- 서버 : 클라이언트 연결 시마다 고유한 ID를 생성하여 관리
- 클라이언트 : 채팅 메시지를 입력하면 서버로 전송되고, 서버는 이걸 모든 클라이언트에게 보냄
그 외
- 랜덤 문자열 생성에서 사용한 함수들 random, toString, substinrg
TCP/IP
TCP (Transmission Control Protocol)
- 네트워트 간 데이터 교환 기술
- 데이터 신뢰성 있게 전송하기 위한 프로토콜(안녕하세요를 보냈을 때 순서대로 깨지지 않고 전달되는 것)
- 정확한 전송 보장
IP (Internet Protocol)
- 데이터 주고받기 위한 통신규약(약속)
- 패킷 기반 : 데이터를 가장 작게 쪼갠 단위
TCP/IP 4계층 = OSI 7계층
같은 건데 흐름을 어떤 기준으로 나누냐에 따라 달라짐
둘 다 네트워크 통신 계층화하여 구조적으로 설명하는 모델
TCP/IP 4계층
- 네트워크 인터페이스 : 이더넷, 와이파이 기술
- 인터넷 계층 : IP 프로토콜 작동, 패킷의 출발지와 목적지
- 전송: TCP(신뢰성) UDP(신뢰성은 떨어지지만 속도가 더 빠름)가 여기서 작동!!
- 소켓은 TCP/UDP 프로토콜 사용해서 작성 -> 실습에서는 TCP 기반 소켓 사용할 예정 👀
- TCP(Transmission Control Protocol) : 연결형 프로토콜 / 이메일, 웹사이트접속(http), 파일다운로드(FTP)
- UDP(User Datagram Protocol) : 비연결형 / 스트리밍, 온라인 게임 등에서 사용
- 응용: 사용자와 가장 가깝다. HTTP/ FTP 등 다양한 프로토콜이 여기서 동작함
Socket
- 프로세스가 네트워크로 데이터를 내보내거나 받기 위한 실제적인 창구 역할
- 2가지 종류 (TCP, UDP) 중 하나 사용해서 네트워크 통신을 위한 엔드포인트 생성하는 개념!
- 서버와 클라이언트 연결해주는 도구(인터페이스 역할)
- 서버 : 클라이언트 소켓의 연결 요청 대기-> 연결 요청 오면 클라이언트 소켓 생성해 통신을 가능하게 함
- 클라이언트 : 실제로 데이터 송수신이 일어나는 곳
- 소켓 정의 : 프로토콜, IP 주소, 포트 넘버
HTTP vs Socket.io
HTTP
- http는 새로고침해야 데이터가 오는 걸 확인할 수 있음
- 클라이언트가 요청하면 서버가 응답하는 방식
- 예 : 웹 페이지, API 호출
Socket.io
- 실시간 양방향 통신 가능
- 새로고침 없이도 서버에서 데이터가 오면 즉시 반영됨
- 예 : 카카오톡, 실시간 주식 가격, 채팅!
소켓 프로그래밍의 흐름
이 메서드들은 다른 언어에서 사용하는 거 소켓에서는 사용 안 함
메서드 참고만 하기
Web Socket
💡💡 자바스크립트에서는 일반 소켓 사용 불가 웹 소켓 써야함
- 한번 연결만 되면 요청과 응답의 순서가 상관없어짐
- HTML5 웹 표준 기술이라 cdn 추가할 필요 없음
- 웹 소켓은 양방향 소통을 위한 프로토콜(약속)
- 이벤트 단순히 듣고 보내는 것만 가능
- handshake: 서버와 클라이언트가 정상 연결됐는 지 확인하는 작업-> 확인 되면 웹소켓을 통해 실시간 통신 가능
Web Socket 이벤트
클라이언트
- 클라이언트(html) 단에서 이루어지는 일
- 소켓 객체를 만들어주고 addEventLister로 처리
💡 클라이언트 websocket 이벤트
- open : 웹 소켓이 성공적으로 열렸을 때
- message : 웹 소켓으로 데이터를 주고 받을 때
- error : 웹 소켓 연결 중 오류가 발생했을 때
- close : 웹 소켓 연결이 종료됐을 때
서버
백엔드에서는 설치 필요
npm i ws
- connection, message, error, close
- connection만 프론트와 다름 -> 이 이벤트의 콜백함수는 새로운 클라이언트 연결마다 실행
- addevnetlistner 없어서 On이라는 함수를 씀
💡 ws 모듈 이벤트 (이벤트 핸들러)
- connection : 클라이언트와 웹 소켓 서버가 연결되었을 때
- message : 클라이언트에게 메시지를 받았을 때
- error : 연결 중 오류
- close: 클라이언트와 연결 종료
소켓은 api만드는 건 아니고
간단 채팅방
클라이언트
: 웹 소켓을 이용해 채팅 메시지를 서버에 보내고, 서버에서 받은 메시지를 화면에 표시
[client.ejs]
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>간단 채팅 만들기(Web Socket)</title>
</head>
<body>
<h4>간단 채팅방</h4>
<h5>채팅 내용</h5>
<ul></ul>
<h5>채팅 입력</h5>
<form id="chat">
<label>이름: <input type="text" id="name" /></label>
<label>내용: <input type="text" id="msg" /></label>
<button>채팅 보내기</button>
</form>
<script>
// ✅ 웹소켓 서버와 연결 ('ws://통신 주소');
const socket = new WebSocket('ws://localhost:8080');
const msg = document.querySelector('#msg');
const name = document.querySelector('#name');
const chatForm = document.querySelector('#chat');
const ul = document.querySelector('ul');
// ✅ WebSocket 이벤트 핸들러
// [1] 서버와 연결이 완료됐을 때
socket.addEventListener('open', (e) => {
console.log('서버에 연결되었습니다!');
// console.log('e', e);
// socket.send('채팅방 입장~!'); // 서버에게 메시지를 보냄
});
// [2] 서버로부터 메시지를 받았을 때
socket.addEventListener('message', (e) => {
console.log('서버로부터 받은 메세지', e.data); //// {'msg': 'ddd', 'name': 'ddd'}
const data = JSON.parse(e.data); // json >> object
console.log('객체로 변환!', data);
// 채팅 내용 화면에 추가
const li = document.createElement('li');
li.textContent = `${data.name}: ${data.msg}`;
ul.append(li);
});
// [3] 사용자가 메시지 입력 후 전송 버튼 눌렀을 때
chatForm.addEventListener('submit', (e) => {
e.preventDefault();
// 사용자가 입력한 데이터 객체 생성
const chatData = { msg: msg.value, name: name.value };
console.log('chatData', chatData); // {msg: 'ddd', name: 'ddd'}
// ❓ chatData를 JSON으로 바꿔서 보내는 이유
// socket.send(chatData); // '클라이언트: 객체 -> 서버: 객체' 로 전달됨
// 💡서버에 데이터 전송 (string으로 변경해서 보내야함)
// 왜냐면 우리가 원하는 형식으로 보내기 위해서! (string -> string)
socket.send(JSON.stringify(chatData));
msg.value = '';
name.value = '';
});
</script>
</body>
</html>
서버
: 웹 소켓 서버를 만들고 연결된 클라이언트와 메시지 주고 받음
[server.js]
// npm i ejs express ws
// [1] 웹 서버 및 웹 소켓 서버 생성
const express = require('express'); //웹 서버 프레임워크
const ws = require('ws'); //ws 라이브러리
const app = express();
const PORT = 8080;
app.set('view engine', 'ejs');
app.get('/', (req, res) => {
res.render('client');
});
// [2] 서버 실행
const server = app.listen(PORT, () => {
console.log(`http://localhost:${PORT}`);
});
// console.log(server); // 서버 객체
// [4] 연결될 클라이언트마다 고유한 ID 값 설정 (랜덤 문자열 생성)
function generateUniqueId() {
const timestamp = Date.now().toString(36); //현재 시간을 36진수로 변환
// console.log('timestamp', timestamp); //m6ooly28
// - 좀 더 복잡한 id
const randomString = Math.random().toString(36).substring(2); //랜덤 문자열 추가
// console.log('randomString', randomString); //4dlmth06aqv
return timestamp + randomString;
}
// console.log('id', generateUniqueId()); //m6ooly284dlmth06aqv
// ---------- [5] 클라이언트가 웹 소켓 서버에 연결될 때 실행되는 코드 --------
const sockets = []; // 클라이언트 소켓들을 저장하는 배열
// [3] 웹 소켓 서버 생성
// - 기존 Express 서버를 웹 소켓 서버와 연결 -> 웹 소켓을 통한 실시간 통신 가능해짐
const wsServer = new ws.Server({ server: server });
// - 클라이언트가 웹 소켓 서버에 연결될 때 실행
wsServer.on('connection', (socket) => {
console.log(socket); // 연결될 하나의 클라이언트(브라우저)에 대한 정보
const clientId = generateUniqueId();
console.log(`클라이언트 id: [${clientId}] 연결됨`);
sockets.push(socket); // 연결된 새로운 클라이언트 socket을 배열에 추가
// 메시지 수신 이벤트 (클라이언트 -> 서버)
socket.on('message', (message) => {
// 메시지는 버퍼 객체 <Buffer ec b1 84 ed 8c 85 eb b0 a9 20 ec 9e 85 ec 9e a5 7e 21>
// console.log('=------------');
// console.log(message); // 버퍼객체
// console.log(message.toString()); // 문자열 '채팅방 입장~!'
console.log(`${clientId} 에게 받은 메시지 : ${message}`);
// [object object] -> 클라이언트 JSON처리 후 {"msg" : "ddd", "name":"ddd"}
// console.log('=------------');
// ✅ 현재 연결된 소켓에게만 메시지 전송
// - socket: 요청하고 있는 클라이언트 1개
// socket.send('안녕하세요?');
// ✅ 연결된 모든 클라이언트에게 메시지 전송
sockets.forEach((client) => {
// client.send(`${client}`); // 👾 에러 발생한 이유: 문자열[object object]을 객체로 바꿔주라고 했기때문!!!
client.send(`${message}`); //버퍼 객체 암시적 호출
});
});
});
// ---------------------------------------------------------------
랜덤 문자열 생성
🔍 substring 함수 알아보기
console.log('abcdef'.substring(2)); //cdef
console.log('abcdefgh'.substring(2, 5)); //cde
🔖 관련 글
Node.js WebSocket 메시지 처리와 Buffer 객체 변환 이해하기 🚀
🌐 참고
서울시 청년취업사관학교(SeSAC) x 코딩온 웹 개발자 풀스택 과정
31.web-socket
'Today I Learned > SeSAC 웹 2기' 카테고리의 다른 글
Socket.io with React MVC 패턴 채팅 앱 | 15주차(3) (0) | 2025.02.09 |
---|---|
Node.js Socket.io 라이브러리(EJS) 💬💬 | 15주차(2) (0) | 2025.02.08 |
TypeScript와 React | 13주차(3) (0) | 2025.01.30 |
Typescript 입문 🥳 | 13주차(2) (0) | 2025.01.24 |
React 상태관리 ContextAPI와 Redux | 13주차(1)하 (0) | 2025.01.23 |