220814 공통 프로젝트 개발일지

·2022년 8월 23일
0

개발일지 & 회고

목록 보기
17/72
post-thumbnail

타이머 이벤트 생성

제작 중인 랜덤매칭 언어교환 플랫폼은 시간이 다되면 메인 페이지로 이동하여 다시 매칭이 이루어져야 한다. 두 유저가 매칭을 통하여, useState()를 통해 5분이라는 시간을 가지게 된 후, state 값이 0분 0초를 가리키게 되는 경우 페이지로 이동시키도록 했다.

타이머 이벤트 이슈

useState() 를 통해 시간을 설정하니, 유저가 서로 시간이 다르게 되는 경우가 발생했다. 접근 환경에 따라, 미팅 페이지 진입 시간이 다르고, 진입 시에 생성되는 state 선언이 달라지기 때문에, 테스트 결과 5초 정도까지 차이가 나타나게 되었다.

타이머 이벤트 이슈 해결 : 시간 공유

useState() 외에 시간을 공유할 수 있는 로직을 고민해본 결과, 소켓 이벤트를 활용하여 미팅페이지 진입부터 유저끼리 시간을 공유한다면, 똑같이 맞출 수 있다는 생각을 하게 되었다.

신규 로직 : 타이머 로직
1. 룸생성자를 기준으로 타이머를 만든 후, 룸 입장자에게 시간 데이터를 1초마다 보낸다. 이후 각자의 시간 데이터를 자신의 로컬에 렌더링한다.
2. 타이머 카운트 처리 역시 룸 생성자가 조작한다. 룸 입장자에게는 매초마다 단순 결과값만 보낸다.
 const [minutes, setMinutes] = useState(5)
 const [seconds, setSeconds] = useState(0)

 ...
 ...
 
  useEffect(() => {
    // timer 로직 요약 설명
    // 생성자 -> 입장자 이루어지는 단방향 로직 설정
    // timer는 방 생성자가 연산하고 관리한다.
    // 방 생성자는 1초마다 연산한 timer를 제공
    // 방 입장자는 1초마다 제공되는 timer를 렌더링만 해야한다.

    // 방 생성자용 timer 설정
    const countdown = setInterval(async () => {
      if (room.isCreatedRoom) {
        const data = {
          minutes: minutes,
          seconds: seconds,
        }

        openvidu_timer_minites.current.textContent = minutes
        openvidu_timer_seconds.current.textContent =
          seconds < 10 ? `0${seconds}` : seconds

        openvidu.publisher.session.signal({
          data: JSON.stringify(data),
          type: 'timerShare',
        })

        if (seconds >= 0) {
          setSeconds(seconds - 1)
        }
        if (seconds === 0) {
          if (minutes === 0) {
            if (heart) {
              const heartData = {
                cnt: 1,
                fromUser: user.id,
                name: 'like',
                route: 'like',
                toUser: peerUser.id,
              }
              await dispatch(heartEvent({ accessToken: auth.token, heartData }))
            }
            clearInterval(countdown)
            dispatch(ovActions.leaveSession())
            window.location.replace('/meeting?rematching=true')
          } else {
            setMinutes(parseInt(minutes) - 1)
            setSeconds(59)
          }
        }
      } else {
        // 방 입장자용 timer 렌더 설정
        openvidu.session.on('signal:timerShare', event => {
          const data = JSON.parse(event.data)

          openvidu_timer_minites.current.textContent = data.minutes
          openvidu_timer_seconds.current.textContent =
            data.seconds < 10 ? `0${data.seconds}` : data.seconds

          setMinutes(data.minutes)
          setSeconds(data.seconds)
        })

        if (minutes === 0 && seconds === 0) {
          if (heart) {
            const heartData = {
              cnt: 1,
              fromUser: user.id,
              name: 'like',
              route: 'like',
              toUser: peerUser.id,
            }
            dispatch(heartEvent({ accessToken: auth.token, heartData }))
          }
          clearInterval(countdown)
          dispatch(ovActions.leaveSession())
          window.location.replace('/meeting?rematching=true')
        }
      }
    }, 1000)
    return () => clearInterval(countdown)
  }, [minutes, seconds, heart])
 
profile
새로운 것에 관심이 많고, 프로젝트 설계 및 최적화를 좋아합니다.

0개의 댓글