Stimulus를 사용한 호버 시 비디오 미리보기

발행: (2026년 3월 13일 오전 02:15 GMT+9)
4 분 소요
원문: Dev.to

Source: Dev.to

프레젠테이션 인덱스

프레젠테이션을 녹화한 후에는 이를 탐색할 방법이 필요합니다. 간단한 인덱스 페이지가 모든 프레젠테이션을 비디오 썸네일과 함께 나열합니다. 썸네일 위에 마우스를 올리면 비디오가 미리보기를 재생합니다. 커서를 떼면 포스터 이미지로 돌아갑니다.

preview#play mouseleave->preview#pause"
  }
%>

Active Storage의 representable? 메서드는 미리보기를 생성할 수 있는지 확인하고 representation()은 썸네일을 자동으로 만들어 줍니다.

프리뷰 컨트롤러

모든 로직은 하나의 Stimulus 컨트롤러에서 이루어집니다:

import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static values = {
    segments: { type: Number, default: 3 },
    interval: { type: Number, default: 1000 },
    minDuration: { type: Number, default: 5 }
  }

  connect() {
    this.originalTime = 0
    this.wasPlaying = false
    this.previewTimer = null
    this.currentIndex = 0
    this.isReady = false
    this.timestamps = []

    this.element.addEventListener("loadedmetadata", () => {
      this.#calculateTimestamps()
      this.isReady = true
    })
  }
}

loadedmetadata 이해하기

loadedmetadata 이벤트가 핵심입니다. 브라우저가 비디오의 재생 시간, 차원 및 기타 메타데이터를 알 만큼 충분히 로드되면 이 이벤트가 발생합니다. 이 정보가 없으면 의미 있는 프리뷰 타임스탬프를 계산할 수 없습니다.

this.element.addEventListener("loadedmetadata", () => {
  this.#calculateTimestamps()
  this.isReady = true
})

loadedmetadata가 발생한 뒤에야 this.element.duration에 안정적으로 접근할 수 있습니다. 이 이벤트 이전에 접근하면 NaN이나 0이 반환됩니다.

스마트 타임스탬핑

시작부터 재생하는 대신, 컨트롤러는 비디오의 여러 부분을 보여줍니다:

#calculateTimestamps() {
  const duration = this.element.duration

  if (duration  1) {
    this.previewTimer = setInterval(() => {
      this.#showNextTimestamp()
    }, this.intervalValue)
  }
}

마우스를 올리면 현재 상태를 저장하고, 오디오를 음소거한 뒤 프리뷰 세그먼트를 순환시킵니다. 마우스를 뗐을 때는 모든 것을 원래대로 복원합니다.

자동 루프 프리뷰

프리뷰는 계산된 타임스탬프를 자동으로 순환합니다:

#showNextTimestamp() {
  this.element.currentTime = this.timestamps[this.currentIndex]
  this.element.play()

  this.currentIndex = (this.currentIndex + 1) % this.timestamps.length
}

모듈로 연산자 (%)가 루프를 만들어 줍니다: 마지막 세그먼트에 도달하면 다시 첫 번째 세그먼트로 돌아갑니다. setInterval과 결합하면 사용자가 비디오 내용을 실제로 체감할 수 있는 순환 프리뷰가 구현됩니다.

핵심은 올바른 시점(메타데이터가 로드될 때)까지 기다리고, 스마트 프리뷰 포인트를 계산한 뒤, 상호작용이 끝날 때 적절히 정리하는 것입니다. 이 작은 Stimulus 컨트롤러는 몇 줄의 JavaScript만으로도 세련된 UX를 제공할 수 있음을 보여줍니다. 🥳

0 조회
Back to Blog

관련 글

더 보기 »

JavaScript 소개

소개 오늘 수업에서 짧게 JavaScript에 대해 배웠으므로, 이 블로그에서 JavaScript에 관한 몇 가지 사실을 공유하려 합니다. JavaScript란? JavaScript…

Vite 8.0 출시

Vite 8.0 발표 기사 https://vite.dev/blog/announcing-vite8 Hacker News 토론 스레드 https://news.ycombinator.com/item?id=47360730 – 24점, 1개의 댓글...