[TIL] 210714

2K1·2021년 7월 18일
0

TIL

목록 보기
28/31
post-thumbnail

협업 미니프로젝트에서 내가 해야하는 부분은 다 했지만 프론트쪽에서 채팅파트를 맡은 팀원이socket.io에 대해 익숙하지가 않아서 스켈레톤 코드를 가져와서 같이 테스트를 하며 만들어가보기로 했다. 리액트를 1도 모르지만 남들이 어떻게 사용을 했는지 보면서 공부를 해갔다.

React에서는 기존 html과 다르게 기능 하나하나를 component로 만들고 element에서 css와 비슷하게 화면에 어떻게 보일지 정해주는거 같았다. 그리고 props를 통해서 받아온 데이터를 받고 그 데이터를 변수로 선언해준다음 그 변수로 어떻게 요리해서 html같은걸 안에 넣은다음 return 해주는거같았다.

일단 프론트에서는 백이랑 다르게 socket.io-client를 쓴다. 그리고 npm말고 yarn을 쓴다고했다. 그래서 yarn으로 먼저 add해주고

yarn add socket.io-client

socket.io를 import 해준다

import io from "socket.io-client";

기존에는 axios를 통해 백에서 데이터를 가져온다음 무언가를 했지만 socket.io에서는 emit과 on으로 서로 통신할때 데이터를 넘겨주기 때문에 props는 쓸일이 없었다. 그런데 내 계획은 token만 프론트에서 던져주면 백에서 jwt를 decode할 생각이였는데 다른 팀원들이 프론트에서 decode를 해주고 넘겨주는 방식으로 정해놨어서 일단 프론트에서 decode를 하기로 했다.

const ChattingBar = (props) => {
  const token = sessionStorage.getItem("MY_SESSION");
  const decoded = jwt_decode(token);
  const nickname = decoded.nickname;
  let date = new Date().toLocaleTimeString();

📂 useEffect

제일 먼저 해야할것은 io.connect로 서버에 socket이랑 연결해주는 작업이라고 생각해서 github에 올라와있는 스켈레톤 코드에서 useEffect안에서 연결해주는게 보여서 이렇게 연결을 해줬다. 그리고 dev tool network에서 연결된걸 확인했다. 그리고 밑에서 나올건데 유저가 보낸 메세지를 emit한걸 서버에서 보내주면 "receiveMsg"라는 이벤트명으로 socketRef.current.on으로 받아온 데이터들을 setChat으로 뭔가 변수 선언을 해주는 작업같았다. 채팅기록을 보내주는 chatLog도 마찬가지.

useEffect(() => {
    socketRef.current = io.connect("연결주소");
    socketRef.current.on("chatLog", (chats) => {
      setChats([...chats, { chats }]);
    });
    socketRef.current.on("receiveMsg", ({ nickname, message, date }) => {
      setChat([...chat, { nickname, message, date }]);
    });
    return () => socketRef.current.disconnect();
  }, [chat]);

📂 setState

이렇게 위에서 setState(메세지 보내기)는 useState로 {} 빈 object로 setChat(메세지 받기), setChats(채팅기록)는 useState로 [] 빈 array로 설정한다. 받아온 nickname, message, date가 들어간다.
useState를 쓰는이유는 바뀌는 변수? 상태관리를 하기위한거라고 한다.. 엄청 자세히는 모르겠다..

  const [state, setState] = useState({
    message: "",
    nickname: nickname,
    date: date,
  });
  const [chat, setChat] = useState([]);
  const [chats, setChats] = useState([]);

📂 Messages 렌더링해주기

이후에는 전에 심화프로젝트의 프론트에서 html위에 있는 scripts안에서 해준것과 비슷한거 같다.
1. 유저가 메세지를 보내면 onTextChange 함수로 변수로 선언된다.
2. onMessageSubmit 함수 안에서 message, nickname, date를 서버에 emit해준다.
3. 서버에서는 받아온 데이터 채팅 db에 저장한다음 저장된 값을 emit으로 모두에게 뿌려준다.
4. showChatLog 함수안에 temp html 비슷하게 틀을 짜고 안에 데이터를 넣은다음 그걸 렌더링하라고 return 해준다.

  const onTextChange = (e) => {
    setState({ ...state, [e.target.name]: e.target.value });
  };

  const onMessageSubmit = (e) => {
    let date = new Date().toLocaleTimeString();
    const { message, nickname } = state;
    socketRef.current.emit("sendMsg", { message, nickname, date });
    e.preventDefault();
    setState({ message: "", nickname: nickname, date: date });
  };

  const showChatLog = () => {
    if (!chats.length) {
      return <div>로딩 중...</div>;
    }
    return chats.map((chatting, index) => (
      <MessageWrap key={index}>
        <ImageWrap>
          <Image shape="circle" />
        </ImageWrap>
        <SenderWrap>
          <SenderNameSpan>{chatting.nickname}</SenderNameSpan>
          <ElMessage>{chatting.message}</ElMessage>
          <SenderTimeSpan>{chatting.date}</SenderTimeSpan>
        </SenderWrap>
      </MessageWrap>
    ));
  };

기본적으로 렌더링할 틀? 인거같다.

  return (
    <Container>
      <ChattingMode>Chat</ChattingMode>
      <ChattingList>{showChatLog()}</ChattingList>
      <ChattingInputBox>
        <form onSubmit={onMessageSubmit}>
          <ChattingInput
            placeholder="메세지를 작성 후 엔터를 눌러주세요"
            name="message"
            onChange={(e) => onTextChange(e)}
            value={state.message}
            label="Message"
          />
        </form>
      </ChattingInputBox>
    </Container>
  );
};
profile
📌dev_log

0개의 댓글