리액트에서 socket.io 알맞게 사용하기 (번역)

Dahee Kim·2021년 8월 27일
1

이 글은 아래 문서를 간단히 요약 후 번역한 것입니다.

https://dev.to/bravemaster619/how-to-use-socket-io-client-correctly-in-react-app-o65

웹 캐치마인드 게임 Scramble 코드를 짜다가, Socket.io를 React에서 어떻게 사용하면 좋을까 고민하던 중 도움이 된 아티클을 번역하였습니다. 프로젝트 규모가 작고, 클라이언트에 Socket 인스턴스가 하나만 필요한 경우 유용합니다. 좀 더 규모가 큰 프로젝트에서 Socket.io 사용에 대해 고민하는 경우 아래 문서가 도움이 될 수 있습니다.

https://meetup.toast.com/posts/11

오류가 있다면 댓글로 알려주세요!

React에서 Socket.io-client를 사용하는 방법

하나의 전역 소켓 인스턴스 관리를 위해 React.js의 Context API를 사용하는 방법을 알아봅시다. 이 글을 읽기에 앞서 React의 라이프 사이클, ContextAPI 등에 대한 기본적인 이해가 필요합니다.

1. Socket Context 생성

React.js의 useContext Hook을 사용하여 어플리케이션 전체에 SocketContext를 제공합시다.
다음과 같은 위치에 아래와 같이 파일을 생성해보세요. context/socket.js

import socketio from "socket.io-client";
import { SOCKET_URL } from "config";

export const socket = socketio.connect(SOCKET_URL);
export const SocketContext = React.createContext();

2. Socket Context를 사용하고 value 값 제공해주기

import {SocketContext, socket} from 'context/socket';
import Child from 'components/Child';

const App = () => {
  return (
    <SocketContext.Provider value={socket}>
      <Child />
      <Child />
      ...
    </SocketContext.Provider
  );
};

여기까지 작업이 끝났다면, 이제 App의 모든 자식 요소에서 소켓을 사용할 수 있습니다.

소켓 사용 예시 코드

child, grandChild등 모든 하위 요소에서 다음과 같이 소켓을 사용할 수 있습니다.

import React, {useState, useContext, useCallback, useEffect} from 'react';
import {SocketContext} from 'context/socket';

const GrandChild = ({userId}) => {

  const socket = useContext(SocketContext);

  const [joined, setJoined] = useState(false);

  const handleInviteAccepted = useCallback(() => {
    setJoined(true);
  }, []);

  const handleJoinChat = useCallback(() => {
    socket.emit("SEND_JOIN_REQUEST");
  }, []);


  useEffect(() => {
    // as soon as the component is mounted, do the following tasks:

    // emit USER_ONLINE event
    socket.emit("USER_ONLINE", userId); 

    // subscribe to socket events
    socket.on("JOIN_REQUEST_ACCEPTED", handleInviteAccepted); 

    return () => {
      // before the component is destroyed
      // unbind all event handlers used in this component
      socket.off("JOIN_REQUEST_ACCEPTED", handleInviteAccepted);
    };
  }, [socket, userId, handleInviteAccepted]);

  return (
    <div>
      { joined ? (
        <p>Click the button to send a request to join chat!</p>
      ) : (
        <p>Congratulations! You are accepted to join chat!</p>
      ) }
      <button onClick={handleJoinChat}>
        Join Chat
      </button>
    </div>
  );
};

3. JWT 토큰을 사용하여 Socket연결 인증하기

JWT 토큰을 이용한 소켓 연결이 필요하다면 아래와 같이 작성하세요.

const getSocket = () => {
  const token = getAuthToken(); // get jwt token from local storage or cookie
  if (token) {
    return socketio.connect(SOCKET_URL, {
      query: { token }
    });
  }
  return socketio.connect(SOCKET_URL);
};

그 후 서버에서 다음과 같이 JWT 토큰을 받아올 수 있습니다.

import SocketIO from "socket.io";

const io = new SocketIO.Server(expressApp);
const jwtMiddleware = (socket, next) => {
  const {token} = socket.handshake.query;
  // verify token
};

io.use(jwtMiddleware);
profile
하루가 너무 짧아~

1개의 댓글

comment-user-thumbnail
2022년 11월 29일

큰 규모 프로젝트 예시 링크 죽었어요!

답글 달기