미새문지

웹 소켓(Web Socket) 채팅 앱 만들기 - 유저 로그인 본문

웹 프론트엔드

웹 소켓(Web Socket) 채팅 앱 만들기 - 유저 로그인

문미새 2024. 4. 28. 21:10
728x90

코딩알려주는누나 웹소켓 강의 : https://www.youtube.com/watch?v=oFiw5VvgRFg&t=0s

 

이전 학습 내용:

https://moonmisae-cdpt.tistory.com/209

 

웹 소켓(Web Socket) 채팅 앱 만들기 - 클라이언트 서버 연결

유튜브의 코딩알려주는누나 영상에서 채팅앱을 만드는 강의를 듣고 작성한다. 코딩알려주는누나 강의 영상: https://www.youtube.com/watch?v=uE9Ncr6qInQ웹 소켓(WebSocket)웹 상에서 양방향 통신을 가능하게

moonmisae-cdpt.tistory.com

다음 학습 내용:

https://moonmisae-cdpt.tistory.com/212

 

웹 소켓(Web Socket) 채팅 앱 만들기 - 메세지 전송

코딩알려주는누나 유저로그인 강의 : https://www.youtube.com/watch?v=pRGOEtGjI-k&t=0s 이전 학습내용:https://moonmisae-cdpt.tistory.com/211 웹 소켓(Web Socket) 채팅 앱 만들기 - 유저 로그인코딩알려주는누나 웹소켓

moonmisae-cdpt.tistory.com


백엔드 프론트엔드 웹 소켓 연동이 끝났으니 이제 유저 로그인을 구현해야 한다.

이름을 입력하기 위해 깃허브에서 받은 폴더의 app.js에 코드를 추가해준다.

import "./App.css";
import socket from "./server";
import {useEffect} from "react";

function App() { 
  
  useEffect(() => {
    askUserName();
  }, [])

  const askUserName = () => {
    const userName = prompt("이름을 입력하세요.");
    console.log("이름 : ", userName); 
  }
  return (
    <div>
      <div className="App"></div>
    </div>
  );
}

export default App;

 

이름을 입력할 수 있는 프롬프트 창을 생성하는 함수를 만들고 그 함수를 페이지가 렌더링될 때 실행되는 useEffect를 사용해 함수를 실행시킨다.

클라이언트를 npm start로 실행시켜보면 이름을 물어보는 프롬프트 창이 뜬다.

프롬프트 창
console.log

이름을 입력했을 때 콘솔 창에 이름이 뜨는 것을 확인할 수 있다.

 

입력을 확인했으면 이제 이 이름을 서버로 보내기 위해 app.js에 코드를 추가해준다.

import "./App.css";
import socket from "./server";
import {useEffect} from "react";

function App() { 
  
  useEffect(() => {
    askUserName();
  }, []);

  const askUserName = () => {
    const userName = prompt("이름을 입력하세요.");
    console.log("이름 : ", userName);

    socket.emit("login", userName, (res) => {
      console.log("Res", res)
    });
  };

  return (
    <div>
      <div className="App"></div>
    </div>
  );
}

export default App;

emit이라는 원하는 이벤트명으로 특정 인자를 전달할 수 있는 함수를 사용해 서버에 유저 이름을 전달해준다.

 

이제 백엔드에서 전달을 받아야 하는데, utils의 io.js에 로그인을 받을 수 있는 코드를 작성한다.

module.exports = function(io) {
    // 클라이언트 연결을 받을 수 있는 on을 사용해 연결되면 메세지 출력
    io.on("connection", async(socket) => {
        console.log("client is connected", socket.id);

        socket.on("login", async(userName, cb) => {
            console.log("backend", userName);
        })

        socket.on("disconnect", () => {
            console.log("user is disconnected");
        });
    }); 
};

 

작성했으면 이제 페이지에서 이름을 입력했을 때 서버로 들어와 지는지 확인한다.

이름 전달 테스트
백엔드 전달 성공

서버로 보낸 이름이 잘 도착하는 걸 볼 수 있다.

 

연동이 확인되었으니 이제 서버에서 유저 정보를 저장할 수 있는 코드를 작성한다.

io.js 코드에서 콘솔출력을 지우고 안에 정보를 담기 위해 controller라는 폴더를 하나 추가해주고 user.controller.js라는 파일을 만들어 코드를 작성한다.

const User = require("../models/user")
const userController = {};

//유저 이름과 소켓 id를 인자로 받기
userController.saveUser = async (userName, sid) => {
    // 유저가 이미 있는지 확인
    let user = await User.findOne({name: userName});
    // 없으면 새로 유저 정보를 만들기
    if(!user) {
        user = new User({
            name: userName,
            token: sid,
            online: true,
        });
    }
    // 이미 있는 유저면 token값을 변경
    user.token = sid;
    user.online = true;

    await user.save();
    return user;
}

module.exports = userController

 

controller는 클라이언트의 요청을 받아 처리한 후 그 결과를 다시 전달해주는 역할을 하기 때문에, 클라이언트에서 받은 데이터를 어떻게 처리할지의 로직을 작성했다.

 

이 후 다시 io.js로 가서 controller에서 받은 유저 데이터를 저장하는 로직을 작성한다.

const userController = require("../controllers/user.controller");

module.exports = function(io) {
    // 클라이언트 연결을 받을 수 있는 on을 사용해 연결되면 메세지 출력
    io.on("connection", async (socket) => {
        console.log("client is connected", socket.id);

        socket.on("login", async (userName, cb) => {
            //유저 정보 저장
            try {
                const user = await userController.saveUser(userName, socket.id);
                cb({ok: true, data: user});
            } catch(error) {
                cb({ok: false, error: error.message});
            }
        })

        socket.on("disconnect", () => {
            console.log("user is disconnected");
        });
    }); 
};

작성이 끝났으면 화면에서 테스트를 해보자.

 

응답 결과

프롬프트에 이름을 넣었을 때 정상적으로 서버와 통신이 된 걸 확인할 수 있다.

 

이제 서버에서 응답을 받았으니 유저 정보의 저장을 해줘야 한다.

기존의 app.js 코드에서 유저 정보를 담을 변수를 useState로 만들고 그 값에 응답 값이 true면 저장한다.

import "./App.css";
import socket from "./server";
import {useEffect, useState} from "react";

function App() { 
  const [user, setUser] = useState(null);
  
  useEffect(() => {
    askUserName();
  }, []);

  const askUserName = () => {
    const userName = prompt("이름을 입력하세요.");
    console.log("이름 : ", userName);

    socket.emit("login", userName, (res) => {
      if (res?.ok) {
        setUser(res.data);
      }
    });
  };

  return (
    <div>
      <div className="App"></div>
    </div>
  );
}

export default App;

 

이러면 유저 이름을 넣고 서버에 요청 시 서버에서 응답한 유저 정보를 변수에 담을 수 있다.

회원 정보를 통신하는 두 번째 강의는 여기까지

728x90