항해99WIL - 11주차

bo-oram·2022년 7월 25일
0

항해99_WIL

목록 보기
10/10

원하는 아웃풋 : 실시간 알림
누군가 나를 포함하는 이벤트를 이르키면 나에게 누군가가 이벤트를 발생시켰다 라는 알림이 오게 하고 싶다

여기서 우리 팀은 socket io라는 라이브러리를 사용했다. 사실 구글링해보면 알림은 굳이 소켓을사용하지 않아도 구현가능하다 실시간인척 하도록 매 시간마다 계속 요청을 보내면 되니까..! 하지만 꼭 경험해보고 싶은 나의 작은 아기고양이 소켓(전혀 작지않음..)

자! 그럼 소켓 통신이 무엇인가
기본적으로 내가 알고있는 웹브라우저에서 이루어지고 있는 통신은 HTTP통신이다 HTTP통신은 HyperText Transfer Protocol의 약자로 html파일을 전송하는 프로토콜을 의미한다(만들어진 목적은 이러하나 현재는 json, image 파일 등 또한 전송한다)HTTP 통신의 통신 방법은 단방향 통신이다 즉 클라이언트의 요청이 있을 때 서버는 응답한다 하지만 내 경우 유저가 이벤트를 발생시킬 때까지 눈 똑띠 뜨고 기다렸다가 다른 유저에게 알려주기가 조금 귀찮다 위에서 말한것처럼 매초에 한번씩 요청을 해도 되지만 의미없는 요청이 너무 많이 일어날 것이다. 소켓통신은 양방향 통신이다 즉 클라이언트도 서버로 요청을 보낼 수 있고 서버도 클라이언트로 요청을 보낼 수 있다 내 경우 누군가 눈 똑띠 뜨고 기다리고 있지 않아도 서버가 뭐 왔는데? 하고 보내준단 소리다 하지만 소켓 통신은 계속해서 Connection을 들고 있기 때문에 http통신에 비해 많은 리소스가 소모된다

정리
1. http 통신은 단방향 통신이다 요청이 있을 때 응답이 이루어진다
2. socket 통신은 양방향 통신으로 C와 S모두 요청할 수 있다
3. 데이터를 자주 주고받는 채팅, 스트리밍 등이 아닌경우 http통신이 더 유리하다


import { io } from "socket.io-client";
///중략///

const [socket, setSocket] = useState(null);
//다른 컨포넌트에 프롭스로 주기 편하도록 변수에 할당했다 사실 리덕스에 넣어서 쓰고 싶었는데..잘 안됐다
//그래서 사용하려는 컴포넌트에 정말 노추천노추천인 프롭스에 프롭스로 전달했다
useEffect(() => {
  setSocket(io("서버주소")); //마운트 될 때 연결
  return disconnectSocket();//언마운트 될 때 연결끊기
}, []);

const disconnectSocket = () => {
    socket?.on("disconnect", () => {
      socket.connect();
    });
  };

///중략///

//socket.emit으로 이벤트를 요청하고 socket.on으로 받는다  
// 아래처러 사용했다
const notiList = async () => {
    await socket?.emit("getAlert", { receiverId: userInfo.userId });
    await socket?.on("getNotification", (data) => {
      console.log(data)//콘솔로 온 데이터 찍어보기
      setNotifications(data.findAlertDB); //이벤트
    });
  };

사실 아직도 잘 모르겠다 어쩌다 이 블로그로 진입한 그대는 절대 이걸 참고하지 않길 바란다 열심히 공부해서 참고할만한 자료로 바꿔 나가겠다!!!

socket io client를 임포트 하고 io("서버주소")면 연결은 끝이다. console로 찍어보면 아래처럼 나오기도 하고 서버와 요청응답을 해보며 연결을 확인할 수 있다.

그리고 emit으로 요청하고 on으로 응답을 받는다 받은 응답으로 이벤트 처리를 해주면된다.
나는 실시간으로 온 데이터와 실시간으로 쌓인 데이터리스트를 받았다 실시간으로 온 데이터는 카운팅해서 숫자로 유저에게 너가 안본 알림이 몇개야!라고 알려주는 카운트용으로 사용했고 쌓인 데이터는 목록으로 보여주었다


여기의 느낌표 대신 숫자가 들어가는 것이다 종 아이콘을 누르면 목록이 보인다 실시간으로 받아 카운팅해서 숫자로 표시한다고 해도 새로고침하면 말짱도루묵이다.. 왜냐 클라이언트에서 다루는 데이터는 휘발휘발이기 때문 휘발... 그래서 로컬 스토리지를 이용했다 마운트됨과 동시에 로컬 스토리지에 0을 넣어두고 실시간으로 소켓통신이 올때마다 꺼내서 1을 더한 후 다시 넣었다 그리고 로컬 스토리지에 넣어둔 숫자를 종아이콘 앞에 넣어주었다. 종아이콘을 누르면 로컬 스토리지에 넣어둔 넘버를 다시 0으로 바꾼다 숫자가 0일경우 종앞에는 아무것도 표시 되지 않는다

///중략

//마운트됨과 동시에 로컬 스토리지에 0을 넣고
useEffect(() => {
    if (!localStorage.getItem("newNoti")) {
      localStorage.setItem("newNoti", 0);
    }
  }, []);

// 중략

// 소켓통신이 오면 꺼내서 1일 더하고 다시 넣었다 
// 주의할것은 로컬스토리지는 문자만 넣을 수 있다 배열등 다른 형태로 넣을거면 처리를 해주어야한다
// 나는 문자열이 된 "0"을 꺼내 넘버로 변환하고 1일 더했다
// 자바스크립트라 지가 알아서 문자여도 숫자 취급해줄지 알았는데 아니였음
 const addStore = async () => {
  await  socket?.on("AddStore", (data) => {
      if (data) {
        let myNewNoti = localStorage.getItem("newNoti");
        myNewNoti = Number(myNewNoti);
        localStorage.setItem("newNoti", myNewNoti + 1);        
        setNewStore((prev) => [...prev, data]);
      }
    })
  }
 
 //중략
 
 // 로컬스토리지에 저장한 숫자를 가져다 종앞에 표시해주기
 // 버튼을 누르면 다시 0으로 셋팅(이름이 동일하면 덮어써짐)
 let notiCount = localStorage.getItem('newNoti')
 
 const notiModalOpen = () => {
    setModal(true)
    localStorage.setItem("newNoti", 0);    
  }
 
 <button onClick={notiModalOpen}>
   <img src={notice} alt="알림창"></img>
   { Number(notiCount) > 0 && <NotiCount>{notiCount}</NotiCount> }
</button>
  
  

이번 알림을 진행하면서 유즈이팩트의 디펜던시값이 얼마나 중요한지 알았다 내가 뭐만 하면 무한 렌더링이다... 좀 더 공부가 필요한... 넘무 재미써 진짜

profile
매일 도망가는 나 잡아오기

0개의 댓글