삼분공부/Vue

[Nuxt] Nuxt3에서 Audio 중복 재생 문제 해결하기 & preload/load 이해하기

케이쓰리 2025. 4. 7. 10:10

Nuxt3 프로젝트를 진행하며 사용자 알림용 소리나 효과음을 넣을 일이 종종 생깁니다. new Audio('/alarm.mp3')처럼 간단히 구현할 수 있지만, 한 가지 문제가 있습니다:

✅ 버튼을 여러 번 누르면 이전 오디오가 겹쳐서 동시에 재생되는 현상!

이 글에서는 이 문제의 원인과 해결 방법, 그리고 오디오 관련 속성인 preload, load()의 개념까지 정리해보겠습니다.


📌 문제: 오디오가 겹쳐 재생된다?

다음과 같은 코드가 있다고 가정해봅시다:

const audio = new Audio('/alarm.mp3')
audio.play()
 

이 코드를 버튼 클릭 시마다 실행하면, 매번 새로운 Audio 인스턴스가 생성되어 각각 따로 재생됩니다. 그래서 버튼을 여러 번 누르면 소리가 겹쳐 들리게 됩니다.


✅ 해결 방법: 오디오 인스턴스를 재활용하자

 
<script setup lang="ts">
import { ref, onUnmounted } from 'vue'

const alarm = '/alarm.mp3'
const audioRef = ref<HTMLAudioElement | null>(null)

const playAlarm = () => {
  // 기존 오디오가 있다면 정지하고 처음으로 돌림
  if (audioRef.value) {
    audioRef.value.pause()
    audioRef.value.currentTime = 0
  }

  // 새 오디오 인스턴스 생성 및 재생
  const newAudio = new Audio(alarm)
  newAudio.play()
  audioRef.value = newAudio
}

// 컴포넌트 사라질 때 정리
onUnmounted(() => {
  if (audioRef.value) {
    audioRef.value.pause()
    audioRef.value = null
  }
})
</script>

<template>
  <button @click="playAlarm">🔔 알람 재생</button>
</template>
 

이렇게 하면 오디오는 매번 새로 생성되지만, 기존에 재생되던 소리를 먼저 멈추고 초기화하기 때문에 중첩되는 일이 없습니다.


🎛️ 추가 개념: preload 와 load()는 뭘까?

HTML5 <audio>나 new Audio()로 오디오를 다룰 때 사용할 수 있는 속성과 메서드입니다.

🔹 audio.preload = 'auto'

  • 브라우저에게 오디오를 미리 로딩하라고 힌트를 줍니다.
  • 'auto': 오디오 전체를 미리 받아올 수도 있음
  • 'metadata': 길이 같은 메타 정보만 미리 로딩
  • 'none': 아예 미리 로딩하지 않음 (필요할 때만 다운로드)

🔹 audio.load()

  • 오디오 파일을 명시적으로 다시 로드하게 합니다.
  • 소스를 바꿨거나, 강제로 다시 불러오고 싶을 때 사용합니다.

예시:

const audio = new Audio('/sound.mp3')
audio.preload = 'auto'
audio.load() // 브라우저가 지금 오디오를 다운로드하도록 시도함

단, preload와 load는 브라우저의 정책이나 사용자 상호작용 여부에 따라 무시될 수 있습니다. 특히 모바일에서는 더 엄격하니 테스트가 중요합니다.


✨ 마무리

Nuxt3에서 오디오를 다룰 때:

  • 중복 재생을 방지하려면 기존 오디오를 멈추고 새로 재생해야 합니다.
  • preload, load() 속성은 오디오의 미리 로딩 여부와 시점을 제어할 수 있습니다.