Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- 비디오스트리밍
- ReactContextAPI
- API루트
- nodemailer
- pyinstaller
- reactjs
- expressjs
- 인스타그램앱만들기
- 쿠키관리
- 넥스트js
- nextjs
- 페이스북개발자
- APIroutes
- socketIO
- 넥스트JS13
- 앱비밀번호
- next js
- 노드메일러
- 비디오전송
- 인스타그램API
- Nodejs
- state전역관리
- pyqt5
- 리액트
- ReactQuill
- 웹소켓
- nextjs13
- mysqlworkbench
- PlanetScale
- 플래닛스케일
Archives
- Today
- Total
Timpossible history
[Express JS] Socket.IO 이용해서 실시간 채팅 어플리케이션 구성 본문
Socket.IO는 웹 소켓(Websocket)을 쉽게 다룰 수 있도록 도와주는 라이브러리로, 실시간 양방향 통신을 구현하는데 아주 유용하다.
1. 프로젝트 초기화
mkdir mychatting
cd mychatting
npm init -y
먼저 프로젝트를 초기화 해주고, 필요한 패키지를 설치해준다.
npm install express socket.io pug
Node js에는 View Engine이 존재하는데, 이는 서버에서 얻은 결과값을 정적 페이지(html)에 표시 할 수 있게 해준다. 물론 자동으로 생성되는 것이 아니라, 기본 템플릿을 만들어놔야 하는데, 기본 html 형식으로 하지 않도록 도와주는 것이 pug이다.
(ejs도 많이 쓰임. pug든 ejs든 동적으로 정적 페이지 렌더링 가능함.)
여기서 pug는 간단하고 직관적으로 보기가 편해서 정적 페이지 구성이 쉬운 장점이 있으니 pug를 쓸 것이다.
2. 서버 사이드 설정
// src/server.js
import express from "express";
import socketIO from "socket.io";
import http from "http";
const app = express();
app.set("view engine", "pug"); // view engine은 pug로 설정
app.set("views", __dirname + "/views"); // 정적 페이지 파일들은 __dirname + '/views' 경로에 있는 폴더에 있다고 설정.
app.use("/public", express.static(__dirname + "/public")); // '/public' 경로로 들어오는 요청을
app.get("/", (req, res) => res.render("home")); // 유저가 메인 페이지('/')에 들어오면 views 폴더의 home.pug가 보여짐.
app.get("/*", (req, res) => res.redirect("/")); // 일단 '/'외에 다른 페이지가 없으므로 기타 다른 루트를 입력해도 home.pug가 렌더링 되도록 설정.
const handleListen = () => console.log(`Listening on http://localhost:3000`);
const httpServer = http.createServer(app);
const wsServer = socketIO(httpServer);
// user가 메인페이지에 들어올 시, 웹소켓 서버와 연결
wsServer.on("connection", (socket) => {
// user의 소켓 객체에 임의적으로 'Anon' 닉네임 property 추가.
socket["nickname"] = "Anon";
// user가 roomName이라는 이름의 방에 들어올 때
socket.on("enter_room", (roomName) => {
socket.join(roomName);
// roomName이름의 방에 있는 전체 user들에게 'welcome'이라는 신호를 보내고, 'nickname joined' 문자열과, roomName 변수를 메세지로 보냄.
socket
.to(roomName)
.emit(
"welcome",
`${socket.nickname} joined!!`,
roomName,
);
});
//'nickname'을 입력했을 때, socket 객체의 nickname property 수정
socket.on("nickname", (nickname, callback) => {
socket["nickname"] = nickname;
callback();
});
// 메세지를 입력했을 때, 방에 있는 유저들에게 'nickname: msg'라는 문자열을 전달
socket.on("new_message", (msg, roomName, callback) => {
socket.to(roomName).emit("new_message", `${socket.nickname} : ${msg}`);
callback();
});
socket.on("disconnecting", () => {
socket.rooms.forEach((room) =>
socket.to(room).emit("bye", `${socket.nickname} left..`)
);
});
socket.on("disconnect", () => {
console.log('user left');
});
});
httpServer.listen(3000, handleListen);
3. 클라이언트 사이드 설정
// src/views/home.pug
doctype html
html(lang="en")
head
meta(charset="UTF-8")
meta(http-equiv="X-UA-Compatible", content="IE=edge")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title Noom
// 간단한 스타일링을 위해서 mvp.css를 연결해주었다.
link(rel="stylesheet", href="https://unpkg.com/mvp.css@1.12/mvp.css")
body
header
h1 Noom
main
h2 Welcome to Noom!
div#welcome
form
input(type="text", placeholder="Room name", required)
button Enter room
ul
div#room
h3#roomName
form#name
input(type="text", placeholder="nickname")
button Save
ul
form#msg
input(type="text", placeholder="message", required)
button Send
script(src="/socket.io/socket.io.js")
// 클라이언트 사이드에서 실행시킬 javascript 코드
script(src="/public/js/app.js")
'/' 루트의 메인 정적 페이지 home.pug를 보기처럼 작성해준다.
클라이언트 사이드에서 실행시키는 js 코드는 /public/js/app.js 루트에 작성했다.
const socket = io();
const welcome = document.querySelector("#welcome");
const form = welcome.querySelector("form");
const room = document.querySelector("#room");
room.hidden = true;
let roomName;
// 유저 입장, 유저 메세지 등을 보여주는 DOM 만듦
const addMessage = (message) => {
const ul = room.querySelector("ul");
const li = document.createElement("li");
li.innerText = message;
ul.appendChild(li);
};
form.addEventListener("submit", (e) => {
e.preventDefault();
welcome.hidden = true;
const roomNameInput = form.querySelector("input");
form.hidden = true;
room.hidden = false;
roomName = roomNameInput.value;
const h3 = room.querySelector("h3");
h3.innerText = `Room ${roomName}`;
roomNameInput.value = "";
const nickname = room.querySelector("#name");
const msg = room.querySelector("#msg");
msg.hidden = true;
nickname.addEventListener("submit", (e) => {
e.preventDefault();
const nicknameInput = room.querySelector("#name input");
// 입력한 nickname을 웹소켓 서버에 보내준다.
// 세번째 인자는 함께 실행시킬 콜백함수.
// nickname을 입력하면 enter_room이라는 신호를 웹소켓 서버에 보내게 됨고 웹소켓 서버에서 on('enter_room') 실행.
socket.emit("nickname", nicknameInput.value, () => {
socket.emit("enter_room", roomName);
});
msg.hidden = false;
nickname.hidden = true;
msg.addEventListener("submit", (e) => {
e.preventDefault();
const msgInput = room.querySelector("#msg input");
const value = msgInput.value;
// msgInput에 입력한 메세지를 보냄.
socket.emit("new_message", msgInput.value, roomName, () =>
addMessage(`You: ${value}`)
);
msgInput.value = "";
});
});
});
4. 실행
node src/server.js
실행해주면, 웹 브라우저 'http://localhost:3000'으로 접속하게됨. 여러 윈도우 탭을 열어 localhost:3000으로 들어가서 실습해볼 수 있다.
'백엔드 > Node JS' 카테고리의 다른 글
[Node JS] Express JS, 서버에서 클라이언트로 동영상 보내기(Feat. Streaming) (0) | 2024.02.29 |
---|---|
[Express JS] Socket.IO로 실시간 화상 채팅 구성(feat. WebRTC) (0) | 2024.01.04 |
[Node JS] Nodemailer 사용 시 필요한 앱 비밀번호 설정 (0) | 2023.12.31 |