회사에 새 프로젝트가 생겨 제가 독립적으로 기술을 선정하고 개발하게 되었습니다. 프로젝트 요구 사항은 영문 제품 소개 공식 웹사이트를 만드는 것이었고, 프로젝트가 비교적 간단하며 일정도 길지 않은 점을 고려해 최종적으로 Nuxt 프레임워크를 사용해 개발하기로 결정했습니다.
개발 과정은 순조로운 편이었지만, 중간에 한 가지 Bug를 만나 많은 시간을 들였습니다. 인터넷에서 오랫동안 찾아봤지만 관련 내용을 극히 일부만 검색할 수 있었고, 모두 Vue의 Github 저장소에 있는 issues였습니다. 결국에도 문제의 원인을 찾지 못했는데, 물론 이것이 Bug가 아니라 프레임워크 자체가 원래 이렇게 설계된 것일 수도 있습니다.
다음은 제가 문제를 해결한 방식입니다. 다른 의견이 있으시다면 지적해 주시고 함께 소통해 주시면 감사하겠습니다.
문제 현상
제품 소개 공식 웹사이트의 첫 화면에는 전체 화면을 차지하는 video 요소가 하나 있습니다. 동영상은 기본적으로 자동 재생되며, 대부분의 최신 브라우저 최신 버전에서 이 기능을 구현하려면 video 요소에 autoplay 속성을 추가하고, 기본 음소거 재생을 위해 muted 속성도 설정해야 합니다.

처음 페이지를 로드했을 때는 정상적으로 자동 재생되며, 이때 DOM 구조도 Vue 템플릿에 작성한 코드와 동일한 것을 볼 수 있습니다.
이때 라우트를 제품 페이지로 전환했다가 다시 첫 화면으로 돌아오면 문제가 발생합니다. 원래 video 요소에 있던 muted가 아무 이유 없이 사라지고, 이로 인해 동영상 자동 재생도 함께 작동하지 않게 됩니다.

문제 분석
처음에는 Nuxt 라우트 전환 문제라고 생각했습니다. Nuxt에서 제공하는 navigateTo() 메서드와 Vue 라우터에서 제공하는 $router.push() 메서드를 사용해 테스트했지만 모두 같은 문제가 발생했습니다.
<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를 설정해 라우트 캐시를 구현해 보았지만 여전히 문제가 해결되지 않았고, 이로 인해 다른 Bug까지 발생했습니다. 더 깊이 살펴보지는 않았으므로 일단 여기서는 언급하지 않겠습니다.
definePageMeta({
layout: 'full-screen',
keepalive: true,
})
세 번째로 video 요소에 v-bind를 사용해 muted 속성을 동적으로 바인딩해 보았습니다. ref로 정의한 값을 사용하든 직접 :muted="true"로 바인딩하든 모두 문제를 해결하지 못했습니다.
<video
src="car.mp4"
class="w-full h-full object-cover"
autoplay
loop
></video>
Nuxt의 문제인지 의심하기 시작했고, 그래서 네 번째로 순수 Vue 프로젝트를 사용해 테스트해 보았습니다. 처음 로드할 때부터 muted 속성이 사라지는 결과를 얻었지만, 이상하게도 동영상은 여전히 자동 재생이 가능했습니다. 이 이상한 문제는 점점 더 오리무중이 되어 갔습니다.

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

이 issues는 2022년 10월 12일에 생성되었으며, 지금까지도 닫히지 않았습니다. 언급할 만한 점은 아래에 「Vue가 실제로 네이티브 브라우저 기능을 망가뜨려서는 안 된다」는 내용의 답변이 하나 있었다는 것입니다. 하지만 이것이 실제로 Vue.js의 Bug일 가능성도 있습니다.
문제 해결
결국 문제의 원인을 더 이상 따지지 않고 해결 방안을 준비하기 시작했습니다. 동적으로 속성을 바인딩하는 방식으로 문제를 해결할 수 없다면, 가장 원시적인 방법을 사용할 수밖에 없습니다. DOM을 조작해 요소의 재생 이벤트를 직접 트리거하는 방식입니다.
onMounted(() => {
const videos = document.getElementsByTagName('video')
Array.from(videos).forEach((video) => {
video.play()
})
})
Vue 마운트가 완료된 후 document.getElementsByTagName('video')를 통해 첫 화면의 모든 동영상 요소를 가져오고, 차례로 재생 이벤트를 트리거합니다. 이렇게 하면 라우트를 전환했다가 다시 첫 화면으로 돌아와도 동영상이 계속 자동 재생되도록 할 수 있습니다.
이 방법으로 간단하게 문제를 해결할 수는 있지만, 이것이 최종적인 해결책은 아닌 것 같습니다. 문제의 핵심은 여전히 프레임워크에 있을 가능성이 크므로, 능력 있는 분께서 깊이 연구해 주시고 저에게도 조언해 주실 수 있기를 바랍니다.