우리가 웹 서핑을 하다 보면 수많은 동영상 콘텐츠를 마주하게 됩니다. 하지만 브라우저가 기본적으로 제공하는 비디오 컨트롤러는 기능적으로는 충실할지 모르나, 디자인 측면에서는 항상 아쉬움이 남습니다. 구글 크롬, 사파리, 엣지 등 브라우저마다 제각각인 인터페이스는 블로그나 웹사이트의 전체적인 톤앤매너를 해치기도 하죠.

오늘 19번째 프로젝트에서는 HTML5의 Video API를 직접 제어하여, 투박한 기본 컨트롤을 숨기고 우리만의 디자인과 기능을 입힌 ‘자바스크립트 커스텀 비디오 플레이어’를 제작해 보려 합니다. 단순히 재생과 일시정지를 넘어 볼륨 조절, 배속 설정, 그리고 실시간 진행바(Progress Bar)까지 구현해 보며 브라우저의 멀티미디어 제어 능력을 한 단계 업그레이드해 보겠습니다.
1. 프로젝트 설계: 비디오 객체
자바스크립트 커스텀 비디오 플레이어 제작의 핵심은 브라우저의 비디오 객체가 보내주는 신호를 자바스크립트가 실시간으로 수신하고 처리하는 것입니다. 비디오가 재생 중인지, 현재 몇 초를 지나고 있는지, 전체 길이는 얼마인지 등의 데이터를 정확히 받아와서 우리가 만든 UI에 투영해야 합니다.
가장 먼저 선행되어야 할 작업은 기본 컨트롤러를 제거하는 것입니다. HTML의 <video> 태그에서 controls 속성을 제외하는 것부터 시작합니다. 그 대신 우리가 만든 별도의 div 요소들을 컨트롤러로 활용하게 됩니다.
[재생 상태 토글 로직]
가장 기본이 되면서도 중요한 부분입니다. 비디오의 상태를 확인하여 재생과 일시정지를 전환합니다.
// 비디오 객체와 버튼 요소를 가져옵니다.
const video = document.getElementById('myVideo');
const playBtn = document.getElementById('playBtn');
function togglePlay() {
// video.paused 속성은 비디오가 멈춰있는지 여부를 불리언 값으로 반환합니다.
if (video.paused) {
video.play(); // 재생 시작
playBtn.innerText = '⏸'; // 아이콘을 일시정지로 변경
} else {
video.pause(); // 일시정지
playBtn.innerText = '▶'; // 아이콘을 재생으로 변경
}
}
// 비디오 화면 자체를 클릭해도 재생/정지가 되도록 이벤트를 연결합니다.
video.addEventListener('click', togglePlay);
playBtn.addEventListener('click', togglePlay);
슬라이더와 버튼 등 다양한 DOM 요소를 제어하는 기초는 [자바스크립트 캔버스 그림판] 프로젝트의 도구 모음 구현법과 연결됩니다.
2. 실시간 데이터 처리: 진행바와 시간 표시
비디오 플레이어에서 사용자가 가장 많이 상호작용하는 부분은 아마도 ‘진행바’일 것입니다. 비디오가 흐름에 따라 붉은 선이 차오르고, 마우스로 클릭한 지점으로 영상이 즉시 이동하는 기능은 정밀한 수학적 계산이 필요합니다.
우리는 비디오 객체가 제공하는 timeupdate 이벤트를 활용할 것입니다. 이 이벤트는 비디오가 재생되는 동안 매우 짧은 간격으로 계속해서 발생합니다. 이때 현재 재생 시간(currentTime)을 전체 시간(duration)으로 나누어 퍼센트 값을 구하고, 이를 CSS의 width 속성에 대입하면 실시간으로 차오르는 진행바를 완성할 수 있습니다.
[진행률 계산 및 시간 포맷팅]
초 단위의 데이터를 우리가 익숙한 ’00:00′ 형태로 변환하고 게이지를 업데이트하는 로직입니다.
video.addEventListener('timeupdate', () => {
// 1. 진행률 계산 (현재시간 / 전체시간 * 100)
const progressPercent = (video.currentTime / video.duration) * 100;
progressBar.style.width = `${progressPercent}%`;
// 2. 시간 텍스트 업데이트
// 분과 초를 계산하여 2자리 숫자로 포맷팅합니다.
const minutes = Math.floor(video.currentTime / 60);
const seconds = Math.floor(video.currentTime % 60);
const format = `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
timeDisplay.innerText = format;
});
진행바의 너비()는 비디오의 전체 재생 시간() 대비 현재 재생 시점()의 비율을 계산하여 산출합니다.
3. 자바스크립트 커스텀 비디오 플레이어 영상

4. 문제 과정: 정밀한 탐색(Scrubbing)
단순히 보기만 하는 플레이어가 아니라, 사용자가 특정 지점을 클릭했을 때 해당 장면으로 즉시 이동하는 ‘탐색’ 기능 구현은 예상보다 까다로운 작업이었습니다. 클릭한 지점의 좌표(offsetX)를 전체 진행바의 너비로 나누어 비율을 구한 뒤, 그 비율을 다시 비디오의 전체 길이에 곱해주는 과정이 필요합니다.
이때 발생할 수 있는 문제는 비디오가 아직 로드되지 않았을 때 duration 값이 NaN을 반환하는 경우입니다. 이를 방지하기 위해 loadedmetadata이벤트를 사용하여 비디오 정보가 완전히 로드된 시점부터 기능을 활성화하는 세심한 처리를 더해 자바스크립트 커스텀 비디오 플레이어를 제작 하였습니다.
5. 사용자 경험을 위한 추가 기능: 배속과 볼륨
최근 유튜브나 넷플릭스 같은 플랫폼에서 빠질 수 없는 기능이 바로 ‘배속 조절’입니다. 바쁜 현대인들에게 1.5배속이나 2.0배속 시청은 필수적인 요소가 되었죠. 자바스크립트의 playbackRate 속성을 이용하면 단 한 줄의 코드로 이 강력한 기능을 구현할 수 있습니다.
또한, 슬라이더(input type=”range”)를 활용해 볼륨 조절 기능을 추가했습니다. 볼륨의 값은 0부터 1 사이의 소수점으로 표현되는데, 이를 슬라이더의 값과 연동하여 사용자가 직관적으로 소리 크기를 조절할 수 있도록 설계했습니다.
전체 화면 표시하기, 공유하기, 자막 보이기 등 다양한 기능들을 추가하면 더 편리하고 완벽한 비디오 플레이어가 될 것입니다.
19번째 프로젝트인 ‘자바스크립트 커스텀 비디오 플레이어’ 제작을 통해, 정적인 텍스트나 이미지를 넘어 동적인 미디어 데이터를 다루는 법을 배울 수 있었습니다. 16번 프로젝트인 아날로그 시계 만들기에서 시간 데이터를 다뤄 보았고, 17번 프로젝트인 텍스트 분석기에서 수치를 계산에 대한 내용을 다뤄 보았습니다. 그리고 이번에는 비디오 데이터를 다루는 방법에 대해서 포스팅을 진행해 보았습니다.
브라우저 기본 플레이어의 투박한 디자인에서 벗어나, CSS로 모든 인터페이스를 직접 디자인하고 Video API로 제어 로직을 연결했습니다. 특히 재생 바(Progress Bar)를 클릭했을 때 해당 시점으로 영상이 이동하도록 currentTime을 계산하는 부분과 볼륨 조절 슬라이더 구현이 흥미로웠습니다. 웹 표준 API를 깊게 파고들 수 있었던 프로젝트 중 하나였습니다.
우리가 만든 이 플레이어는 이제 단순한 기능 모음이 아닙니다. 색상을 바꾸고, 아이콘을 커스텀하고, 독특한 애니메이션을 추가하는 순간 세상에 단 하나뿐인 저만의 플레이어가 됩니다. 코딩은 결국 정해진 답을 찾는 과정이 아니라, 자신의 색깔로 문제를 해결해 나가는 창의적인 여정임을 다시 한번 느낍니다.
다음 20번째 프로젝트에서는 더욱 놀랍고 실용적인 주제로 찾아뵙겠습니다.