• 한국어
  • 2.x
  • 1.x에서 마이그레이션

    이 문서는 react-native-youtube-bridge 1.x에서 2.x로 이동하는 방법을 설명합니다.

    2.x API는 expo-audio, expo-video 같은 현대적인 Expo API처럼 Hook 중심으로 다시 설계되었습니다.

    변경 사항 개요

    항목1.x2.x
    API 스타일imperative, ref 기반declarative, hook 기반
    렌더링 APIYoutubePlayer 컴포넌트useYouTubePlayer + YoutubeView
    이벤트 처리callback propsuseYouTubeEvent hook
    상태 관리직접 useState 관리reactive event subscription
    플레이어 제어playerRef.current.method()player.method()
    초기 설정컴포넌트 props / playerVarshook config

    1. 컴포넌트 API 교체

    이전 방식: 1.x

    import { YoutubePlayer } from 'react-native-youtube-bridge';
    
    <YoutubePlayer
      ref={playerRef}
      source="AbZH7XWDW_k"
      height={400}
      playerVars={{
        autoplay: true,
        controls: true,
        playsinline: true,
        rel: false,
        muted: true,
      }}
      onReady={handleReady}
      onStateChange={handleStateChange}
      onProgress={handleProgress}
      onError={handleError}
    />;

    현재 방식: 2.x

    import { YoutubeView, useYouTubePlayer } from 'react-native-youtube-bridge';
    
    const player = useYouTubePlayer('AbZH7XWDW_k', {
      autoplay: true,
      controls: true,
      playsinline: true,
      rel: false,
      muted: true,
    });
    
    <YoutubeView player={player} height={400} />;

    2. 플레이어 설정을 useYouTubePlayer로 이동

    1.x에서는 대부분의 플레이어 옵션을 컴포넌트의 playerVars로 전달했습니다.

    <YoutubePlayer
      source="AbZH7XWDW_k"
      playerVars={{
        autoplay: true,
        controls: true,
        muted: true,
      }}
    />

    2.x에서는 같은 옵션을 useYouTubePlayer의 두 번째 인자로 전달합니다.

    const player = useYouTubePlayer('AbZH7XWDW_k', {
      autoplay: true,
      controls: true,
      muted: true,
    });
    
    <YoutubeView player={player} />;

    height, width, style, iframeStyle, webViewStyle, webViewProps, useInlineHtml, webViewUrl 같은 렌더링 관련 prop은 YoutubeView에 남겨둡니다.

    3. 이벤트를 useYouTubeEvent로 이동

    useYouTubeEvent는 state-style 구독과 callback-style side effect를 모두 지원합니다.

    이전 방식: 1.x callback props

    const [isPlaying, setIsPlaying] = useState(false);
    const [currentTime, setCurrentTime] = useState(0);
    const [duration, setDuration] = useState(0);
    const [playbackRate, setPlaybackRate] = useState(1);
    const [availableRates, setAvailableRates] = useState([1]);
    
    const handleReady = useCallback((playerInfo) => {
      if (playerInfo?.availablePlaybackRates) {
        setAvailableRates(playerInfo.availablePlaybackRates);
      }
    }, []);
    
    const handleStateChange = useCallback((state) => {
      setIsPlaying(state === PlayerState.PLAYING);
    }, []);
    
    const handleProgress = useCallback((progress) => {
      setCurrentTime(progress.currentTime);
      setDuration(progress.duration);
    }, []);
    
    <YoutubePlayer
      source="AbZH7XWDW_k"
      onReady={handleReady}
      onStateChange={handleStateChange}
      onProgress={handleProgress}
    />;

    현재 방식: 2.x event hook

    const player = useYouTubePlayer('AbZH7XWDW_k');
    
    // State-style 구독
    const playbackRate = useYouTubeEvent(player, 'playbackRateChange', 1);
    const progress = useYouTubeEvent(player, 'progress', 1000);
    const state = useYouTubeEvent(player, 'stateChange');
    
    const currentTime = progress?.currentTime ?? 0;
    const duration = progress?.duration ?? 0;
    const isPlaying = state === PlayerState.PLAYING;
    
    // Callback-style side effect
    const [availableRates, setAvailableRates] = useState([1]);
    
    useYouTubeEvent(player, 'ready', (playerInfo) => {
      if (playerInfo.availablePlaybackRates) {
        setAvailableRates(playerInfo.availablePlaybackRates);
      }
    });
    
    useYouTubeEvent(player, 'autoplayBlocked', () => {
      console.log('Autoplay was blocked');
    });
    
    useYouTubeEvent(player, 'error', (error) => {
      console.error('Player error:', error);
    });
    
    return <YoutubeView player={player} />;

    4. ref 기반 제어를 직접 메서드 호출로 교체

    이전 방식: 1.x ref methods

    const playerRef = useRef<PlayerControls>(null);
    
    const play = () => playerRef.current?.play();
    const pause = () => playerRef.current?.pause();
    const stop = () => playerRef.current?.stop();
    const seekTo = (time: number) => playerRef.current?.seekTo(time, true);
    const setVolume = (volume: number) => playerRef.current?.setVolume(volume);
    const mute = () => playerRef.current?.mute();
    const unMute = () => playerRef.current?.unMute();
    
    const getPlayerInfo = async () => {
      const currentTime = await playerRef.current?.getCurrentTime();
      const duration = await playerRef.current?.getDuration();
      const state = await playerRef.current?.getPlayerState();
    };
    
    <YoutubePlayer ref={playerRef} source="AbZH7XWDW_k" />;

    현재 방식: 2.x direct player methods

    const player = useYouTubePlayer('AbZH7XWDW_k');
    
    const play = () => player.play();
    const pause = () => player.pause();
    const stop = () => player.stop();
    const seekTo = (time: number) => player.seekTo(time, true);
    const setVolume = (volume: number) => player.setVolume(volume);
    const mute = () => player.mute();
    const unMute = () => player.unMute();
    
    const getPlayerInfo = async () => {
      const currentTime = await player.getCurrentTime();
      const duration = await player.getDuration();
      const state = await player.getPlayerState();
    };
    
    <YoutubeView player={player} />;

    비동기 getter 값을 안정적으로 사용해야 한다면 ready 이벤트 이후에 호출하세요. YoutubeView가 내부 controller를 연결하기 전에는 getter가 undefined를 반환할 수 있습니다.

    5. source 처리 방식 업데이트

    두 버전 모두 비디오 ID와 YouTube URL을 지원하지만, 2.x에서는 sourceYoutubePlayer가 아니라 useYouTubePlayer에 전달합니다.

    const playerA = useYouTubePlayer('AbZH7XWDW_k');
    const playerB = useYouTubePlayer({ videoId: 'AbZH7XWDW_k' });
    const playerC = useYouTubePlayer({ url: 'https://youtube.com/watch?v=AbZH7XWDW_k' });

    6. 렌더링 모드 마이그레이션

    렌더링 모드 관련 prop은 렌더 표면에 속하므로 YoutubeView로 이동합니다.

    이전 방식: 1.x

    <YoutubePlayer
      source="AbZH7XWDW_k"
      useInlineHtml={false}
      webViewUrl="https://your-custom-player.com"
    />

    현재 방식: 2.x

    const player = useYouTubePlayer('AbZH7XWDW_k');
    
    <YoutubeView player={player} useInlineHtml={false} webViewUrl="https://your-custom-player.com" />;

    마이그레이션 체크리스트

    필수 변경

    • YoutubePlayer import를 YoutubeViewuseYouTubePlayer로 교체
    • source를 컴포넌트에서 useYouTubePlayer(source)로 이동
    • playerVarsuseYouTubePlayer(source, config)의 두 번째 인자로 이동
    • 이벤트 handler props를 useYouTubeEvent hook으로 교체
    • 일반적인 재생 제어용 useRef<PlayerControls> 제거
    • playerRef.current?.method()player.method()로 교체
    • height, width, 스타일, WebView 옵션 같은 렌더링 prop은 YoutubeView에 유지

    선택 개선

    • 수동 useState 미러링을 state-style useYouTubeEvent 구독으로 단순화
    • useYouTubeEvent(player, 'error', ...)로 에러 처리 추가
    • muted 상태 UI가 필요하면 muteChange 사용
    • 1.x prop 안정성을 위해서만 쓰던 불필요한 callback memoization 제거

    Breaking changes 요약

    • YoutubePlayeruseYouTubePlayer + YoutubeView로 대체되었습니다.
    • 이벤트 prop은 제거되고 useYouTubeEvent를 사용합니다.
    • ref 기반 제어는 직접 player method 호출로 바뀌었습니다.
    • playerVars는 컴포넌트 prop에서 hook config로 이동했습니다.
    • 직접 관리하던 상태는 reactive event 값으로 대체할 수 있습니다.

    대부분의 앱은 화면 단위로 천천히 마이그레이션할 수 있습니다. 먼저 useYouTubePlayer로 player를 만들고 YoutubeView로 렌더링한 뒤, 이벤트와 ref 호출을 hook/direct method 방식으로 옮기면 됩니다.