Notice
Recent Posts
Recent Comments
Link
관리 메뉴

윤일무이

[이세계 MBTI 테스트] Audio 음악 객체 알아보기 본문

🛠️ 프로젝트/⭐️ 이세계 테스트

[이세계 MBTI 테스트] Audio 음악 객체 알아보기

썸머몽 2024. 3. 8. 16:23
728x90

들어가기

개발자지만 아이러니하게도 이세계 MBTI를 만들면서 개발만큼 신경썼던 부분이 디자인이었다.

몇 번 개발을 하면서 '내가 힘들게 만든 내 새끼... 다른 사람들도 봐주면 좋을텐데' 라는 생각이 많이 들었다.

MBTI 테스트를 2번이나 만든 이유도 MBTI 테스트 같은 스낵 컨텐츠는 비교적 유저 유입이 쉬울 것 같아서였다.

실제로 지인이 필요한 곰곰 다이어리(ㅠㅠ)는 참여율이 저조했으나 이세계 MBTI는 단시간 내 제법 높은 유입을 기록했다.

 

요는 사람들이 할만한 테스트를 만들고 싶었던 건데, box-shadow, text-shadow 등 몽환적인 톤앤매너를 가져가는 동시에 게임 사이트처럼 BGM을 넣고 싶었다. 우연히 어떤 게임 사이트를 들어갔는데 BGM이 잘 어울려서 이것저것 눌러봤던 개인적인 경험이 있었기 때문이다.

 

우리 이세계 MBTI 테스트도 진짜 이세계에 떨어진 것처럼 몰입하게 노래를 틀어보자!

 

원래는 레전드인 테일즈위버의 레미니센스를 넣고 싶었는데 저작권에 위배되는 듯 해 제외했다.

(유튜브에서 링크를 따오려 했으나 그런 식으로 동영상의 화면 없이 음악만 재생되는 경우도 저작권에 위배되는듯?)

혹시 몰라 무료 음원을 서치했고 마음에 드는 느낌의 mp3 파일을 다운 받았다.

 

Audio 태그

<audio>는 웹 페이지에서 오디오를 재생하는데 사용되는 요소로 MP3, WAV, OGG 등 다양한 오디오 포맷 파일을 웹에서 재생할 수 있다.

  • src 속성: 오디오 파일의 경로를 지정한다.
  • autoplay 속성: 자동 재생 여부를 설정한다.
  • loop 속성: 반복 재생 여부를 설정한다.
  • controls 속성: 컨트롤 패널 노출 여부를 설정한다.
  • muted 속성: 음소거 기능을 설정한다.

대부분의 브라우저에서는 유저의 어떤 액션이 없는 한 자동 음원 재생을 지원하지 않는다. 

오디오 객체를 로드하고 자동으로 play() 메서드를 설정해 음원을 재생하게 하면 브라우저 상에서 이를 차단해버린다.

const music = new Audio('music.mp3');
music.play();

 

이전에는 크롬 브라우저에서 JS를 이용해 음원을 자동으로 재생하는 게 가능했지만 보안의 위협이 될 수도 있다고 한다.

MDN에 의하면 아래의 조건 중 하나라도 해당되면 자동 재생이 가능하다.

  • 음소거이거나 오디오의 볼륨이 0일 경우
  • 유저가 사이트와 상호작용하는 경우 (클릭, 터치, 키 입력 등)
  • 화이트리스트에 등록된 사이트
  • 자동 재생 정책이 허용으로 지정돼 <iframe>와 document에서 자동 재생을 지원하는 경우

이 외의 경우에는 자동 재생이 차단된다. 더불어 자동 재생은 유저에게 불쾌한 경험(unpleasant)이 될 수도 있으므로 지양하는 것이 좋다.

 

이세계 MBIT에서는

<MusicPlayer onClick={handleMusicStart}>
	<Music src={getMusicIcon()} alt="음악 플레이어 아이콘" />
</MusicPlayer>

 

MusicPlayer 컴포넌트는 button으로 음악을 재생하고 멈출 수 있다.

Music 컴포넌트는 그 버튼 안에 들어가는 재생(음표) / 정지(뮤트) img다.

 

원하는 기능의 세부 사항은 다음과 같다.

1. 유저가 한 번 클릭하면 음악이 재생되고 한 번 더 클릭하면 음악이 정지된다. 다시 클릭하면 또 재생된다.

2. 음악의 볼륨이 줄어든 상태로 재생되는 게 아니라 노래를 아예 멈추고 싶다.

3. 다시 재생할 때 처음부터 재생되는 게 아니라 정지시킨 부분부터 재생하고 싶다.

4. 노래가 다 끝나면 다시 재생되게 하고 싶다.

 

먼저 재생 여부 상태를 관리할 state를 만들어준다.

다음 audio 객체를 생성한 뒤, 노래가 끝나도 다시 재생되게 loop 속성을 true로 설정한다.

 

이 때 useMemo로 값을 메모이제이션 하지 않으면 2가지 문제가 생긴다.

 

1. Audio 객체가 매 렌더링마다 생성되어 불필요한 리소스가 소모된다. 

2. 클릭(재생) -> 클릭(정지) -> 클릭(재생) 이 되지 않고 모두 재생이 되어 버린다. 

 

따라서 audio 객체로 만든 audio는 loop 속성이 true이며,

첫 렌더링 시에만 객체가 생성되고 이후에는 메모이제이션된 값이 재사용된다.

const [isPlaying, setIsPlaying] = useState(false);

  const music = useMemo(() => {
    const audio = new Audio('/music/ost.mp3');
    audio.loop = true;
    return audio;
  }, []);

  const handleMusicStart = () => {
    if (!isPlaying) {
      music.play();
      setIsPlaying(true);
    } else {
      music.pause();
      setIsPlaying(false);
    }
  };

버튼을 클릭할 때마다 handleMusicStart가 실행되는데 만약 재생하고 있다면 일시 정지와 더불어 정지 상태로,

재생하지 않고 있다면 재생과 더불어 재생 상태로 불리언 값을 바꿔준다.

 

  useEffect(() => {
    const handleEnded = () => {
      setIsPlaying(false);
    };
    music.addEventListener('ended', handleEnded);

    return () => {
      music.removeEventListener('ended', handleEnded);
    };
  }, [music]);

music값이 바뀔 때마다 실행되는 useEffect 훅을 만들었다.

'ended'는 audio 태그에서 음악이 종료될 때 발생하는 이벤트다.

즉 노래가 끝나면 정지 상태로 바꾸고 클린업 함수를 통해 ended 이벤트 리스너를 제거한다.

 

  const getMusicIcon = () => {
    return isPlaying ? '/img/icon/music.png' : '/img/icon/mute.png';
  };

버튼 안의 이미지는 재생 상태에 따라 바뀐다.

재생하고 있으면 음표 아이콘을, 정지했으면 뮤트 아이콘을 띄워줬다.

 

 

브라우저에서 자동 재생이 지원되지 않은 이유, audio 객체에 대해 조금 더 자세히 알게 되었다. 👍🏻

 


 

**참고

 

🔊 웹에서 음악 객체(Audio) 다루기

HTML Audio 태그 HTML 태그는 웹 페이지에서 오디오를 재생하기 위해 사용되는 요소이다. MP3, WAV, OGG 등 다양한 오디오 포맷 파일을 웹에서 재생할 수 있다. audio 태그 속성 속성 값 설정 내용 src 파일

inpa.tistory.com

 

미디어 및 Web Audio API 자동 재생 가이드 - 웹 미디어 기술 | MDN

페이지가 로드 되자마자 소리(또는 소리가 나는 영상)를 자동으로 재생하는 것은 사용자에게 별로 유쾌한 경험은 아닐겁니다. 미디어 자동 재생이 유용하려면 꼭 필요한 경우에 한하여 조심스

developer.mozilla.org

 

HTMLAudioElement: Audio() constructor - Web APIs | MDN

The Audio() constructor creates and returns a new HTMLAudioElement which can be either attached to a document for the user to interact with and/or listen to, or can be used offscreen to manage and play audio.

developer.mozilla.org

 

728x90