--- url: /ko/guide/getting-started/overview.md --- # 개요 ![react-native-youtube-bridge 데모](https://raw.githubusercontent.com/react-native-bridges/react-native-youtube-bridge/main/assets/example.gif) React Native에서 YouTube 플레이어를 붙이려면 iframe 설정, 이벤트 연결, 재생 제어, 플랫폼 차이를 한 번에 처리해야 하는 경우가 많습니다. `react-native-youtube-bridge`는 [YouTube IFrame Player API](https://developers.google.com/youtube/iframe_api_reference)를 React Native에 맞는 방식으로 감싼 라이브러리이며, 핵심은 세 가지입니다. - `useYouTubePlayer`로 플레이어 인스턴스를 만든다. - `YoutubeView`로 플레이어를 렌더링한다. - `useYouTubeEvent`로 상태, 진행률, 음소거, 에러를 구독한다. ## 왜 이 라이브러리를 쓰나 - 네이티브 YouTube 플레이어 모듈 없이 사용 가능 - iOS, Android, Web 지원 - 현대적인 React 코드에 잘 맞는 Hook 기반 API - 빠른 임베드부터 고급 외부 WebView 전략까지 확장 가능 ## 핵심 사용 모델 ```tsx import { YoutubeView, useYouTubePlayer } from 'react-native-youtube-bridge'; function App() { const player = useYouTubePlayer('AbZH7XWDW_k'); return ; } ``` 플레이어 인스턴스가 API의 중심입니다. - 생성 시 옵션을 설정하고 - `YoutubeView`에 전달해 렌더링하고 - 메서드로 제어하고 - `useYouTubeEvent`로 변화를 구독합니다. --- url: /ko/guide/getting-started/installation.md --- # 설치 먼저 메인 패키지를 설치합니다. ```sh [npm] npm install react-native-youtube-bridge ``` ```sh [yarn] yarn add react-native-youtube-bridge ``` ```sh [pnpm] pnpm add react-native-youtube-bridge ``` ```sh [bun] bun add react-native-youtube-bridge ``` ```sh [deno] deno add npm:react-native-youtube-bridge ``` ## peer dependency iOS와 Android에서는 `react-native-webview`가 필요합니다. ```sh [npm] npm install react-native-webview ``` ```sh [yarn] yarn add react-native-webview ``` ```sh [pnpm] pnpm add react-native-webview ``` ```sh [bun] bun add react-native-webview ``` ```sh [deno] deno add npm:react-native-webview ``` ## 최소 조건 | 패키지 | 버전 | | ---------------------- | ---------- | | `react` | `>=16.8.0` | | `react-native` | `>=0.60.0` | | `react-native-webview` | `>=11.0.0` | ## 설치 후 사용 가능한 것 - `useYouTubePlayer` - `useYouTubeEvent` - `YoutubeView` - 공개 타입들 - `useYoutubeOEmbed` 일반적인 사용만 한다면 `@react-native-youtube-bridge/web`는 바로 설치할 필요가 없습니다. --- url: /ko/guide/getting-started/quick-start.md --- # 빠른 시작 ## 예제 & 데모 - [🤖 Expo Snack](https://snack.expo.dev/@harang/react-native-youtube-bridge) - Expo Snack에서 바로 체험 가장 작은 예제는 아래와 같습니다. ```tsx import { YoutubeView, useYouTubePlayer } from 'react-native-youtube-bridge'; function App() { const player = useYouTubePlayer('AbZH7XWDW_k'); return ; } ``` ## source 입력 형태 ```tsx const playerA = useYouTubePlayer('AbZH7XWDW_k'); const playerB = useYouTubePlayer({ videoId: 'AbZH7XWDW_k' }); const playerC = useYouTubePlayer({ url: 'https://www.youtube.com/watch?v=AbZH7XWDW_k' }); ``` ## 초기 옵션 추가 ```tsx const player = useYouTubePlayer('AbZH7XWDW_k', { autoplay: true, controls: true, playsinline: true, rel: false, muted: true, }); ``` ## 다음 단계 - source 모델은 [기본 사용법](/ko/guide/usage/basic-usage.md)에서 확인하세요. - 이벤트 구독은 [이벤트 처리](/ko/guide/usage/handling-events.md)에서 확인하세요. - 재생 제어는 [플레이어 제어](/ko/guide/usage/player-controls.md)에서 확인하세요. --- url: /ko/guide/getting-started/ai.md --- # AI AI가 이 라이브러리의 기능, 버전별 문서, 프로젝트 규칙을 더 잘 이해해서 개발이나 트러블슈팅 과정에서 더 정확한 도움을 줄 수 있도록, 이 프로젝트는 다음 기능들을 제공합니다. ## llms.txt [`llms.txt`](https://llmstxt.org/)는 LLM이 프로젝트 문서를 더 쉽게 탐색하고 활용할 수 있도록 돕는 표준입니다. 이 사이트는 다음 파일들을 제공합니다. - [llms.txt](https://react-native-youtube-bridge-docs.pages.dev/ko/llms.txt): `2.x` 문서용 구조화된 인덱스 파일 ```txt https://react-native-youtube-bridge-docs.pages.dev/ko/llms.txt ``` - [llms-full.txt](https://react-native-youtube-bridge-docs.pages.dev/ko/llms-full.txt): `2.x` 문서 전체를 하나로 합친 파일 ```txt https://react-native-youtube-bridge-docs.pages.dev/ko/llms-full.txt ``` 사용 목적에 따라 적절한 파일을 선택하면 됩니다. - `llms.txt`는 더 작고 가벼워서 필요한 문서만 선택적으로 가져올 때 적합합니다. - `llms-full.txt`는 해당 버전 문서 전체를 한 번에 제공하므로, 넓은 범위의 이해나 큰 리팩터링 작업에 적합합니다. ## Markdown docs 모든 문서 페이지는 AI에게 직접 전달할 수 있는 Markdown 버전도 함께 제공합니다. 예시: ```txt https://react-native-youtube-bridge-docs.pages.dev/ko/guide/getting-started/overview.md https://react-native-youtube-bridge-docs.pages.dev/ko/guide/getting-started/quick-start.md https://react-native-youtube-bridge-docs.pages.dev/ko/guide/usage/player-controls.md ``` 특정 기능 하나만 물어볼 때는 전체 문서보다 관련 Markdown 페이지 하나를 제공하는 편이 더 효율적입니다. --- url: /ko/guide/usage/basic-usage.md --- # 기본 사용법 ## 플레이어 만들기 ```tsx import { YoutubeView, useYouTubePlayer } from 'react-native-youtube-bridge'; function App() { const player = useYouTubePlayer('AbZH7XWDW_k'); return ; } ``` ## source 입력 형태 ```tsx useYouTubePlayer('AbZH7XWDW_k'); useYouTubePlayer({ videoId: 'AbZH7XWDW_k' }); useYouTubePlayer({ url: 'https://www.youtube.com/watch?v=AbZH7XWDW_k' }); ``` source가 유효하지 않으면 에러 이벤트가 발생합니다. --- url: /ko/guide/usage/player-controls.md --- # 플레이어 제어 `useYouTubePlayer`가 반환하는 플레이어 객체에는 직접 호출할 수 있는 메서드, 비동기 getter, 동적 비디오 로드 메서드가 포함됩니다. > 비동기 getter 메서드는 플레이어가 준비된 뒤 사용하는 것을 권장합니다. `YoutubeView`가 내부 controller를 연결하기 전에는 getter가 `undefined`를 반환할 수 있으므로, 값에 의존해야 한다면 `ready` 이벤트 이후에 호출하세요. ## 재생 제어 ```tsx player.play(); player.pause(); player.stop(); player.seekTo(30, true); ``` ## 볼륨과 음소거 ```tsx player.setVolume(50); player.mute(); player.unMute(); const volume = await player.getVolume(); const muted = await player.isMuted(); ``` ## 상태와 비디오 정보 조회 ```tsx const [currentTime, duration, state, loadedFraction, url, embedCode] = await Promise.all([ player.getCurrentTime(), player.getDuration(), player.getPlayerState(), player.getVideoLoadedFraction(), player.getVideoUrl(), player.getVideoEmbedCode(), ]); ``` ## 재생 속도 ```tsx const currentRate = await player.getPlaybackRate(); const availableRates = await player.getAvailablePlaybackRates(); player.setPlaybackRate(1.5); ``` ## 다른 비디오 로드 또는 큐잉 ```tsx player.loadVideoById('M7lc1UVf-VE'); player.cueVideoById('M7lc1UVf-VE', 30); ``` - `loadVideoById`는 바로 로드를 시작합니다. - `cueVideoById`는 재생 없이 다음 비디오를 준비합니다. ## 크기 변경 ```tsx player.setSize(640, 360); ``` 초기 렌더 이후 imperative하게 크기를 바꿔야 할 때 유용합니다. --- url: /ko/guide/usage/handling-events.md --- # 이벤트 처리 `useYouTubeEvent`는 reactive state 구독과 callback 기반 side effect를 모두 지원합니다. ## 1. state 방식 ```tsx const playbackRate = useYouTubeEvent(player, 'playbackRateChange', 1); const isMuted = useYouTubeEvent(player, 'muteChange', false); const progress = useYouTubeEvent(player, 'progress', 1000); ``` ## 2. callback 방식 ```tsx useYouTubeEvent(player, 'ready', (playerInfo) => { console.log('ready', playerInfo); }); useYouTubeEvent(player, 'error', (error) => { console.error(error); }); useYouTubeEvent(player, 'autoplayBlocked', () => { console.log('autoplay blocked'); }); ``` ## callback dependency array callback가 바뀌는 값에 의존한다면 네 번째 인자로 dependency array를 전달하세요. ```tsx useYouTubeEvent( player, 'stateChange', (state) => { console.log('state', state, analyticsLabel); }, [analyticsLabel], ); ``` ## 이벤트 목록 | 이벤트 | payload | 설명 | | ----------------------- | ----------------- | -------------------------------------------------------------- | | `ready` | `PlayerInfo` | 첫 전체 플레이어 스냅샷 | | `stateChange` | `PlayerState` | `UNSTARTED`, `PLAYING`, `PAUSED`, `BUFFERING`, `ENDED`, `CUED` | | `error` | `YoutubeError` | YouTube 또는 bridge 레벨 에러 | | `progress` | `ProgressData` | `currentTime`, `duration`, `percentage`, `loadedFraction` | | `playbackRateChange` | `number` | 현재 재생 속도 | | `playbackQualityChange` | `PlaybackQuality` | 현재 화질 | | `autoplayBlocked` | `undefined` | 브라우저/플랫폼 autoplay 제한 | | `muteChange` | `boolean` | 현재 음소거 상태 | ## `ready` payload `ready`에서는 아래 같은 초기 정보를 받을 수 있습니다. - `availablePlaybackRates` - `availableQualityLevels` - `currentTime` - `duration` - `muted` - `playbackQuality` - `playbackRate` - `playerState` - `size` - `volume` ## `progress` payload ```ts { currentTime: number; duration: number; percentage: number; loadedFraction: number; } ``` ### progress interval 동작 - 세 번째 인자는 밀리초 단위 interval - 기본값은 `1000` - interval 기반 업데이트가 필요 없으면 `0` ```tsx const progress = useYouTubeEvent(player, 'progress', 500); ``` `seekTo()` 이후에도 progress가 한 번 더 빠르게 갱신되어 UI가 바로 따라오도록 설계되어 있습니다. ## mute tracking 주의점 `muteChange`를 구독할 때만 muted tracking이 활성화됩니다. --- url: /ko/guide/usage/player-config.md --- # 플레이어 설정 초기 옵션은 `useYouTubePlayer`의 두 번째 인자로 전달합니다. ```tsx const player = useYouTubePlayer('AbZH7XWDW_k', { autoplay: true, controls: true, playsinline: true, rel: false, muted: true, }); ``` ## 주요 옵션 - `autoplay` - `controls` - `loop` - `muted` - `startTime` - `endTime` - `playsinline` - `rel` - `origin` --- url: /ko/guide/usage/styling-and-layout.md --- # 스타일과 레이아웃 `YoutubeView`가 실제 렌더링 표면을 담당합니다. ```tsx ``` ## 주요 스타일 props ```tsx ``` - `iframeStyle`: Web 전용 - `webViewStyle`: iOS / Android 전용 - `webViewProps`: iOS / Android 전용 ## `webViewProps` 자세히 `webViewProps`는 bridge 기본 동작을 깨지 않으면서 네이티브 WebView를 튜닝할 때 유용합니다. ```tsx ``` 다만 bridge가 `ref`, `source.uri`, `style`, `onMessage`, `javaScriptEnabled`, `onError`는 직접 관리하므로 `webViewProps`는 부분 커스터마이징 레이어로 생각하는 게 좋습니다. --- url: /ko/guide/usage/inline-html-vs-webview.md --- # Inline HTML vs WebView iOS와 Android에서는 두 가지 렌더링 전략을 지원합니다. ## Inline HTML 모드 ```tsx ``` - 기본 모드 - 앱 내부에서 HTML을 직접 로드 - 대부분의 앱에서 가장 단순한 선택 ## 외부 WebView 모드 ```tsx ``` - 외부 플레이어 페이지를 로드 - inline HTML 제약이나 호스팅 요구사항이 있을 때 유용 - 기본 호스팅 페이지: `https://react-native-youtube-bridge.pages.dev` ## `webViewUrl` 의미 - `useInlineHtml: true`일 때는 HTML `baseUrl` - `useInlineHtml: false`일 때는 WebView `uri` override ## 정확한 origin 규칙 커스텀 origin을 쓰는 경우 문서 origin과 YouTube iframe `origin`을 정확히 맞춰야 합니다. inline HTML 모드에서는: - `webViewUrl`이 HTML `baseUrl`이 되고 - iframe `origin`은 그 페이지 origin과 정확히 일치해야 하며 - port가 있다면 포함해야 하고 - `baseUrl`은 trailing slash를 포함하고 - `origin`은 trailing slash 없이 써야 합니다. 예시: - base URL: `https://localhost:8081/` - origin: `https://localhost:8081` ## 언제 외부 WebView로 전환할까 다음과 같다면 외부 WebView 모드를 우선 고려하세요. - inline HTML에서 `embed not allowed`가 발생할 때 - 직접 호스팅하는 플레이어 페이지가 필요할 때 - 페이지 환경을 더 세밀하게 제어해야 할 때 --- url: /ko/guide/usage/custom-webview-player.md --- # 커스텀 WebView 플레이어 직접 호스팅하는 외부 플레이어 페이지가 필요할 때만 `@react-native-youtube-bridge/web`를 사용하면 됩니다. ## 전형적인 흐름 1. `@react-native-youtube-bridge/web`로 작은 웹 플레이어 페이지 작성 2. 해당 페이지를 배포 3. `YoutubeView`의 `webViewUrl`로 전달 ## 설치 ```bash npm install @react-native-youtube-bridge/web ``` ## 최소 예제 ```tsx import { YoutubePlayer } from '@react-native-youtube-bridge/web'; function CustomPlayerPage() { return ; } export default CustomPlayerPage; ``` ## 네이티브에서 사용 ```tsx ``` ## query-string 계약 네이티브 `YoutubeView`는 외부 플레이어 페이지를 로드할 때 URL query에 아래 값을 붙입니다. - `videoId` - `startTime` - `endTime` - `origin` - `autoplay` - `controls` - `loop` - `muted` - `playsinline` - `rel` 즉 커스텀 페이지는 다음 중 하나여야 합니다. - stock `@react-native-youtube-bridge/web` 플레이어를 그대로 사용하거나 - 직접 wrapper를 만들더라도 같은 query contract를 유지해야 합니다. ## 메시지 브리지 기대사항 React Native WebView 안에서 실행될 때는 플레이어 이벤트와 command 결과를 `window.ReactNativeWebView.postMessage(...)`로 다시 전달해야 합니다. stock `@react-native-youtube-bridge/web`를 쓰면 이 부분은 이미 처리되어 있습니다. --- url: /ko/guide/usage/metadata-with-oembed.md --- # oEmbed 메타데이터 재생 자체에는 필요 없지만, UI를 더 풍부하게 만들 때 유용합니다. `useYoutubeOEmbed`는 YouTube URL에 대한 메타데이터를 가져오며 아래 값을 반환합니다. - `oEmbed` - `isLoading` - `error` ```tsx const { oEmbed, isLoading, error } = useYoutubeOEmbed( 'https://www.youtube.com/watch?v=AbZH7XWDW_k', ); ``` ## 자주 쓰는 `oEmbed` 필드 - `title` - `thumbnail_url` - `author_name` - `author_url` - `provider_name` - `width` - `height` ## 활용 예시 - 플레이어 위에 비디오 제목 표시 - 썸네일/미리보기 카드 구성 - 더 풍부한 미디어 목록 UI 구성 --- url: /ko/guide/usage/errors-and-troubleshooting.md --- # 오류와 트러블슈팅 ## 잘못된 source 다음 형식 중 하나를 사용하세요. - `'AbZH7XWDW_k'` - `{ videoId: 'AbZH7XWDW_k' }` - `{ url: 'https://www.youtube.com/watch?v=AbZH7XWDW_k' }` ## 자주 보는 에러 코드 | 코드 | 의미 | | ------ | ----------------------- | | `2` | 잘못된 YouTube 파라미터 값 | | `5` | HTML5 플레이어 오류 | | `100` | 비디오를 찾을 수 없거나 비공개 | | `101` | embedded playback 불가 | | `150` | embedded playback 제한 | | `1000` | WebView 메시지 파싱 실패 | | `1001` | 네이티브 WebView 로딩 오류 | | `1002` | 잘못된 YouTube 비디오 ID | | `1003` | YouTube API 로딩 실패 | | `1004` | 알 수 없는 bridge/player 오류 | ## autoplay blocked 오디오가 켜져 있으면 환경에 따라 autoplay가 막힐 수 있습니다. autoplay가 중요하면 `muted`와 함께 테스트하고, 필요하면 `autoplayBlocked` 이벤트를 받아 UI에서 대응하세요. ## `embed not allowed` inline HTML 모드에서 YouTube iframe 제한이 걸리면: 1. `useInlineHtml={false}`로 전환 2. 기본 호스팅 페이지 또는 커스텀 페이지 사용 3. 대상 `origin`이 호스팅된 페이지 origin과 맞는지 확인 ## origin mismatch 커스텀 `webViewUrl`을 쓰는 경우, 페이지 origin과 iframe `origin`을 맞춰야 합니다. 페이지 자체가 열려도 origin mismatch로 iframe 동작이 깨질 수 있습니다. ## WebView 로딩 문제 네이티브 WebView가 로드되지 않는다면: - URL에 실제로 접근 가능한지 확인하고 - 호스팅한 페이지가 올바른 플레이어를 렌더링하는지 확인하고 - 전달한 source URL과 origin 설정이 맞는지 확인하고 - `webViewProps.source.headers`나 호스팅 규칙이 로드를 방해하지 않는지도 확인하세요. --- url: /ko/guide/usage/api-reference.md --- # API 레퍼런스 ## 주요 export ```ts export { useYouTubeEvent, useYouTubePlayer, YoutubeView, useYoutubeOEmbed, } from 'react-native-youtube-bridge'; ``` ## 핵심 API - `useYouTubePlayer(source, config?)` - `YoutubeView` - `useYouTubeEvent(player, event, ...)` - `useYoutubeOEmbed(url?)` ## 플레이어 메서드 - `play`, `pause`, `stop`, `seekTo` - `setVolume`, `getVolume`, `mute`, `unMute`, `isMuted` - `getCurrentTime`, `getDuration`, `getVideoUrl`, `getVideoEmbedCode` - `getPlaybackRate`, `setPlaybackRate`, `getAvailablePlaybackRates` - `getPlayerState`, `getVideoLoadedFraction` - `loadVideoById`, `cueVideoById`, `setSize` > 비동기 getter 메서드의 값을 안정적으로 사용해야 한다면 `ready` 이벤트 이후에 호출하세요. 렌더 표면이 아직 연결되기 전에는 `undefined`를 반환할 수 있습니다. ## 이벤트 - `ready` - `stateChange` - `error` - `progress` - `playbackRateChange` - `playbackQualityChange` - `autoplayBlocked` - `muteChange` ## 중요한 타입 - `YoutubeSource` - `YoutubePlayerVars` - `YoutubeError` - `ProgressData` - `PlayerInfo` - `PlayerState` - `YoutubeViewProps` ## `YoutubeView` props ### `player` `useYouTubePlayer`에서 반환된 `YoutubePlayer` 인스턴스입니다. 훅과 메서드 호출에서 사용하는 컨트롤러를 렌더 표면에 연결하려면 같은 인스턴스를 `YoutubeView`에 전달하세요. ```tsx const player = useYouTubePlayer('AbZH7XWDW_k'); return ; ``` ### `width` / `height` 플레이어의 렌더링 크기를 제어합니다. 두 prop 모두 숫자, `'auto'`, 또는 `'100%'` 같은 퍼센트 문자열을 받을 수 있습니다. ```tsx ``` ### `style` 플레이어 컨테이너에 React Native view 스타일을 적용합니다. ```tsx ``` ### `iframeStyle` (web only) React Native Web에서 iframe wrapper에 CSS 속성을 적용합니다. ### `useInlineHtml` (iOS / Android, 기본값: `true`) `true`이면 네이티브 WebView에 inline HTML을 전달합니다. `false`이면 WebView가 기본 호스팅 플레이어 페이지(`https://react-native-youtube-bridge.pages.dev`) 또는 `webViewUrl`로 전달한 URL을 로드합니다. ### `webViewUrl` (iOS / Android) WebView source URL을 재정의하거나, `useInlineHtml`이 `true`일 때 HTML 콘텐츠의 `baseUrl`로 사용됩니다. inline HTML을 사용할 때는 `webViewUrl`의 origin이 YouTube IFrame API `origin` 값과 정확히 일치해야 합니다. 필요한 경우 포트를 포함하고, `baseUrl`에는 trailing slash를 붙이고, `origin`에는 trailing slash를 붙이지 마세요. ### `webViewStyle` (iOS / Android) 내부 WebView에 직접 React Native view 스타일을 적용합니다. ### `webViewProps` (iOS / Android) 라이브러리가 내부적으로 제어하는 prop은 유지하면서 내부 WebView에 추가 prop을 전달합니다. `ref`, `source`, `style`, `onMessage`, `javaScriptEnabled`, `onError`는 내부에서 관리되므로 덮어쓸 수 없습니다. ## `YoutubeViewProps` type [Go to source](https://github.com/react-native-bridges/react-native-youtube-bridge/blob/main/packages/react-native-youtube-bridge/src/types/youtube.ts#L17) ````tsx title="YoutubeViewProps" /** * `YoutubeView` 컴포넌트의 props입니다. * @example * ```tsx * const player = useYouTubePlayer('AbZH7XWDW_k'); * * * ``` */ export type YoutubeViewProps = { /** * 플레이어 인스턴스입니다. * @example * ```tsx * const player = useYouTubePlayer('AbZH7XWDW_k'); * * * ``` */ player: YoutubePlayer; /** * 플레이어의 너비입니다. */ width?: number | 'auto' | `${number}%`; /** * 플레이어의 높이입니다. */ height?: number | 'auto' | `${number}%`; /** * 플레이어의 스타일입니다. */ style?: StyleProp; /** * iframe wrapper의 스타일입니다. * @platform web */ iframeStyle?: CSSProperties; /** * true로 설정하면 플레이어가 inline HTML을 사용합니다. * @remarks * false이면 플레이어가 기본 URI(https://react-native-youtube-bridge.pages.dev)의 webview를 사용합니다. * 커스텀 webview를 사용하려면 `webViewUrl`을 직접 설정하세요. * @defaultValue true * @platform ios, android */ useInlineHtml?: boolean; /** * WebView source로 사용할 URL입니다. * @remarks * `useInlineHtml`이 `true`이면 이 값은 HTML 콘텐츠의 `baseUrl`로 설정됩니다. * 이 경우 `webViewUrl`의 origin은 YouTube IFrame API `origin`과 정확히 일치해야 합니다. * - 필요한 경우 포트를 포함하세요. (예: baseUrl `https://localhost:8081/` ⇄ origin `https://localhost:8081`). * - `baseUrl`에는 trailing slash를 사용하되, `origin`에는 사용하지 마세요. (scheme + host [+ port] only). * * `useInlineHtml`이 `false`이면 이 값은 WebView source의 기본 URI(https://react-native-youtube-bridge.pages.dev)를 대체합니다. * @platform ios, android */ webViewUrl?: string; /** * WebView의 스타일입니다. * @platform ios, android */ webViewStyle?: StyleProp; /** * WebView에 전달할 props입니다. * @platform ios, android */ webViewProps?: Omit< WebViewProps, 'ref' | 'source' | 'style' | 'onMessage' | 'javaScriptEnabled' | 'onError' > & { source?: Omit; }; }; ```` --- url: /ko/guide/migration-from-1.x.md --- # 1.x에서 마이그레이션 이 문서는 `react-native-youtube-bridge` 1.x에서 2.x로 이동하는 방법을 설명합니다. 2.x API는 `expo-audio`, `expo-video` 같은 현대적인 Expo API처럼 Hook 중심으로 다시 설계되었습니다. ## 변경 사항 개요 | 항목 | 1.x | 2.x | | ------- | ---------------------------- | ---------------------------------- | | API 스타일 | imperative, ref 기반 | declarative, hook 기반 | | 렌더링 API | `YoutubePlayer` 컴포넌트 | `useYouTubePlayer` + `YoutubeView` | | 이벤트 처리 | callback props | `useYouTubeEvent` hook | | 상태 관리 | 직접 `useState` 관리 | reactive event subscription | | 플레이어 제어 | `playerRef.current.method()` | `player.method()` | | 초기 설정 | 컴포넌트 props / `playerVars` | hook config | ## 1. 컴포넌트 API 교체 ### 이전 방식: 1.x ```tsx import { YoutubePlayer } from 'react-native-youtube-bridge'; ; ``` ### 현재 방식: 2.x ```tsx import { YoutubeView, useYouTubePlayer } from 'react-native-youtube-bridge'; const player = useYouTubePlayer('AbZH7XWDW_k', { autoplay: true, controls: true, playsinline: true, rel: false, muted: true, }); ; ``` ## 2. 플레이어 설정을 `useYouTubePlayer`로 이동 1.x에서는 대부분의 플레이어 옵션을 컴포넌트의 `playerVars`로 전달했습니다. ```tsx ``` 2.x에서는 같은 옵션을 `useYouTubePlayer`의 두 번째 인자로 전달합니다. ```tsx const player = useYouTubePlayer('AbZH7XWDW_k', { autoplay: true, controls: true, muted: true, }); ; ``` `height`, `width`, `style`, `iframeStyle`, `webViewStyle`, `webViewProps`, `useInlineHtml`, `webViewUrl` 같은 렌더링 관련 prop은 `YoutubeView`에 남겨둡니다. ## 3. 이벤트를 `useYouTubeEvent`로 이동 `useYouTubeEvent`는 state-style 구독과 callback-style side effect를 모두 지원합니다. ### 이전 방식: 1.x callback props ```tsx 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); }, []); ; ``` ### 현재 방식: 2.x event hook ```tsx 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 ; ``` ## 4. ref 기반 제어를 직접 메서드 호출로 교체 ### 이전 방식: 1.x ref methods ```tsx const playerRef = useRef(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(); }; ; ``` ### 현재 방식: 2.x direct player methods ```tsx 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(); }; ; ``` > 비동기 getter 값을 안정적으로 사용해야 한다면 `ready` 이벤트 이후에 호출하세요. `YoutubeView`가 내부 controller를 연결하기 전에는 getter가 `undefined`를 반환할 수 있습니다. ## 5. source 처리 방식 업데이트 두 버전 모두 비디오 ID와 YouTube URL을 지원하지만, 2.x에서는 `source`를 `YoutubePlayer`가 아니라 `useYouTubePlayer`에 전달합니다. ```tsx 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 ```tsx ``` ### 현재 방식: 2.x ```tsx const player = useYouTubePlayer('AbZH7XWDW_k'); ; ``` ## 마이그레이션 체크리스트 ### 필수 변경 - [ ] `YoutubePlayer` import를 `YoutubeView`와 `useYouTubePlayer`로 교체 - [ ] `source`를 컴포넌트에서 `useYouTubePlayer(source)`로 이동 - [ ] `playerVars`를 `useYouTubePlayer(source, config)`의 두 번째 인자로 이동 - [ ] 이벤트 handler props를 `useYouTubeEvent` hook으로 교체 - [ ] 일반적인 재생 제어용 `useRef` 제거 - [ ] `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 요약 - `YoutubePlayer`가 `useYouTubePlayer` + `YoutubeView`로 대체되었습니다. - 이벤트 prop은 제거되고 `useYouTubeEvent`를 사용합니다. - ref 기반 제어는 직접 player method 호출로 바뀌었습니다. - `playerVars`는 컴포넌트 prop에서 hook config로 이동했습니다. - 직접 관리하던 상태는 reactive event 값으로 대체할 수 있습니다. 대부분의 앱은 화면 단위로 천천히 마이그레이션할 수 있습니다. 먼저 `useYouTubePlayer`로 player를 만들고 `YoutubeView`로 렌더링한 뒤, 이벤트와 ref 호출을 hook/direct method 방식으로 옮기면 됩니다. --- url: /ko/index.md --- # React Native Youtube Bridge React Native를 위한 쉬운 YouTube 재생 > iOS, Android, Web를 지원하는 Hook 기반 YouTube IFrame 플레이어 [빠른 시작](/ko/guide/getting-started/quick-start.html) | [GitHub](https://github.com/react-native-bridges/react-native-youtube-bridge) ## Features - 🌐 **크로스 플랫폼 플레이어**: iOS, Android, Web에서 동일한 플레이어 흐름을 사용할 수 있습니다. - 🪝 **Hook 기반 API**: useYouTubePlayer로 플레이어를 만들고 YoutubeView로 렌더링합니다. - 🧠 **타입 안전 이벤트**: ready, state, progress, mute, error 이벤트를 TypeScript와 함께 다룰 수 있습니다. - 🎥 **네이티브 YouTube 모듈 불필요**: 네이티브 YouTube 플레이어 모듈 대신 YouTube IFrame Player API를 사용합니다. - 🧩 **유연한 렌더링 모드**: 기본 inline HTML 또는 필요 시 외부 WebView 플레이어 페이지를 사용할 수 있습니다. - 🚀 **Expo 친화적**: Expo와 최신 React Native 프로젝트에서 쉽게 사용할 수 있습니다.