[WebSocket/Socket IO] 채팅 서비스 구현 8. 닉네임 설정하기

2022. 12. 7. 08:01·개발/Projects

이전 포스팅인 웹소켓을 사용하여 닉네임 설정하기에서 닉네임을 설정했던 방법을 기억하시나요? 이 때의 핵심은 socket 객체 안에 새로운 키와 값을 추가해줄 수 있다는 것이었는데요. 비슷한 방식으로 Socket IO에서도 닉네임 설정 기능을 구현할 수 있습니다.

 

먼저, home.pug에서 닉네임을 설정하는 필드를 만들어주겠습니다.

// 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")
    link(rel="stylesheet", href="https://unpkg.com/mvp.css")
    title Zoom
  body
    header
      h1 Chat Service
    main
      div#nickname
        form
          input(type="text", placeholder="Please enter your nickname", required, autofocus)
          button Save
      div#room
        form
          input(type="text", placeholder="Please type Room name", required)
          button Enter the Room
      div#chat
        h2 Room Name
        ul
        form
          input(type="text", placeholder="You can type here", required)
          button Send
    script(src="/socket.io/socket.io.js") 
    script(src="/public/js/app.js")

여기서 잠시 사용자가 서비스를 사용하는 로직을 정리해보고 갈게요. 채팅 서비스에 접속하면 1. 닉네임 설정 2. 방 입장 3. 메시지 전송의 흐름을 구현하려고 합니다.

 

아래와 같이 app.js를 업데이트해줍니다. 기존의 로직에 다음과 같이 코드를 추가 및 업데이트해줍니다.

// app.js

const socket = io();

const room = document.querySelector("#room");
const roomForm = room.querySelector("form");
const chat = document.querySelector("#chat");
const chatForm = chat.querySelector("form");
const nicknameSet = document.querySelector("#nickname");
const nicknameForm = nickname.querySelector("form");

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

function handleSendMessage(event) {
  event.preventDefault();

  const message = chatForm.querySelector("input");
  socket.emit("message", message.value, sendMessage);
  message.value = "";
}

room.hidden = true;
chat.hidden = true;

function showRoom(roomName) {
  // 로직 흐름에 따라 상황에 맞는 div 표시해주기
  room.hidden = true;
  nicknameSet.hidden = true;
  chat.hidden = false;

  const roomNameHeader = chat.querySelector("h2");
  roomNameHeader.innerText = `Room: ${roomName}`;

  chatForm.querySelector("input").focus();

  chatForm.addEventListener("submit", handleSendMessage);
}

function handleRoomName(event) {
  event.preventDefault();

  const input = roomForm.querySelector("input");
  const roomName = input.value;

  socket.emit("room", roomName, showRoom);
}

// 닉네임 저장하기
function saveNickname(nickname) {
  room.hidden = false;
  nicknameSet.hidden = true;
  chat.hidden = true;

  roomForm.querySelector("input").focus();

  // 채팅방 이름에 이벤트 리스너 추가
  roomForm.addEventListener("submit", handleRoomName);
}

// 닉네임 버튼 핸들러
function handleNickName(event) {
  event.preventDefault();

  const input = nicknameForm.querySelector("input");
  const nickname = input.value;

  socket.emit("nickname", nickname, saveNickname);
}

nicknameForm.addEventListener("submit", handleNickName);

socket.on("greeting", (nickname) => {
  sendMessage(`${nickname} has joined!`);
});

socket.on("goodbye", (nickname) => {
  sendMessage(`${nickname} has left!`);
});

socket.on("sendMessage", sendMessage);

다음으로 server.js에서 닉네임 부분을 처리해줍니다. 기존 코드에서 따로 떼어내기가 어려워 모든 코드를 첨부합니다. 주석이 붙은 부분을 중점적으로 보시면 됩니다.

// server.js

import http from "http";
import { Server } from "socket.io";
import express from "express";

const app = express();

app.set("view engine", "pug");
app.set("views", __dirname + "/views");
app.use("/public", express.static(__dirname + "/public"));

app.get("/", (_, res) => res.render("home"));
app.get("/*", (_, res) => res.redirect("/"));

const httpServer = http.createServer(app);
const ioServer = new Server(httpServer);

ioServer.on("connection", (socket) => {
  socket.onAny((event) => {
    console.log(`Socket Event: ${event}`);
  });
  socket.on("room", (roomName, showRoom) => {
    socket.join(roomName);
    showRoom(roomName);
    // 환영 메시지에 닉네임 추가
    socket.to(roomName).emit("greeting", socket["nickname"]);
    // 메시지 옆에 닉네임 추가
    socket.on("message", (message, addMessage) => {
      message = `${socket["nickname"]}: ${message}`;
      socket.to(roomName).emit("sendMessage", message, addMessage(message));
    });
  });
  // 퇴장 메시지에 닉네임 추가
  socket.on("disconnecting", () => {
    socket.rooms.forEach((room) =>
      socket.to(room).emit("goodbye", socket["nickname"])
    );
  });
  // 닉네임 설정 이벤트 처리
  socket.on("nickname", (nickname, saveNickname) => {
    socket["nickname"] = nickname;
    console.log(`설정한 닉네임: ${socket["nickname"]}`);
    saveNickname(nickname);
  });
});

httpServer.listen(8000);

마지막으로 테스트를 해보겠습니다. 아래와 같이 닉네임을 설정하고, 방에 참여하여, 메시지를 주고 받을 수 있다면 성공입니다!

'개발 > Projects' 카테고리의 다른 글

[WebSocket/Socket IO] 채팅 서비스 구현 9. 공개 채팅방 찾고 알림 전송하기  (0) 2022.12.07
[WebSocket/Socket IO] 채팅 서비스 구현 7. 메시지 전송 및 수신  (0) 2022.12.06
[WebSocket/Socket IO] 채팅 서비스 구현 6. 채팅방 알림 전송하기  (0) 2022.12.06
'개발/Projects' 카테고리의 다른 글
  • [WebSocket/Socket IO] 채팅 서비스 구현 10. 관리자 패널 추가하기
  • [WebSocket/Socket IO] 채팅 서비스 구현 9. 공개 채팅방 찾고 알림 전송하기
  • [WebSocket/Socket IO] 채팅 서비스 구현 7. 메시지 전송 및 수신
  • [WebSocket/Socket IO] 채팅 서비스 구현 6. 채팅방 알림 전송하기
휘Hwi
휘Hwi
여행, 사진, 개발, 책 이야기를 기록하는 여행자 휘의 블로그 𓂍
Klook.com
  • 휘Hwi
    휘: 끝나지 않은 이야기
    휘Hwi
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 기록
        • 일상 에세이
        • 인사이트
        • 투자와 재테크
        • 코인 이야기
        • 아카이빙
        • 집무실 레터
        • 사랑에 대하여
        • 번역 이야기(完)
        • 프리랜서 일지(完)
      • 여행
        • 🌎 세계 여행기 S1 (完)
        • 🌊 삼삼한 여행기 (完)
        • 🚶 온더로드
        • 🇯🇵 일본
        • 🏝️ 발리
        • 🇻🇳 베트남
        • 🇱🇰 스리랑카
        • 🇮🇳 인도
        • 🇹🇭 태국
        • 🇸🇬 싱가포르
        • 🇦🇺 호주
        • 🇭🇰 홍콩
        • 🇰🇷 한국
        • 🍚 여행자의 한 끼
        • ℹ️ 여행 정보
      • 사진
        • 사진가
        • 사진 이론과 생각
        • 사진 관련 정보
      • 영상
        • 파이널컷 모션 공부
        • 고프로 GoPro
        • 영상 관련 정보
      • 책
        • 책 읽고 쓰기
      • 개발
        • 티스토리
        • Internet
        • HTML
        • CSS
        • JavaScript
        • Typescript
        • React
        • Node.js
        • Express
        • NestJS
        • Python
        • Django
        • MySQL
        • MongoDB
        • AWS
        • Deployment
        • Terminal
        • Git
        • Glossaries
        • Articles
        • Projects
        • TIL;
      • 미분류
  • 인기 글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
휘Hwi
[WebSocket/Socket IO] 채팅 서비스 구현 8. 닉네임 설정하기
상단으로

티스토리툴바