Roothyo
루시오의 Devlog
Roothyo
전체 방문자
오늘
어제
  • 분류 전체보기 (92)
    • ComputerScience (56)
      • 자료구조 (1)
      • 알고리즘 (6)
      • 네트워크 (12)
      • 코딩테스트 (34)
      • AI & ML (1)
      • BlockChain (1)
      • Security (1)
    • Programming Language (8)
      • JavaScript (8)
      • Python (0)
    • 서비스개발(Web, App) (18)
      • Front-End (2)
      • Back-End (8)
      • Cloud Server (2)
      • DevOps (4)
    • 프로젝트 (9)
      • UNY (4)
      • ThrowOrNot (4)
      • MoA (1)
    • 잡담 (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • Vast
  • 네트워크
  • nodejs
  • Socket.io
  • github
  • Nest.js
  • TLS
  • Node
  • 코테
  • VPAID
  • node.js
  • 네트워크공부
  • Redis
  • 완전탐색
  • 프로그래머스
  • 알고리즘
  • chat
  • Python3
  • 클라우드서버
  • vmap
  • 코딩테스트
  • level2
  • FRONT-END
  • 백준
  • js
  • 애자일프로젝트
  • JavaScript
  • Python
  • 비디오광고
  • OpenVidu

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Roothyo
프로젝트/UNY

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

socket.io 실시간 chat 구현 (react - Node.js) - (2)
프로젝트/UNY

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

2021. 7. 8. 18:25

다음은 앞서 설명했던 단계들이 socket.io에서 어떻게 구현되어 있는지를 알아보겠다.

클라이언트단은 React.js 서버단은 Node.js를 사용하였다.

 

1. 소켓 생성

: 클라이언트는 socket.io-client에서 server의 IP와 port를 넣고 변수를 생성하면 된다.

클라이언트 - socket()

//./component/socket.js
import React from 'react';
import io from "socket.io-client";
// import { SOCKET_URL } from "config";

export const socket = io('localhost:5000');
export const SocketContext = React.createContext();

: 서버는 socket.io에서 http server를 인식시키고, port를 선택하여, 요청을 listen한다. 

서버 - socket(), bind(), listen()

// server.js

const server = require('http').createServer(app);
const io = require('socket.io')(server, {cors : {origin : "*"}});
const port = process.env.PORT || 5000;

io.listen(port, () => {
  console.log('Server listening at port %d', port);
});

 

2. 연결, 연결 해제 및  데이터 전송

클라이언트 : emit(), on()

서버 : emit(), on()

 

1. client로 부터 username과 함께, 'add user'로 접근한다.

//client

useEffect(async() => {
    socket.emit('add user', nickname);
    
    ...
});

2. io.on('connection', (socket) => { ... }) 에서 연결을 처리하며, numUsers와 socket의 임의의 parameter인 username을 붙여서 관리한다.

//server.js

io.on('connection', (socket) => {
  let addedUser = false;

  // when the client emits 'add user', this listens and executes
  socket.on('add user', (username) => {
    if (addedUser) return;

    // we store the username in the socket session for this client
    socket.username = username;
    ++numUsers;
    console.log("connected : "+socket.id+" num : "+numUsers);
    addedUser = true;
    socket.emit('login', {
      numUsers: numUsers
    });
    // echo globally (all clients) that a person has connected
    socket.broadcast.emit('user joined', {
      username: socket.username,
      numUsers: numUsers
    });
  });

3. 요청받은 request를 처리하고, emit을 통해서, response 하면, client에서는 on을 통하여, 그에 해당하는 동작들을 실행한다.

//client 

useEffect(async() => {
      
    socket.emit('add user', nickname);
    
    socket.on('login', (data) => {
      setIsConnected(true);    
      addChatMessage(data);
    });
    socket.on('user joined', (data) =>{
      setchats(chats.concat(`${data.username} joined`));
    })
});

4. client에서 새로운 Msg를 'new message'로 전달하면, broadcast 명령을 통해서, msg를 전달한 client를 제외한 나머지 socket에 msg를 emit 해준다.

//client

const sendMessage = () => {
    console.log(Msg);
    setchats(chats.concat(`${nickname} : ${Msg}`));
    socket.emit('new message', Msg);
    setMessage('');
}

useEffect(async() => {
      
    socket.on('new message', (data) => {
      setchats(chats.concat(`${data.username} : ${data.message}`));
    });
    return () => {
      socket.off('login');
      socket.off('disconnect');
      socket.off('new message');
    };
});
io.on('connection', (socket) => {
 

  // when the client emits 'new message', this listens and executes
  socket.on('new message', (data) => {
    console.log(`${socket.username} : ${data}`);
    // we tell the client to execute 'new message'
    socket.broadcast.emit('new message', {
      username: socket.username,
      message: data
    });
  });
  
  ...
}

최종 코드

클라이언트

const Home = () => {
  const location = useLocation();
  const nickname = location.state.nickname;
  const [chats, setchats] = useState([]);
  const [isConnected, setIsConnected] = useState(socket.connected);
  const [Msg, setMessage] = useState(null);

  const addChatMessage = (data) => {
    let message = '';
    if (data.numUsers === 1) {
      message += `there's 1 participant`;
    } else {
      message += `there are ${data.numUsers} participants`;
    }
    setchats(chats.concat(message));
  }

  useEffect(async() => {
      
    socket.emit('add user', nickname);
    
    socket.on('login', (data) => {
      setIsConnected(true);    
      addChatMessage(data);
    });
    socket.on('user joined', (data) =>{
      setchats(chats.concat(`${data.username} joined`));
    })
    socket.on('user left', (data) => {
      setchats(chats.concat(`${data.username} left`));
    });
    socket.on('disconnect', () => {
      setIsConnected(false);
    });
    socket.on('new message', (data) => {
      setchats(chats.concat(`${data.username} : ${data.message}`));
    });
    return () => {
      socket.off('login');
      socket.off('disconnect');
      socket.off('new message');
    };
  });

  const sendMessage = () => {
    console.log(Msg);
    setchats(chats.concat(`${nickname} : ${Msg}`));
    socket.emit('new message', Msg);
    setMessage('');
  }

  const onChange = (e) =>{
    setMessage(e.target.value);
  }

  return (
    <div className="App">
      <header className="App-header">
        <p>Connected: { '' + isConnected }</p>
        <p>socket ID: {nickname+`(${socket.id})` }</p>
        <div className="scrollBlind">
          <ul class ="message">
            {chats.map((val, index) => {
              return (<li key={index}>{val}</li>);
            })}
          </ul>
        </div>
        <div>
          <input 
            onChange={onChange} value={Msg} class="inputMessage" 
            placeholder="Type here..." 
            onKeyPress={(e)=>{
              if (e.key === 'Enter')
                sendMessage();
            }}/>
          <button onClick={sendMessage} >Send</button>
        </div>
      </header>
    </div>
  );
};

export default Home;

 

서버

// Routing
app.use(express.static(path.join(__dirname, 'public')));

// Chatroom
let rooms = ["room1", "room2", "room3"];
let numUsers = 0;

io.on('connection', (socket) => {
  let addedUser = false;

  // when the client emits 'new message', this listens and executes
  socket.on('new message', (data) => {
    console.log(`${socket.username} : ${data}`);
    // we tell the client to execute 'new message'
    socket.broadcast.emit('new message', {
      username: socket.username,
      message: data
    });
  });

  // when the client emits 'add user', this listens and executes
  socket.on('add user', (username) => {
    if (addedUser) return;

    // we store the username in the socket session for this client
    socket.username = username;
    ++numUsers;
    console.log("connected : "+socket.id+" num : "+numUsers);
    addedUser = true;
    socket.emit('login', {
      numUsers: numUsers
    });
    // echo globally (all clients) that a person has connected
    socket.broadcast.emit('user joined', {
      username: socket.username,
      numUsers: numUsers
    });
  });

  // when the client emits 'typing', we broadcast it to others
  socket.on('typing', () => {
    socket.broadcast.emit('typing', {
      username: socket.username
    });
  });

  // when the client emits 'stop typing', we broadcast it to others
  socket.on('stop typing', () => {
    socket.broadcast.emit('stop typing', {
      username: socket.username
    });
  });

  // when the user disconnects.. perform this
  socket.on('disconnect', () => {
    
    if (addedUser) {
      --numUsers;
      console.log("disconnected : "+socket.id+" num : "+numUsers);
      // echo globally that this client has left
      socket.broadcast.emit('user left', {
        username: socket.username,
        numUsers: numUsers
      });
    }
  });
});

 

실행화면

 

 

소스코드 

https://github.com/geun9716/node-multiroom-chat

 

geun9716/node-multiroom-chat

Multi rooms chatting system demo by Using socket.io in node.js - geun9716/node-multiroom-chat

github.com

 

'프로젝트 > UNY' 카테고리의 다른 글

socket.io 실시간 chat API 서버 (Node.js, Socket.io, Redis)  (0) 2022.04.20
socket.io 실시간 chat 구현 (react - Node.js) - (1)  (0) 2021.07.08
CI board 와 xampp 로컬 설정  (0) 2021.07.05
  • 최종 코드
'프로젝트/UNY' 카테고리의 다른 글
  • socket.io 실시간 chat API 서버 (Node.js, Socket.io, Redis)
  • socket.io 실시간 chat 구현 (react - Node.js) - (1)
  • CI board 와 xampp 로컬 설정
Roothyo
Roothyo
개발 관련 지식 포스팅/ 잡담 블로그 입니다. 반갑습니다! (github : https://github.com/geun9716)

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.