[유데미x스나이퍼팩토리] 10주 완성 프로젝트 캠프(프론트엔드) 12회차 - 웹 소켓을 이용한 실시간 채팅
📝 수업 내용
웹 소켓은 브라우저와 서버 사이의 동적인 양방향 연결 채널을 구성하는 기술이다.
웹 소켓에 대해 자세히 서술한 다음 블로그를 참고하자.
[WEB] 🌐 웹 소켓 (Socket) 정리 (역사부터 차근차근)
웹 개발을 처음 배우기 시작했다면 서버와 클라이언트의 통신은 모두 HTTP 프로토콜만 이용해서 이루어진다고 생각할 수 있습니다. 하지만 웹 개발을 하면서 채팅, 게임, 주식 차트 등의 실시
inpa.tistory.com
웹 소켓을 이용해 간단한 실시간 채팅 앱을 구현하기 위해 먼저 Express, Socket.IO를 사용하여 채팅 서버를 구현할 server.js 파일에 다음 코드를 넣자.
const express = require("express");
const http = require("http");
const socketIO = require("socket.io");
const cors = require("cors");
const app = express();
app.use(cors());
const server = http.createServer(app);
const io = socketIO(server, {
cors: {
origin: "http://localhost:3000",
methods: ["GET", "POST"],
},
});
io.on("connection", (socket) => {
console.log("새로운 클라이언트가 연결되었습니다.");
socket.on("message", (message) => {
console.log("새로운 메시지:", message);
io.emit("message", message);
});
// 클라이언트 연결 해제 처리
socket.on("disconnect", () => {
console.log("클라이언트가 연결을 해제하였습니다.");
});
});
server.listen(3001, () => {
console.log("서버가 3001 포트에서 실행 중입니다.");
});
벡엔드에 해당하는 부분이라 강사님이 따로 설명은 안하고 넘어가셨지만 코드 주요 내용은 다음과 같다.
1. 모듈 및 미들웨어 로드
- express, http, socket.io, cors 모듈을 로드하고 express를 사용하여 앱을 생성한다.
- cors 미들웨어를 사용하여 CORS(Cross-Origin Resource Sharing) 설정을 추가한다.
2. 서버 및 소켓 설정
- http 모듈을 사용하여 서버를 생성하고 socket.io를 사용하여 서버와 소켓 간의 통신을 설정한다.
- CORS 설정을 추가하여 특정 origin에서의 요청을 허용한다.
3. 소켓 이벤트 처리
- io.on("connection", (socket) => { ... })를 사용하여 클라이언트의 연결 이벤트를 처리한다.
- 연결된 클라이언트에 대한 정보를 출력한다.
- socket.on("message", (message) => { ... })를 사용하여 클라이언트로부터의 메시지 이벤트를 처리한다.
- 수신한 메시지를 콘솔에 출력한 후, io.emit("message", message)를 사용하여 모든 클라이언트에게 메시지를 전달한다.
- socket.on("disconnect", () => { ... })를 사용하여 클라이언트의 연결 해제 이벤트를 처리한다.
4. 서버 실행
- server.listen(3001, () => { ... })를 사용하여 서버를 지정된 포트(3001)에서 실행한다.
따라서 이 코드는 3001 포트에서 실행되며, 클라이언트가 message 이벤트를 통해 서버로 메시지를 보낼 수 있다.
서버는 수신한 메시지를 다시 모든 클라이언트에게 전달하고 클라이언트의 연결 및 연결 해제 이벤트도 처리한다.
다음은 react를 사용한 채팅 앱의 프론트 부분 코드로 chat.js 파일에 저장하자.
import React, { useState, useEffect } from "react";
import io from "socket.io-client";
const socket = io("http://localhost:3001");
function Chat() {
const [username, setUsername] = useState("");
const [message, setMessage] = useState([]);
const [inputValue, setInputValue] = useState("");
useEffect(() => {
socket.on("message", handleMessage);
return () => {
socket.off("message", handleMessage);
};
});
const handleMessage = (message) => {
setMessage((prev) => [...prev, message]);
};
const handleMessageSubmit = () => {
if (inputValue.trim() !== "") {
const currentTime = new Date().toLocaleDateString();
socket.emit("message", {
name: username,
content: inputValue,
time: currentTime,
});
setInputValue("");
}
};
return (
<div>
<h1>실시간 채팅</h1>
<input
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
placeholder="사용자 이름 입력하세요"
/>
<h1>채팅</h1>
<div>
{message.map((message, index) => (
<p key={index}>
{message.name} : {message.content} - {message.time}
</p>
))}
</div>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
<button onClick={handleMessageSubmit}>전송</button>
</div>
);
}
export default Chat;
주요 설명은 다음과 같다.
1. 모듈 로드
-React, useState, useEffect를 로드하고 socket.io-client 모듈을 로드하여 소켓 클라이언트를 생성한다.
2. 소켓 연결
- io("http://localhost:3001")를 사용하여 서버의 소켓에 연결한다. (http://localhost:3001은 서버의 주소)
- 생성한 소켓 클라이언트를 socket 변수에 저장한다.
3. 컴포넌트와 상태 설정
- username, message, inputValue를 상태로 설정한다.
- username은 사용자 이름을 저장, message는 수신한 메시지들을 저장하는 상태로, 초기값은 빈 배열이고 inputValue는 입력 필드의 값을 저장하는 상태다.
4. useEffect를 통한 이벤트 리스너 설정
- useEffect를 사용하여 컴포넌트가 마운트되었을 때 socket.on("message", handleMessage)을 호출한다.
- handleMessage 함수는 수신한 메시지를 상태에 추가하는 역할을 한다.
- 컴포넌트가 언마운트될 때, socket.off("message", handleMessage)을 호출하여 이벤트 리스너를 해제한다.
5. handleMessage 함수
- 수신한 메시지를 받아서 현재 message 상태를 업데이트한다.
- 이전 상태의 배열에 새로운 메시지를 추가하기 위해 전개 연산자 ...를 사용헌다.
6. handleMessageSubmit 함수
- 입력 필드의 값이 비어 있지 않은 경우, 현재 시간을 포함하여 서버로 메시지를 전송한다.
- 소켓을 통해 socket.emit("message", {...})을 호출하여 서버에 메시지 이벤트를 발생시킨다.
- 메시지를 전송한 후에는 입력 필드를 비운다.
7. 렌더링
- 사용자 이름을 입력하는 입력 필드를 렌더링한다.
- 수신한 메시지들을 나타내기 위해 message 상태를 매핑하여 출력한다.
- 입력 필드와 전송 버튼을 렌더링한다.
- 입력 필드의 값과 변경 이벤트에 대한 핸들러를 설정한다.
이제 App.js에서 Chat컴포넌트를 렌더링하면 사용자가 이름과 메세지를 입력해 서버와 실시간 통신할 수 있다.
🔥 실습
https://github.com/udemy-team18/practice/tree/yueun/0630/chatting
GitHub - udemy-team18/practice: 유데미 x 스나이퍼 팩토리 10주 완성 프로젝트 부트캠프 18팀 실습 저장소
유데미 x 스나이퍼 팩토리 10주 완성 프로젝트 부트캠프 18팀 실습 저장소. Contribute to udemy-team18/practice development by creating an account on GitHub.
github.com
—————————————————————————————————————————
본 후기는 유데미-스나이퍼팩토리 10주 완성 프로젝트캠프 학습 일지 후기로 작성 되었습니다.
—————————————————————————————————————————