Vue.js에서 사라지는 HTML Video의 muted 속성

4,736 0

회사에 새로운 프로젝트가 생겼고, 제가 독립적으로 기술 스택을 선정하여 개발하게 되었습니다. 프로젝트 요구 사항은 영문 제품 소개 웹사이트를 제작하는 것이었으며, 프로젝트가 비교적 간단하고 기간도 길지 않은 점을 고려해 최종적으로 Nuxt 프레임워크를 사용하여 개발하기로 결정했습니다.

개발 과정은 대체로 순조로웠지만, 중간에 한 가지 버그를 만나 많은 시간을 들였습니다. 인터넷에서 오랫동안 찾아보았지만 관련 내용을 극히 일부만 검색할 수 있었고, 모두 Vue의 Github 저장소 issues에 있는 내용이었습니다. 결국에도 문제의 원인을 찾지 못했는데, 물론 이것이 버그가 아니라 프레임워크 자체가 원래 이렇게 설계된 것일 수도 있습니다.

다음은 제가 문제를 해결한 과정입니다. 여러분 중 다른 의견이 있다면 지적하고 함께 이야기해 주시면 감사하겠습니다.

문제 현상

제품 소개 웹사이트의 홈페이지에는 전체 화면을 차지하는 video 요소가 하나 있습니다. 동영상은 기본적으로 자동 재생되며, 대부분의 최신 브라우저 최신 버전에서 이 기능을 구현하려면 video 요소에 autoplay 속성을 추가하고, 기본적으로 음소거된 상태로 재생되도록 muted 속성도 설정해야 합니다.

처음 페이지를 로드했을 때는 정상적으로 자동 재생되며, 이때 DOM 구조는 Vue 템플릿에 작성한 코드와 동일한 것을 확인할 수 있습니다.

이때 라우트를 제품 페이지로 전환했다가 다시 홈페이지로 돌아오면 문제가 발생합니다. 원래 video 요소에 있던 muted가 알 수 없는 이유로 사라지고, 그에 따라 동영상 자동 재생도 작동하지 않게 됩니다.

문제 분석

처음에는 Nuxt 라우트 전환의 문제라고 생각했습니다. Nuxt에서 제공하는 navigateTo() 메서드와 Vue 라우터에서 제공하는 $router.push() 메서드를 사용해 테스트해 보았지만, 모두 동일한 문제가 발생했습니다.

HTML
<div class="flex items-center justify-center">
  <img
    class="logo h-9 w-72 cursor-pointer"
    src="/logo.png"
    @click="$router.push('/')"
  />
</div>

두 번째로 페이지에 keepalive: true를 설정하여 라우트 캐시를 구현해 보았지만, 여전히 문제가 해결되지 않았습니다. 게다가 이로 인해 다른 버그까지 발생했는데, 더 깊이 파고들지는 않았으므로 일단 여기서는 다루지 않겠습니다.

JavaScript
definePageMeta({
  layout: 'full-screen',
  keepalive: true,
})

세 번째로 video 요소에 v-bind를 사용하여 muted 속성을 동적으로 바인딩해 보았습니다. ref로 정의한 값을 사용하든, 직접 :muted="true"를 바인딩하든 모두 문제를 해결하지 못했습니다.

HTML
<video
  src="car.mp4"
  class="w-full h-full object-cover"
  autoplay
  loop
></video>

Nuxt의 문제인지 의심하기 시작했고, 네 번째로 순수 Vue 프로젝트를 사용하여 테스트해 보았습니다. 처음 로드할 때부터 muted 속성이 사라지는 결과가 나왔습니다. 그런데 이상하게도 동영상은 여전히 자동 재생이 가능했습니다. 이 이상한 문제는 점점 더 복잡하고 알 수 없게 변해 갔습니다.

결국 Vue의 Github 저장소에서 아직 해결되지 않은 issues 하나를 찾았고, 저와 같은 문제를 겪은 내용이었습니다.

이는 2022년 10월 12일에 등록된 issues이며, 지금까지도 닫히지 않은 상태입니다. 주목할 만한 점은 아래에 「Vue가 실제로 브라우저의 기본 기능을 망가뜨려서는 안 된다」라고 지적한 답변이 하나 있다는 것입니다. 하지만 어쩌면 이것은 정말 Vue.js의 버그일 수도 있습니다.

문제 해결

결국 문제의 원인을 더 이상 고민하지 않고 해결 방법을 준비하기 시작했습니다. 동적 속성 바인딩으로 문제를 해결할 수 없다면, 가장 원시적인 방법을 사용할 수밖에 없습니다. DOM을 조작하여 요소의 재생 이벤트를 직접 트리거하는 것입니다.

JavaScript
onMounted(() => {
  const videos = document.getElementsByTagName('video')
  Array.from(videos).forEach((video) => {
    video.play()
  })
})

Vue 마운트가 완료된 후 document.getElementsByTagName('video')를 통해 홈페이지의 모든 동영상 요소를 가져온 다음 차례대로 재생 이벤트를 트리거합니다. 이렇게 하면 라우트를 전환했다가 다시 홈페이지로 돌아왔을 때도 동영상이 계속 자동 재생 상태를 유지할 수 있습니다.

이 방법으로 문제를 간단히 해결할 수는 있지만, 이것이 최종적인 해결책은 아닌 것 같습니다. 문제의 핵심은 여전히 프레임워크에 있는 것으로 보입니다. 누군가 이 문제를 깊이 연구해 주시고, 저에게도 조언을 해주실 수 있기를 바랍니다.

댓글

(0)

아직 댓글이 없습니다

댓글 작성