뷰포트 기반 비디오 자동 재생/일시 정지 구현
이 기능은 Stimulus 컨트롤러와 JavaScript의 Intersection Observer API를 활용하여 비디오의 뷰포트 가시성을 동적으로 감지하고 재생 상태를 제어합니다.
1. HTML 구조 설정
비디오 요소에 data-controller="video"
와 data-video-percentage-visible-value
속성을 추가하여 Stimulus 컨트롤러를 연결하고, 비디오가 ‘보이는’ 것으로 간주될 최소 가시성 비율(예: 50%)을 정의합니다.
```html
```
2. Stimulus 컨트롤러 정의
bin/rails generate Stimulus video
명령으로 컨트롤러를 생성한 후, 두 가지 static values
를 정의합니다.
* playing
: 비디오가 뷰포트를 벗어날 때 재생 중이었는지 여부를 추적합니다 (Boolean, 기본값 false
).
* percentageVisible
: 비디오가 ‘보이는’ 것으로 간주될 최소 가시성 비율입니다 (Number, 기본값 20
).
3. 연결 및 해제 로직
connect()
: 컨트롤러 연결 시#detectViewport()
메서드를 호출하여 뷰포트 감지를 시작합니다.disconnect()
: 컨트롤러 해제 시this.observer?.disconnect()
를 통해 Intersection Observer를 정리하여 메모리 누수를 방지합니다. 옵셔널 체이닝을 사용하여 옵저버가 존재하지 않을 경우의 오류를 방지합니다.
4. 뷰포트 감지 (#detectViewport
)
IntersectionObserver
인스턴스를 생성하여 비디오 요소의 가시성 변화를 감지합니다.
* 콜백 함수로 #adjustPlayback(entry)
를 지정하여 가시성 변화 시 재생 상태를 조정합니다.
* threshold
옵션은 #thresholdValue
게터를 통해 설정됩니다. 이 게터는 percentageVisibleValue
를 100으로 나누어 Intersection Observer API가 요구하는 0과 1 사이의 소수점 값으로 변환합니다.
5. 재생 상태 조정 (#adjustPlayback
)
IntersectionObserver
콜백에 의해 호출됩니다.
* entry.isIntersecting
속성을 통해 비디오가 뷰포트 내에 있는지 확인합니다.
* 뷰포트 이탈 시: #pauseWhenOutOfView()
를 호출하여 비디오를 일시 정지하고, playingValue
를 true
로 설정하여 이전에 재생 중이었음을 기록합니다.
* 뷰포트 진입 시: #resumeIfPreviouslyPlaying()
를 호출하여 이전에 재생 중이었다면 비디오 재생을 다시 시도합니다.
6. 비디오 재생 시도 (#attemptToPlay
)
HTML5 비디오 API의 play()
메서드는 Promise
를 반환합니다.
* #attemptToPlay()
는 this.element.play() || Promise.reject()
를 사용하여 항상 Promise
를 반환하도록 합니다. 이는 브라우저의 자동 재생 정책으로 인해 play()
가 실패할 경우를 대비하고, 구형 브라우저에서 Promise
를 반환하지 않을 수 있는 상황에 대응합니다.
* 재생 실패 시(Promise reject
), 호출부의 .catch()
핸들러에서 playingValue
를 false
로 설정하여 불필요한 자동 재생 시도를 방지합니다.
이 컨트롤러는 프라이빗 메서드, 배열 비구조화, 옵셔널 체이닝 등 최신 JavaScript 기능을 활용하여 깔끔하고 유지보수 가능한 코드를 제공합니다.