코드도보통지

6관문. Video/Canvas Control

관문 6 / 7

명령적 video API를 리액트 상태로 선언적으로 제어하라.

📖 이론 비급

명령적 API의 선언적 래핑

외부 라이브러리나 미디어 API는 play(), pause() 같은 명령형 메서드를 제공한다. 이를 리액트 상태와 동기화하려면 Effect로 감싸야 한다.

원칙: 리액트 상태가 진실의 원천이 되고, Effect가 그 상태를 외부 API에 반영하는 역할을 한다. 외부 API 이벤트(ended, error 등)는 setState로 다시 리액트 상태에 반영한다.

⚔️ 수련 코드

import { useState, useRef, useEffect } from 'react';

export default function VideoController() {
  const videoRef = useRef(null);
  const [isPlaying, setIsPlaying] = useState(false);
  const [volume, setVolume] = useState(1);

  useEffect(() => {
    const video = videoRef.current;
    if (!video) return;
    // TODO: isPlaying에 따라 play/pause 동기화
  }, [isPlaying]);

  useEffect(() => {
    if (videoRef.current) {
      // TODO: volume 상태를 video.volume에 동기화
    }
  }, [volume]);

  return (
    <div>
      <video ref={videoRef} src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4" loop style={{ width: 300 }} />
      <div>
        <button onClick={() => setIsPlaying(p => !p)}>{isPlaying ? '정지' : '재생'}</button>
        <input type="range" min={0} max={1} step={0.1} value={volume} onChange={e => setVolume(Number(e.target.value))} />
      </div>
    </div>
  );
}