Step-by-Step

[4] Socket.IO 사용 - Room 생성 및 닉네임, 메세지 출력 본문

프로젝트/Zoom (WebRTC)

[4] Socket.IO 사용 - Room 생성 및 닉네임, 메세지 출력

희주(KHJ) 2023. 3. 8. 21:49

https://socket.io/

 

Socket.IO

Reliable Rest assured! In case the WebSocket connection is not possible, it will fall back to HTTP long-polling. And if the connection is lost, the client will automatically try to reconnect.

socket.io

 

간단한 정리 : [IT 기술] - HTTP vs WebSocket vs Socket.IO

 

ㅠㅠ 왜 이걸 이제 공부한거지?? 너무 재밌다.. 양방향 통신!

 

 

Socket.io 설치

 

npm install socket.io

 

 

소켓의 기본 기능

 

// 데이터 주기
socket.emit("이벤트명", ... );

// 데이터 받기
socket.on("이벤트 명", ... );

// 소켓의 Room 필드에 값 추가
socket.join("Room 명");

// 특정 Room에 속해있는 소켓들  .emit() 등 붙여서 사용 가능
socket.to("Room 명"); 

// 소켓에 필드 추가
socket["필드 명"] = 데이터;
  • FE -> BE 전송  및   BE -> FE 전송 모두 가능

 

 

1) Server.js

 

 

Socket.IO 사용 및 HTTP 서버와 연결 (Server.js)

 

import SocketIO from "socket.io";

const httpServer = http.createServer(app);
const wsServer = SocketIO(httpServer);

 

 

소켓 처음 연결시 (Server.js)

 

wsServer.on("connection", (socket) => {
	// Connection 성공 후 이벤트 처리 코드
	// 밑에 나온 이벤트 처리 코드는 전부 Connection 내부
}

 

 

소켓 기본 이벤트 처리 (Server.js)

 

// Socket의 모든 이벤트를 살핌
socket.onAny((event) => {
	console.log(`Socket Event : ${event}`);
});

// 퇴장시 처리
socket.on("disconnecting", () => {
	socket.rooms.forEach(room => socket.to(room).emit("bye", socket.nickname));
});

 

 

소켓 customized 이벤트 처리 기본 구조 (Server.js)

 

// connection 내부에 작성
socket.on("이벤트 명", (파라미터1, 파라미터2, ... , 함수) => {
	// 파라미터 처리
});
  • 이벤트 명 제외 파라미터는 0개 이상임
  • 마지막으로 전달된 함수는 FE 함수로, FE에서만 실행됨!!!!! ★ - 보안 문제도 있기 때문(DB 조작 등)
  • 파라미터는 거의 모든 타입이 가능함 (string, int, json 등)

 

 

각 기능별 코드 (Server.js)

 

wsServer.on("connection", (socket) => {
    // 초기 닉네임
    socket["nickname"] = "Anon";

    // Socket의 모든 이벤트를 살핌
    socket.onAny((event) => {
        console.log(`Socket Event : ${event}`);
    });


    // 입장시 처리
    socket.on("enter_room", (roomName, done) => {
        
        // socket.io에서 기본으로 제공하는 ROOM 기능 = join
        socket.join(roomName.payload);
        done();     // FE함수로, FE에서만 실행됨!!!!! (중요) - 보안 문제도 있기 때문(DB 조작 등)
        
        socket.to(roomName.payload).emit("welcome", socket.nickname);
    });

    // 퇴장시 처리
    socket.on("disconnecting", () => {
        socket.rooms.forEach(room => socket.to(room).emit("bye", socket.nickname));
    })

    // 채팅 메세지 전송
    socket.on("new_message", (msg, room, done) => {
        socket.to(room).emit("new_message", `${socket.nickname} : ${msg}`);
        done();
    });

    // 닉네임 변경
    socket.on("nickname", (nickname) => {socket["nickname"]=nickname});
})

 

 

 

2) App.js

 

 

BE에서 FE로 소켓 정보 가져오기 (App.js)

 

const socket = io();
  • BackEnd와 socket.io를 자동적으로 연결해주는 Function
  • 자동으로 BE로 socket 전송 

 

 

이벤트 처리 (App.js)

 

socket.on("이벤트 명", 파라미터1, 파라미터2, ... , 함수);
  • 이벤트 명은 Server.js와 동일해야 함
  • 함수는 마지막으로 설정!

 

 

각 기능별 코드 (App.js)

 

// BackEnd와 socket.io를 자동적으로 연결해주는 Function
// 자동으로 BE로 socket 전송 
const socket = io();

const welcome = document.getElementById("welcome");
const form = welcome.querySelector("form");
const room = document.getElementById("room");

// 화면에 안보이게 하기
room.hidden = true;

let roomName;

function showRoom() {
    welcome.hidden = true;
    room.hidden = false;

    // 룸 네임 보여주기
    const h3 = room.querySelector("h3");
    h3.innerText = `Room ${roomName}`;

    // 닉네임
    const nameForm = room.querySelector("#name");
    nameForm.addEventListener("submit", handleNicknameSubmit);
    
    // 메세지 입출력
    const msgForm = room.querySelector("#msg");
    msgForm.addEventListener("submit", handleMessageSubmit)
}

function handleNicknameSubmit(event){
    event.preventDefault();
    const input = room.querySelector("#name input");
    const value = input.value;

    socket.emit("nickname", value);

}

function handleMessageSubmit(event){
    event.preventDefault();
    const input = room.querySelector("#msg input");
    const value = input.value;      // 
    socket.emit("new_message", input.value, roomName, () => {
        addMessage(`You: ${value}`);
    });
    input.value = "";
}

function handleRoomSubmit(event){
    event.preventDefault();
    const input = form.querySelector("input");
    roomName = input.value;

    // emit(이벤트명, BE로 전달할 객체, FE에서 호출될 함수) => 이벤트명 이하 파라미터는 개수, 형식 관계없이 마음대로 작성
    // 다만 Server에서 작업이 끝난 후 실행되었으면 하는 함수는 마지막 파라미터로 넣어주기!
    socket.emit("enter_room", { payload : input.value }, showRoom); 
    input.value = "";
}

function addMessage(message){
    const ul = room.querySelector("ul");
    const li = document.createElement("li");
    li.innerText = message;
    ul.appendChild(li);
}

form.addEventListener("submit", handleRoomSubmit);


// 입장시 메세지
socket.on("welcome", (user) => {
    console.log("welcome");
    addMessage(`${user} Arrived!`);
})

// 퇴장시 메세지
socket.on("bye", (user) => {
    addMessage(`${user} Left ㅠㅠ`);
})

// 룸 채팅 메세지 
socket.on("new_message", addMessage);

 

 

 

Comments