react 컴포넌트에 websocket 적용하기

2021. 2. 9. 14:28·WEB/React
반응형

코드 ver 0.2

import React, { useEffect, useState, useRef } from "react";

const SocketTest = () => {
  const [socketConnected, setSocketConnected] = useState(false);
  const [sendMsg, setSendMsg] = useState(false);
  const [items, setItems] = useState([]);

  const webSocketUrl = `ws://websocket.com`;
  let ws = useRef(null);

  // 소켓 객체 생성
  useEffect(() => {
    if (!ws.current) {
      ws.current = new WebSocket(webSocketUrl);
      ws.current.onopen = () => {
        console.log("connected to " + webSocketUrl);
        setSocketConnected(true);
      };
      ws.current.onclose = (error) => {
        console.log("disconnect from " + webSocketUrl);
        console.log(error);
      };
      ws.current.onerror = (error) => {
        console.log("connection error " + webSocketUrl);
        console.log(error);
      };
      ws.current.onmessage = (evt) => {
        const data = JSON.parse(evt.data);
        console.log(data);
        setItems((prevItems) => [...prevItems, data]);
      };
    }

    return () => {
      console.log("clean up");
      ws.current.close();
    };
  }, []);

  // 소켓이 연결되었을 시에 send 메소드
  useEffect(() => {
    if (socketConnected) {
      ws.current.send(
        JSON.stringify({
          message: sendMessage,
        })
      );

      setSendMsg(true);
    }
  }, [socketConnected]);

  return (
    <div>
      <div>socket</div>
      <div>socket connected : {`${socketConnected}`}</div>
      <div>res : </div>
      <div>
        {items.map((item) => {
          return <div>{JSON.stringify(item)}</div>;
        })}
      </div>
    </div>
  );
};

export default SocketTest;

onmessage 메서드는 send 후 데이터가 올 때 트리거가 되므로 웹소켓 객체 정의 안으로 이동했습니다. send 메소드는 따로 빼지 않고 onopen 함수 안에 넣어도 됩니다. 


코드 ver 0.1

import React, { useEffect, useState, useRef } from "react";

const SocketTest = () => {
  const [socketConnected, setSocketConnected] = useState(false);
  const [sendMsg, setSendMsg] = useState(false);
  const [items, setItems] = useState([]);

  const webSocketUrl = `ws://websocket.com`;
  let ws = useRef(null);

  // 소켓 객체 생성
  useEffect(() => {
    if (!ws.current) {
      ws.current = new WebSocket(webSocketUrl);
      ws.current.onopen = () => {
        console.log("connected to " + webSocketUrl);
        setSocketConnected(true);
      };
      ws.current.onclose = (error) => {
        console.log("disconnect from " + webSocketUrl);
        console.log(error);
      };
      ws.current.onerror = (error) => {
        console.log("connection error " + webSocketUrl);
        console.log(error);
      };
    }

    return () => {
      console.log("clean up");
      ws.current.close();
    };
  }, []);

  // 소켓이 연결되었을 시에 send 메소드
  useEffect(() => {
    if (socketConnected) {
      ws.current.send(
        JSON.stringify({
          message: sendMessage,
        })
      );

      setSendMsg(true);
    }
  }, [socketConnected]);

  // send 후에 onmessage로 데이터 가져오기
  useEffect(() => {
    if (sendMsg) {
      ws.current.onmessage = (evt) => {
        const data = JSON.parse(evt.data);
        console.log(data);
        setItems((prevItems) => [...prevItems, data]);
      };
    }
  }, [sendMsg]);

  return (
    <div>
      <div>socket</div>
      <div>socket connected : {`${socketConnected}`}</div>
      <div>res : </div>
      <div>
        {items.map((item) => {
          return <div>{JSON.stringify(item)}</div>;
        })}
      </div>
    </div>
  );
};

export default SocketTest;

 

코드를 짜면서 고민했던 점은 컴포넌트가 unmount 되었을 때 socket 연결이 끊어지기를 바랬습니다. 여러 시행 착오 끝에 소켓 객체를 생성하는 useEffect에 clean up을 하는 것이 원하는대로 동작하였습니다.

 

소켓 객체를 컴포넌트 밖에 전역으로 생성하기 보다는 컴포넌트에 ref를 통해 저장이 되도록 하고, 소켓 객체의 send 메소드와 onmessage 메소드가 순차적으로 실행되기를 바래서 위와 같이 작성했습니다.

 

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

'WEB > React' 카테고리의 다른 글

react 컴포넌트가 unmount 된 후 setState가 실행되는 문제 해결 방법  (0) 2021.07.12
폴더 안의 파일을 모두 import 하는 방법  (0) 2021.02.16
redux 강의 기본 핵심 튜토리얼 5탄 - redux data 사용하기  (0) 2020.11.16
redux 강의 기본 핵심 튜토리얼 4탄 - redux data flow  (0) 2020.11.11
redux 강의 기본 핵심 튜토리얼 3탄 - redux app 구조  (0) 2020.11.03
'WEB/React' 카테고리의 다른 글
  • react 컴포넌트가 unmount 된 후 setState가 실행되는 문제 해결 방법
  • 폴더 안의 파일을 모두 import 하는 방법
  • redux 강의 기본 핵심 튜토리얼 5탄 - redux data 사용하기
  • redux 강의 기본 핵심 튜토리얼 4탄 - redux data flow
vitnal
vitnal
4년차 프론트엔드 개발자 입니다. 이 블로그는 기록하고 싶은 내용을 저장하기 위해 사용하고 있습니다. 정제되지 않은 내용이 있을 수 있는 점 양해 부탁드립니다.
  • vitnal
    vitnal 아카이브
    vitnal
  • 전체
    오늘
    어제
    • 분류 전체보기 (149) N
      • AI (0)
      • WEB (76)
        • React (21)
        • Nextjs (17)
        • JavaScript (16)
        • React Native (5)
        • HTML & CSS (7)
      • CS (3)
      • Git (15)
      • Dev Tools (23)
      • Deploy (12)
      • Tech Memo (12) N
      • Retrospect (7)
  • 반응형
  • hELLO· Designed By정상우.v4.10.5
vitnal
react 컴포넌트에 websocket 적용하기
상단으로

티스토리툴바