Skip to content

기술공유 05. 채널 방문자 수를 실시간으로 카운트 하기🦉

DHKIM edited this page Dec 22, 2019 · 2 revisions

드로피 기술공유 채널 방문자 카운트🦉

왜 필요한가요? 🤔

채널에 사람이 몇명 있는지 확인하는 것이 중요하다고 생각했습니다.

이유는 심플했습니다. 몇명이 접속했는지 궁금하기 때문입니다. (사실 캠퍼분들에게 요청이 많이 들어왔습니다.🤭)

어떤식으로 방문자를 카운트 할 수 있을까요?🌝

가장 간단한 방법은 Socket을 이용한 방법이었습니다. 정말 간단하게 Socket IO에서 지원하는 length함수를 이용해 카운팅을 하는 방식이 있습니다.

하지만 저희는 일반적인 web socket이 아니라 apollo web socket을 이용했습니다. Apollo web socket은 legnth를 지원해주지 않았습니다.

문제는 더 있었습니다. 기존에 저희가 설계한 방식이 처음 웹이 시작할 때, socket을 연결한다는 점이었습니다. 그래서 단순하게 connect와 disconnect를 이용해 사람 수를 관리한다면, 채널 내의 사용자 관리가 힘들고, 전체 드로피 웹에 있는 사용자를 계산하는 식이 되버렸습니다.

그래서 저희는 채널에 들어온 사람과 나간 사람을 계산할 수 있는 브라우저 이벤트를 이용한 방식을 구상했습니다.

채널에 들어오는 순간 배열에 유저를 검색하고 없으면 추가하는 방식이었습니다.

들어오는 부분에 대해서는 전혀 문제가 없었습니다. 하지만 나가는 경우 onbeforeunload와 같은 이벤트를 사용해 처리하면 문제 없을거라는 생각과는 달리, 오차가 지속적으로 발생했습니다.

생각보다 구현도 만만치 않았고, 시간을 많이 잡아 먹었습니다. 그렇게 해서 1차 시도는 포기를 하고 말았습니다. 급한 개발이 추가되었기 때문이죠..(변명..🐤)

imageMagick

🤔 잊고있던 feature가 생각났습니다. 채널 내 사용자를 카운트를 해야 합니다. 😥

어떻게 할까 팀원들과 고민하다가.. 결국 web socket을 이용하는 방법밖에 없다 라는 결론이 나왔습니다.

이유는 첫 째, 명확한 함수가 존재했습니다. ApolloServer에서 제공해주는 onConnect, onDisconnect를 이용하면, socket이 접속될 때, 그리고 접속이 해제되는 걸 잡아낼 수 있었습니다.

둘 째, 첫 번째 이유에 따른 강제종료나 다른 브라우저 현상 및 인터넷 현상도 동일하게 적용할 수있다는 장점이 있습니다.

널 구현해버리겠어😠

구현 방식을 요약하면, Apollo-server 에서 subscription의 하위에 있는 함수인 onConnect 그리고 onDisconnect를 이용합니다.

클라이언트는 무얼 해야 할까요?🤔

먼저 wsClientwsParams 를 graphql/link에서 가지고 왔습니다. 클라이언트에서 socket이 접속될 때와 해제될 때 꼭 필요한 (채널아이디) 정보를 넘기기 위함입니다.

import { wsClient, wsParams } from '@/graphql/link';

const Entrance = ({
  children,
  channelId,
  isMaster,
}) => {
  useEffect(() => {
    wsParams.channelId = channelId;
    wsParams.isMaster = isMaster;
    wsClient.connect();

    return () => {
      wsClient.close();
      wsParams.channelId = null;
      wsParams.isMaster = false;
    };
  }, [channelId, isMaster]);

  return <>{children}</>;
};

위와 같이 web socket을 감지할 수 있는 Provider를 만들어 채널에 감싸줬습니다.☺️

이제 채널에 입장하고 나갈때 감지할 수 있는 작업이 클라이언트에서는 마무리 되는 것이죠!

서버사이드는 무얼 해야 해요?🤔

subscriptions: {
  onConnect: async () => {};
  onDisconnect: async () => {};
};

Apollo Server에서 사용할 수 있는 onConnect와 onDisconnect를 사용합니다!

onConnect

클라이언트로부터 채널 정보를 받은 서버는 데이터베이스에서 채널에 이사람이 존재하는지 토큰을 통해 검사를 한 후에 없으면 추가를 해줍니다. 그 후에 pubsub을 이용해 채널 내에 있는 사용자에게 배열 length값을 알려줍니다.

추가로 이 사람이 채널의 스피커인지 리스너인지도 확인을 합니다. 이는 스피커가 onConnected인 상태이면, 프레젠테이션 상태를 on 으로 바꿔주기 위함입니다.

onDisconnect

마찬가지로 정보를 받은 서버는 데이터베이스에서 채널에 이사람이 존재하는지 검사를 합니다.

그 후에 있으면 그 사람을 삭제를 합니다. 같은 방식으로 pubsub을 이용해 채널 내에 있는 사용자에게 배열 length값을 알려줍니다.

그 리고 스피커라면, 프레젠테이션 상태가 off 가 됩니다.

알고나니까 그 떈 왜그렇게 고민했을까? 하지만 정말 보람찬 작업이었습니다!!

참고자료

Clone this wiki locally