본문 바로가기

Develop_story/trouble shooting

Audio custom hook - currentTime (조회수 관련)

SMALL

1. 문제점

  • 프로젝트에서 음악 재생 수 즉, 스트리밍 수에 따른 순위를 만들기 위해 음악이 재생되고 X초 후에 api를 요청하여 조회수를 1회 늘리는 방법을 구현해야 했다.
  • X초 후에 api를 요청하여 조회수를 1씩 늘리려고 하는 이유는 다른 사람들이 편법을 사용해 스트리밍 수를 조작할 수 있기 때문에, 이를 막기 위해 제한 사항을 만들었음

2. 시도한 방법

  • audio 태그를 사용했을 때, 분명히 현재 얼마나 재생됐는지, 혹은 재생하고 있는 시간이 몇 분, 몇 초인지 알 수 있는 event가 있을 것이라 생각했고, 대부분 current 관련된 이름으로 되어있을 것이라 생각해 audio current 관련된 것들을 모두 검색했고, currentTime이라는 event를 하나 알게 되었다.
  • 그리고 이를 가지고 어떻게 구현할지 미리 구상을 짜고, 코드를 작성했다.
  1. audio에 ref 지정
  2. 지정한 ref의 currentTime event를 가지고 currentTime이 3초일 때, console.log를 찍어보았다.
const audioRef = useRef<HTMLAudioElement>(null);

<div>
  <audio
    ref={audioRef}
    controls
    onTimeUpdate={handleTimeUpdate}
    src="01-Copland-Danzon_Cubano-Bernstein1963.mp3"
  ></audio>
</div>
  • currentTime의 이벤트는 onTimeUpdate에 들어있음으로 onTimeUpdate를 실행할 함수를 먼저 만들고, 그 안에 작성하였음
const handleTimeUpdate = () => {
  if (audioRef.current?.currentTime && audioRef.current.currentTime >= 3) {
    console.log("3초가 지났습니다.")
  }
};
  • 위와 같이 했을 때, 음악의 시간이 3초가 넘어가면 console이 찍혔다
  • 문제점
    • 3초가 지난 후에는 console이 재생하는 음악의 시간이 지날 때마다 console이 계속 찍히게 됨
    • 음악을 만약 4초에 시작하면 console이 바로 찍히게 됨
  • 위와 같은 문제점을 만났고, api가 계속 요청되면 결국 편법으로 조회수를 올리는 것이기 때문에, 위의 방법에서 조금 더 로직을 추가해야 했음

3. 시도한 방법

추가된 로직

  1. timer이라는 값을 하나 만들고, 이를 state로 지정하여 관리하기로 했음
  2. currentTime을 지정하고, 재생될 때마다 아까 console이 계속 찍혔으니, timer을 계속 증가시키고, timer가 지정된 숫자(초 단위는 아니었음)가 될 사 api 요청
const [timer, setTimer] = useState<number>

const handleTimeUpdate = () => {
  if (audioRef.current?.currentTime && audioRef.current.currentTime >= 3) {
    setTimer((prev) => prev + 1);
  }
};

if (timer === 10) {
  console.log("api 작동");
}
  • 위와 같이 작성했을 때, 일정 시간이 지난 후 “api 작동” 이라는 console이 찍혔음
  • 즉 console로 찍는 부분을 api가 작동하도록 만들게 되면 문제 없이 실행 될 것임

4. custom hook으로 만들기

  • Custom Hook 부분
import { useRef, useState } from "react";

export type UseAudioReturnType = [() => void, React.RefObject<HTMLAudioElement>];

function useAudio(): UseAudioReturnType {
  const audioRef = useRef<HTMLAudioElement>(null);
  const [timer, setTimer] = useState<number>(0);

  const handleTimeUpdate = () => {
    if (audioRef.current?.currentTime && audioRef.current.currentTime >= 3) {
      setTimer((prev) => prev + 1);
    }
  };

  if (timer === 10) {
    console.log("api 작동");
  }

  return [handleTimeUpdate, audioRef];
}

export default useAudio;
  • custom hook이 사용된 부분
import useAudio, { UseAudioReturnType } from "./hooks/useAudio";

function App() {
  const [handleTimeUpdate, audioRef] : UseAudioReturnType = useAudio()

  return (
    <>
      <div>
        <audio
          ref={audioRef}
          controls
          onTimeUpdate={handleTimeUpdate}
          src="01-Copland-Danzon_Cubano-Bernstein1963.mp3"
        ></audio>
      </div>
    </>
  );
}

export default App;

5. 알게 된 점

  • 정말 다양하고 많은 event들이 존재하는 것을 알았고, audio에서도 event를 사용할 수 있다는 것을 알게 되었음
  • 어떠한 특정 시간이 지난 후에 api를 실행하는 것은 개인적인 생각으로 setTimeout을 사용하면 될 것이라 생각하지만, audio가 재생된 후에 일정 시간이 지나면 api를 요청하는 것이 조금 어려울 것 같았다. 하지만 좋은 event를 많이 제공해 생각보다 쉽게 해결할 수 있었던 것 같다.
  • 이전까진 custom hook을 사용해야 하는데 하면서 어렵다고 생각해 계속 미루고 있었다. 하지만 위와 같은 코드가 프로젝트 상 많은 곳에서 사용되기 때문에 무조건 custom hook을 만들어야 했고, 이전에 공부했던 custom hook을 다시 기억해내 어렵지 않게 구현한 것 같다. 코드를 구현하고 로직을 짤 때 처음부터 너무 어려울 것이라 생각해 막연하게 겁을 먹어 시간을 보내는 것 보다는 그런 시간에 로직을 조금이라도 더 생각하고 코드를 한 줄이라도 더 작성하는 것이 도움이 될 것 같다.
LIST