[React / Socket.io] 채팅 구현하기

2023. 9. 13. 02:11·웹 프로젝트/👨‍👨‍👧‍👧소셜 가계부
반응형

프로젝트 개발 당시 프론트는 리액트, 백엔드는 스프링으로 진행하기로 했는데 백엔드 인원이 갑작스레 빠지게 되면서 혼자 백엔드까지 구현 해야 하는 상황이 되었다. 

스프링은 한번도 해본 적이 없어서 급하게 노드로 백엔드 서버를 만들고 리액트로 프론트를 구현하기로 했다.

구글링을 통해 노드 채팅 코드를 검색했고 레퍼런스를 통해 코드의 구조를 대략적으로 이해하는 시간을 가졌다 .이후에 서버의 데이터를 프론트에서 받아 사용하는 코드를 작성했다.

 

🌅 서버 구현

우선 아래 패키지를 모두 설치해준다.

npm i nodemon express socket.io cors

 

📂 Server > 📄 index.js 

const httpServer = require("http").createServer(); //서버 객체 생성
// http server를 socket.io server로 upgrade
const io = require("socket.io")(httpServer, {
  cors: {
    origin: "http://localhost:3000",
    methods: ["GET", "POST"],
  },
}); //cors 정책 설정

//socket 연결
io.on("connection", (socket) => {
  console.log("connection");
  socket.on("init", (payload) => {
    console.log(payload);
  });

  //연결이 되면 클라이언트에 메시지를 전송하고 클라이언트로부터 메시지를 수신한다
  socket.on("send message", (item) => {
    console.log(item.author + " : " + item.message);
    io.emit("receive message", { author: item.author, message: item.message, time: item.time });
    //클라이언트에 이벤트를 보냄
  });
});

httpServer.listen(80); //80번 포트 서버 실행

 

 

🎨 프론트엔드 구현

프론트엔드에 서버 코드를 적용하는 데는 시간이 조금 더 걸렸다.

우선 프론트에서도 socket.io를 사용할 수 있도록 패키지를 설치한다.

npm i socket.io-client

 

📂 Front > 📄 ChattingView.js 

 

//80번 포트와 연결
const socket = io.connect("http://localhost:80");

서버와 연결한다.

 

  const [userInputMsg, setUserInputMsg] = useState("");
  const [chatArr, setChatArr] = useState([]);

state는 2개를 지정했다.

  • 사용자에게 메시지를 입력받는 state ---> 사용자가 입력하는 내용을 보여주고, 메시지 전송 시 창을 비워준다. 서버에 사용자의 입력을 포함한 객체를 전송한다.
  • 서버에서 받은 {author, message, time} 객체를 저장하는 배열 state

실제 채팅 구현 부분은 아래와 같다.

//서버에게서 받은 receive message이벤트에 대한 콜백
  useEffect(() => {
    socket.on("receive message", (message) => {
      setChatArr((chatArr) => chatArr.concat(message));
    });
  }, [socket]);

  //버튼 클릭 시 send message 이벤트 발생(메시지 전송)
  const sendMessageHandler = useCallback(() => {
    socket.emit("send message", {
      author: userInfo.name,
      message: userInputMsg,
      time: new Date(Date.now()).getHours() + ":" + new Date(Date.now()).getMinutes(),
    });
    setUserInputMsg("");
  }, [userInputMsg, userInfo.name]);

  //사용자에게 입력받은 채팅 내용을 기반으로 state 변경
  const changeMessage = useCallback((e) => {
    setUserInputMsg(e.target.value);
  }, []);
  • 'receive message'로 받은 메시지는 chat 배열에 추가해준다. 이때 push가 아니라 concat을 이용해 원본 배열의 변경이 없도록 한다. (concat은 값을 추가한 새로운 배열을 반환한다)
  • 사용자가 입력창에 메시지를 작성하고 전송 버튼을 누르면 sendMessageHandler 함수가 실행된다. 이때 서버에 유저이름, 작성 메시지, 작성 시간을 객체로 넘겨준다.
  • 사용자가 입력한 메시지를 userInpuMsg 변수에 저장한다. useCallback 사용하지 않을 시 엔터를 쳐서 함수 실행하면 여러번 메시지가 전송되는 버그가 발생하므로 useCallback을 반드시 설정해 준다.

 

return (
    <Section>
      <div className="contentContainer">
        {chatArr.map((messageContent) => {
          return (
            <div>
              {userInfo.name === messageContent.author ? (
                <SeneChatCard massage={messageContent.message} time={messageContent.time} />
              ) : (
                <RecieveChatCard
                  massage={messageContent.message}
                  time={messageContent.time}
                  author={messageContent.author}
                />
              )}
            </div>
          );
        })}
      </div>
      <div className="sendContainer">
        <input
          type="text"
          placeholder="메시지를 입력하세요"
          value={userInputMsg}
          onChange={changeMessage}
          onKeyDown={(event) => {
            event.key === "Enter" && sendMessageHandler();
          }}
        />
        <button onClick={sendMessageHandler}>전송</button>
      </div>
    </Section>
  );

작성자의 이름과 서버로 전송된 메시지의 작성자가 동일하면 내가 보내는 것으로 간주하고 스타일링했다.

🙄 변경점
이 부분은 이름이 동일한 사람도 있을 수 있으니 id값을 확인하는 것으로 변경해야겠다.

 

✨ 최종 화면

채팅 구현 화면

채팅목록이나 채팅 상단의 제목은 하드코딩된 상태이지만 채팅 기능은 정상적으로 동작한다.

실제 채팅 화면은 아래와 같다.

 

- 1:1 채팅

 

 

- 2명 이상 채팅

크롬, 크롬시크릿, 마이크로 엣지 3개의 브라우저로 세 명의 유저가 채팅을 진행하도록 했다. 더 많은 인원이 채팅하는 것도 가능하다.

 

 

🎈 개선점

- 채팅 유저 확인 이름->아이디로 변경

- 입력값 검증 (아무것도 입력하지 않았을 시 서버에 객체 전송 x)

- 채팅방 개설 기능

- 채팅 목록 선택 가능하도록

- 채팅방 개념 도입 (각 방에서 주고받은 메시지는 그 방에 참여 중인 사용자에게만 보이게 한다.)

 


 

참고

 

https://tinyurl.com/yt4clkjz

 

나만의 채팅 서비스 만들기 (react + express + Socketio)

갑자기 왜? 마이스터고등학교에 재학하며 다양한 프로젝트 경험을 쌓을 수 있었습니다. 다양한 프로젝트를 진행하며 여러 기술을 사용해보았지만, 정작 꼭 사용해보고 싶었던 기술인 Websocket기

velog.io

 

https://poiemaweb.com/nodejs-socketio

 

Node.js(Express)와 Socket.io | PoiemaWeb

WebSocket, Socket.io를 사용한 실시간 채팅 애플리케이션

poiemaweb.com

 

https://tinyurl.com/yw6bf94e

 

react 로 socket io 연결

webSocket에 이전부터 관심이 있어서 찾아보았는데 webSocket은 크로스 브라우징이 안되는 곳이 있다고 해서 socket.io라이브러리로 만들어 보았다.처음에 백엔드에서 설정을 해줘야 해서 폴더를 server

velog.io

 

https://roothyo.tistory.com/42

 

socket.io 실시간 chat 구현 (react - Node.js) - (2)

다음은 앞서 설명했던 단계들이 socket.io에서 어떻게 구현되어 있는지를 알아보겠다. 클라이언트단은 React.js 서버단은 Node.js를 사용하였다. 1. 소켓 생성 : 클라이언트는 socket.io-client에서 server의 I

roothyo.tistory.com

 

https://github.com/machadop1407/socket-io-react-example

 

GitHub - machadop1407/socket-io-react-example

Contribute to machadop1407/socket-io-react-example development by creating an account on GitHub.

github.com

 

반응형
저작자표시 비영리 변경금지 (새창열림)

'웹 프로젝트 > 👨‍👨‍👧‍👧소셜 가계부' 카테고리의 다른 글

[React/Node.js/Express/MongoDB] 소셜 가계부 프로젝트 구현 일지: 프론트엔드 초안 작성하기(라우터 설정, 가계부 월별 이동하기 구현)  (1) 2024.01.16
[React/Node.js/Express/MongoDB] 소셜 가계부 프로젝트 구현 일지: 기존 React + Spring Boot 소셜 로그인 코드 삭제하기  (0) 2024.01.13
[React/Node.js/Express/MongoDB] 소셜 가계부 프로젝트 구현 일지: 프로젝트 전체 기획 정리  (1) 2024.01.13
[React/Spring Boot/MySQL] 리액트+스프링부트 OAuth2 Google, Facebook, Github 소셜로그인 구현 일지 (스프링 구현x, 리액트 구현o)  (0) 2023.05.26
[React/JavaScript/Nodejs/Express] 채팅 기능을 포함한 가계부 프론트 웹 프로젝트  (0) 2022.06.27
[React, FrontEnd] 가계부 웹 사이트 프로젝트 일지-3. 달력 페이지 구현  (0) 2022.05.29
'웹 프로젝트/👨‍👨‍👧‍👧소셜 가계부' 카테고리의 다른 글
  • [React/Node.js/Express/MongoDB] 소셜 가계부 프로젝트 구현 일지: 기존 React + Spring Boot 소셜 로그인 코드 삭제하기
  • [React/Node.js/Express/MongoDB] 소셜 가계부 프로젝트 구현 일지: 프로젝트 전체 기획 정리
  • [React/Spring Boot/MySQL] 리액트+스프링부트 OAuth2 Google, Facebook, Github 소셜로그인 구현 일지 (스프링 구현x, 리액트 구현o)
  • [React/JavaScript/Nodejs/Express] 채팅 기능을 포함한 가계부 프론트 웹 프로젝트
청량리 물냉면
청량리 물냉면
프로그래밍 공부를 하고 있습니다. 공부 내용 정리 겸 정보 공유를 목적으로 합니다.
    반응형
  • 청량리 물냉면
    노력중인 블로그
    청량리 물냉면
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 프로그래밍
        • Programming
        • C | C++
        • Java
        • Python
      • 웹 프로그래밍
        • HTML | CSS
        • JavaScript | TypeScript
        • React
        • Vue.js
        • Next.js
        • Spring & Spring Boot
        • JSP & Servlet
        • DB
      • 웹 프로젝트
        • 웹 프로젝트
        • 🥨스낵몰
        • 👨‍👨‍👧‍👧소셜 가계부
        • 🌜꿈 일기장
        • 🔮포트폴리오 사이트
        • 🏃‍♂️팀 프로젝트: 일정관리 프로그램
        • 📈팀 프로젝트: AI기반 주식 분석 플랫폼
        • 😺Just Meow It: 고양이의 조언
      • 앱 프로그래밍
        • Flutter
        • Kotlin
      • Problem Solving
        • 백준
        • 프로그래머스
        • SWEA
      • Computer Science
        • 알고리즘
        • 컴퓨터 네트워크
        • 이산수학
      • Developer
        • 후기
        • 자료정리
        • 취업 | 취준
        • 웹개발 교육 프로그램
        • TIL
  • 블로그 메뉴

    • 홈
    • Github
  • 공지사항

    • 프로그래밍 공부 중😊
  • 인기 글

  • 태그

    프로그래머스
    spring boot
    백준
    뉴렉처
    플러터
    bfs
    블로그 제작
    클론 프로젝트
    d3
    React
    타입스크립트
    웹사이트
    공식문서
    강의내용정리
    Til
    SWEA
    ZeroCho
    알고리즘
    AWS
    파이썬
    컴퓨터네트워크
    구현
    Next.js
    프로젝트
    mysql
    Jiraynor Programming
    자바
    자바스크립트
    리액트
    포트폴리오
  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
청량리 물냉면
[React / Socket.io] 채팅 구현하기
상단으로

티스토리툴바