@teamsparta/sparta-player
v1.1.0
Published
A Simple React Component for video.js with TypeScript support
Readme
Sparta Player
video.js 기반의 간편한 React 비디오 플레이어 컴포넌트입니다.
📑 목차
📖 소개
Sparta Player는 video.js를 React에서 손쉽게 사용할 수 있도록 만든 컴포넌트 라이브러리입니다. 복잡한 UI 설정 없이도 강력한 비디오 플레이어 기능을 바로 사용할 수 있습니다.
주요 기능
- ✅ HLS 스트리밍 지원 -
application/x-mpegURL타입 지원 - ✅ TypeScript 지원 - 완벽한 타입 정의 제공
- ✅ 사용자 정의 UI - 세련된 커스텀 컨트롤러
- ✅ 자막(VTT) 지원 - WebVTT 형식의 자막 파일 지원
- ✅ 단축키 지원 - 키보드로 플레이어 제어
- ✅ 재생 속도 조절 - 0.5x ~ 2.0x 배속 재생
- ✅ 화질 선택 - 360p ~ 1080p, 자동 화질 선택
- ✅ 볼륨 및 음소거 - 볼륨 조절 및 음소거 기능
- ✅ 전체화면 모드 - 전체화면 재생 지원
- ✅ 내비게이션 - 이전/다음 콘텐츠 이동 버튼
- ✅ 자동 재생 설정 - 다음 콘텐츠 자동 재생 옵션
📦 설치
TypeScript 프로젝트
최신 버전은 TypeScript로 작성되었습니다:
# npm 사용
npm install @teamsparta/sparta-player
# yarn 사용
yarn add @teamsparta/sparta-player
# pnpm 사용
pnpm add @teamsparta/sparta-playerJavaScript 프로젝트
순수 JavaScript 프로젝트에서는 0.3.19 버전을 사용하세요:
npm install @teamsparta/[email protected]🚀 사용 방법
기본 예제 (TypeScript)
import React from "react";
import { SpartaPlayer } from "@teamsparta/sparta-player";
const VideoPage: React.FC = () => {
const videoSrc =
"https://bitdash-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8";
return (
<SpartaPlayer
source={videoSrc}
videoType="application/x-mpegURL"
autoPlay={false}
controls={true}
title="샘플 비디오"
/>
);
};
export default VideoPage;고급 예제 (모든 옵션 포함)
import React from "react";
import { SpartaPlayer } from "@teamsparta/sparta-player";
import { useNavigate } from "react-router-dom";
const AdvancedVideoPage: React.FC = () => {
const contentId = 0;
const navigate = useNavigate();
const videoSrc =
"https://bitdash-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8";
const vttSource = "https://example.com/subtitles/korean.vtt";
return (
<SpartaPlayer
source={videoSrc}
videoType="application/x-mpegURL"
autoPlay={true}
controls={true}
vttSource={vttSource}
thumbnail="https://picsum.photos/1024/500"
isNoVttSourceAlert={true}
noVttSourceAlertMessage="자막을 지원하지 않는 수업이에요."
title="스파르타 코딩클럽 강의"
isNavigationOn={true}
isAutoPlayButtonOn={true}
isLoaded={true}
defaultQuality={localStorage.getItem("quality") || "auto"}
defaultPlaybackRate={localStorage.getItem("rate") || "1"}
defaultSubtitle={localStorage.getItem("subtitle") || "false"}
defaultFullscreen={localStorage.getItem("fullscreen") || "false"}
defaultVolume={Number(localStorage.getItem("volume")) || 1}
defaultMuted={localStorage.getItem("muted") === "true"}
onReady={(player) => {
console.log("플레이어 준비 완료", player);
}}
onPlay={(time) => console.log("재생 시작", time)}
onPause={(time) => console.log("일시정지", time)}
onEnded={() => console.log("재생 종료")}
onTimeUpdate={(time) => console.log("시간 업데이트", time)}
onVolumeChange={(volume) =>
localStorage.setItem("volume", volume.toString())
}
onSeeking={(time) => localStorage.setItem("seeking", time.toString())}
onMute={(isMuted) => localStorage.setItem("muted", isMuted.toString())}
onPlaybackRateChange={(rate) =>
localStorage.setItem("rate", rate.toString())
}
onQualityChange={(quality) =>
localStorage.setItem("quality", quality.toString())
}
onSubtitleChange={(isSubtitle) =>
localStorage.setItem("subtitle", isSubtitle.toString())
}
onFullscreenChange={(isFullscreen) =>
localStorage.setItem("fullscreen", isFullscreen.toString())
}
onChangeAutoPlay={(isAutoPlay) =>
localStorage.setItem("autoplay", isAutoPlay.toString())
}
onClickPrev={() => {
if (contentId > 0) {
navigate(`/lecture/${contentId - 1}`);
}
}}
onClickNext={() => {
navigate(`/lecture/${contentId + 1}`);
}}
/>
);
};
export default AdvancedVideoPage;JavaScript 예제
import React from "react";
import { SpartaPlayer } from "@teamsparta/sparta-player";
export const VideoPage = () => {
return (
<SpartaPlayer
title="샘플 비디오"
source="https://www.w3schools.com/html/mov_bbb.mp4"
videoType="video/mp4"
isNavigationOn={true}
/>
);
};📚 Props API
| 속성명 | 타입 | 기본값 | 설명 |
| ----------------------- | ------------------------------------- | ---------- | ----------------------------------------------------------------- |
| source | string | "" | 필수 / 비디오 소스 URL |
| videoType | string | "" | 필수 / 비디오 타입 (예: 'video/mp4', 'application/x-mpegURL') |
| autoPlay | boolean | false | 로드 시 자동 재생 여부 |
| controls | boolean | true | 플레이어 컨트롤 바 표시 여부 |
| vttSource | string | "" | VTT 자막 파일 URL |
| thumbnail | string | "" | 썸네일 이미지 URL |
| isNoVttSourceAlert | boolean | false | 자막이 없을 때 알림 표시 여부 |
| noVttSourceAlertMessage | string | "" | 자막 없음 알림 메시지 |
| title | string | "" | 내비게이션에 표시될 제목 |
| isNavigationOn | boolean | false | 내비게이션 바 표시 여부 |
| isAutoPlayButtonOn | boolean | true | 설정 메뉴에 자동 재생 버튼 표시 여부 |
| isLoaded | boolean | true | 플레이어 로드 완료 여부 |
| defaultQuality | number | "auto" | "auto" | 기본 화질 (360, 540, 720, 1080 또는 "auto") |
| defaultPlaybackRate | number | 1 | 기본 재생 속도 |
| defaultMuted | boolean | false | 기본 음소거 상태 |
| defaultVolume | number | 1 | 기본 볼륨 (0-1) |
| defaultSubtitle | string | "false" | 기본 자막 상태 ("true" 또는 "false") |
| onReady | (player: any) => void | () => {} | 플레이어 준비 완료 시 호출 |
| onPlay | (time: number) => void | () => {} | 재생 시작 시 호출 |
| onPause | (time: number) => void | () => {} | 일시정지 시 호출 |
| onEnded | (time?: number) => void | () => {} | 재생 종료 시 호출 |
| onTimeUpdate | (time: number) => void | () => {} | 재생 시간 업데이트 시 호출 |
| onVolumeChange | (volume: number) => void | () => {} | 볼륨 변경 시 호출 |
| onSeeking | (time: number) => void | () => {} | 탐색 중 호출 |
| onMute | (muted: boolean) => void | () => {} | 음소거 상태 변경 시 호출 |
| onPlaybackRateChange | (rate: number) => void | () => {} | 재생 속도 변경 시 호출 |
| onQualityChange | (quality: number \| string) => void | () => {} | 화질 변경 시 호출 |
| onSubtitleChange | (enabled: boolean) => void | () => {} | 자막 상태 변경 시 호출 |
| onFullscreenChange | (fullscreen: boolean) => void | () => {} | 전체화면 상태 변경 시 호출 |
| onChangeAutoPlay | (autoPlay: boolean) => void | () => {} | 자동 재생 상태 변경 시 호출 |
| onClickPrev | () => void | () => {} | 내비게이션에서 이전 버튼 클릭 시 호출 |
| onClickNext | () => void | () => {} | 내비게이션에서 다음 버튼 클릭 시 호출 |
🔧 TypeScript 지원
버전 0.4.0부터 SpartaPlayer는 TypeScript를 완벽하게 지원합니다. 모든 props에 대한 타입 정의가 제공되어 IDE의 자동완성과 컴파일 타임 오류 검출이 가능합니다.
import { SpartaPlayer, SpartaPlayerProps } from "@teamsparta/sparta-player";
// SpartaPlayerProps로 타입 안전성 확보
const customProps: Partial<SpartaPlayerProps> = {
source: "video.mp4",
videoType: "video/mp4",
onPlay: (time) => console.log(`비디오가 ${time}초에 재생되었습니다`),
};
// IDE가 타입 힌트와 유효성 검사를 제공합니다
const MyPlayer = () => <SpartaPlayer {...customProps} autoPlay />;🛠️ 개발 환경 설정
필요한 도구
- Node.js: v16 이상
- pnpm: v8 이상 (권장)
저장소 클론 및 설치
# 저장소 클론
git clone <repository-url>
cd sparta-player
# 의존성 설치
pnpm install개발 서버 실행
# 개발 모드로 실행 (핫 리로딩 지원)
pnpm start개발 서버가 실행되면 http://localhost:3000에서 테스트 페이지를 확인할 수 있습니다.
프로젝트 구조
sparta-player/
├── src/
│ ├── lib/ # 라이브러리 소스 코드
│ │ ├── assets/ # SVG 아이콘 및 이미지
│ │ ├── utils/ # 유틸리티 함수
│ │ ├── SpartaPlayer.tsx
│ │ ├── types.ts # TypeScript 타입 정의
│ │ └── ...
│ ├── index.tsx # 개발 테스트용 엔트리
│ └── VideoPage.tsx # 테스트 페이지
├── dist/ # 빌드 결과물 (npm 배포용)
├── public/ # 개발용 정적 파일
└── scripts/ # 빌드 스크립트🏗️ 빌드 및 배포
빌드 프로세스
# TypeScript 컴파일 및 빌드
pnpm build빌드 과정은 다음 단계로 진행됩니다:
- 이미지 변환:
scripts/convert-images.mjs실행 - TypeScript 컴파일:
src/lib/폴더의 TypeScript 파일을dist/로 컴파일 - CSS 복사:
src/lib/sparta-player.css를dist/로 복사 - 에셋 복사:
src/lib/assets/폴더를dist/assets/로 복사
빌드 결과물
빌드가 완료되면 dist/ 폴더에 다음과 같은 파일들이 생성됩니다:
dist/
├── index.js # 컴파일된 JavaScript
├── index.d.ts # TypeScript 타입 정의
├── sparta-player.css # 스타일시트
├── assets/ # SVG 아이콘들
└── ... # 기타 컴파일된 파일들📦 패키지 버전업 가이드
본 프로젝트는 Changesets를 사용하여 패키지 버전을 관리합니다. 다음은 패키지 버전을 업데이트하는 단계별 가이드입니다.
1. Changeset 생성
pnpm changeset이 명령어를 실행하면 다음과 같은 과정을 거치게 됩니다:
- 변경된 패키지 선택
- 버전 업데이트 유형 선택 (major, minor, patch)
- 변경사항에 대한 설명 작성
2. 버전 업데이트 유형
- 패치(patch):
1.0.0->1.0.1- 예: 버그 수정, 작은 기능 개선
- 마이너(minor):
1.0.0->1.1.0- 예: 새로운 기능 추가 (하위 호환성 유지)
- 메이저(major):
1.0.0->2.0.0- 예: 주요 시스템 변경, 하위 호환성을 깨는 변경
3. Changeset 커밋
생성된 Changeset 파일(.changeset 디렉토리 내)을 커밋합니다:
git add .changeset
git commit -m "chore: add changeset for [변경사항 설명]"4. Pull Request 생성
변경사항과 Changeset을 포함한 Pull Request를 생성합니다.
5. 리뷰 및 머지
코드 리뷰 후 Pull Request가 승인되면 main 브랜치로 머지합니다.
6. 버전 업데이트 PR 생성
main 브랜치로 머지된 후, Changeset 봇이 자동으로 버전 업데이트 PR을 생성합니다.
7. 버전 업데이트 PR 머지
버전 업데이트 PR을 리뷰하고 main 브랜치로 머지합니다.
8. 자동 배포
버전 업데이트 PR이 머지되면 CI/CD 파이프라인에 의해 자동으로 새 버전이 배포됩니다.
수동 배포 (필요한 경우)
자동 배포가 실행되지 않는 경우, 다음 명령어로 수동 배포할 수 있습니다:
# 버전 업데이트 및 배포
pnpm release이 명령은 다음을 수행합니다:
- 프로젝트 빌드
- changeset에 따라 버전 업데이트
- npm에 패키지 배포
🚢 프리릴리스 배포 (Canary / Next)
프리릴리스 버전을 배포하려면 다음 단계를 따릅니다:
Canary 배포
Canary 배포는 매우 초기 단계의 변경사항을 테스트하기 위한 것입니다.
- Canary 브랜치 생성:
git checkout -b canary- Changeset 생성:
pnpm changeset pre enter canary- 변경사항 커밋 및 푸시:
git add .
git commit -m "chore: prepare canary release"
git push origin canary- Canary 버전 배포:
pnpm changeset version
pnpm changeset publishNext 배포
Next 배포는 다음 정식 버전의 후보 릴리스를 위한 것입니다.
- Next 브랜치 생성:
git checkout -b next- Changeset 생성:
pnpm changeset pre enter next- 변경사항 커밋 및 푸시:
git add .
git commit -m "chore: prepare next release"
git push origin next- Next 버전 배포:
pnpm changeset version
pnpm changeset publish프리릴리스 모드 종료
프리릴리스 모드를 종료하고 정식 버전으로 돌아가려면:
pnpm changeset pre exit주의사항
- 하나의 PR에는 하나의 기능 또는 수정사항만 포함하도록 합니다.
- Changeset 설명은 명확하고 구체적으로 작성합니다.
- 버전 업데이트 유형(major, minor, patch)을 신중히 선택합니다.
- Canary와 Next 배포는 실험적 기능이나 큰 변경사항을 테스트할 때 사용합니다.
- 프리릴리스 버전은 안정성이 보장되지 않으므로 프로덕션 환경에서는 사용하지 않도록 주의합니다.
이 가이드를 따르면 일관된 방식으로 패키지 버전을 관리하고 변경사항을 추적할 수 있습니다.
🧪 테스트
# 유닛 테스트 실행
pnpm test
# 워치 모드로 테스트 실행
pnpm test -- --watch현재 src/lib/utils/playerLogic.test.ts에서 playerLogic 관련 유닛 테스트를 실행할 수 있습니다.
