Next.js로 사이드프로젝트 진행 중, socket.io를 활용한 채팅방 기능을 구현하고 있습니다.
express를 활용한 서버는 아래와 같이 구성합니다.
import express, { Express } from "express";
import { createServer } from "http";
import { Server, Socket } from "socket.io";
const app: Express = express();
const httpServer = createServer(app);
const PORT: number = 8080;
const io = new Server(httpServer, {
path: "/socket/chat",
cors: {
origin: "*",
credentials: true,
},
});
io.on("connection", (socket: Socket) => {
console.log(`유저입장 :${new Date()} 유저아이디:${socket.id}`);
socket.on("sendMessage", ({ userName, message }: { userName: string; message: string }) => {
io.emit("message", { userName, message });
});
socket.on("disconnect", () => {
console.log(`유저나감 : ${new Date()} 유저아이디:${socket.id}`);
});
});
httpServer.listen(PORT, () => {
console.log(`[server]: Server is running at http://localhost:${PORT}`);
});
- io변수의 path는 클라이언트측과 socekt을 연동시켜주는 주소라고 생각하면 됩니다.
- io.on 및 io.emit을 통해, 클라이언트측과의 이벤트를 구성해줍니다.
- io.on은 이벤트수신 , io.emit은 이벤트전송이라 생각하면 됩니다.
클라이언트는 Next.js로 구성했습니다.
(CSS 미적용)
import { useEffect, useState } from "react";
import { io, Socket } from "socket.io-client";
interface ChatMessage {
userName: string;
message: string;
}
let socket: Socket;
export default function Home() {
const [userName, setUserName] = useState<string>("");
const [message, setMessage] = useState<string>("");
const [chatMessage, setChatMessage] = useState<ChatMessage[]>([]);
useEffect((): any => {
socket = io("http://localhost:8080", { path: "/socket/chat" });
socket.on("connect", () => {
console.log("소켓연결 성공!!!", socket.id);
});
socket.on("message", (receiveMessage: ChatMessage) => {
console.log("메세지 수신");
setChatMessage((prev) => [...prev, receiveMessage]);
});
if (socket) return () => socket.disconnect();
}, []);
const onMessageSubmit = () => {
socket.emit("sendMessage", { userName, message });
setMessage("")
};
const enterKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.key === "Enter" && !event.shiftKey) {
event.preventDefault();
onMessageSubmit();
}
};
return (
<div>
<div>
{chatMessage.map((item, index) => {
return <div key={index}>{`${item.userName} : ${item.message}`}</div>;
})}
</div>
<form>
<input type="text" placeholder="닉네임을 입력해주세요" onChange={(e) => setUserName(e.currentTarget.value)} />
<input type="text" placeholder="메세지를 입력해주세요" onChange={(e) => setMessage(e.currentTarget.value)} onKeyDown={enterKeyDown} />
<button type="button" onClick={onMessageSubmit}>
메세지 전송
</button>
</form>
</div>
);
}
- useEffect를 통해 렌더링 후 서버측과 socket을 연결시켜줍니다.
- 위의 코드에서 onMessageSubmit함수를 호출하면 작성한 메세지를 서버로 전송합니다.
- 이후 서버측이 전송한 메세지를 다시 chatMessage에 추가하여 채팅을 보여줍니다.
간단하게 기능확인을 위해 적용한 코드이므로
CSS적용 및 컴포넌트분리등을 추가한 내용으로 2편을 작성하겠습니다.
전체소스코드는 아래의 저장소에서 확인 가능합니다.
깃허브 저장소 이동