OpenScreen은 Screen Studio($29/월)의 무료 오픈소스 대안으로, Electron + React + PixiJS로 만든 데스크톱 화면 녹화 & 영상 편집 앱입니다. 워터마크 없이 자동 줌, 모션 블러, 크롭, 어노테이션 등 후편집 기능을 포함하며, macOS·Windows·Linux 크로스플랫폼을 지원합니다.
기존 OBS는 녹화만 하고 별도 편집 툴이 필요합니다. OpenScreen은 녹화 → 자동 줌 효과 적용 → 배경 교체 → 어노테이션 추가 → 내보내기까지 한 앱에서 완결됩니다.
비결은 4개의 독립 BrowserWindow(HUD 오버레이·소스 선택·편집기·카운트다운 오버레이)가 각자의 역할에 최적화된 설정으로 동시에 동작하는 멀티 윈도우 아키텍처입니다.
OpenScreen은 유료 대안의 무료화라는 단순하지만 강력한 메시지로 주목받았습니다. Screen Studio·Loom 같은 유료 녹화 도구의 핵심 기능을 MIT 라이선스로 제공하고, 웹 개발자가 익숙한 Electron + React + Vite 스택을 써서 진입 장벽을 낮췄습니다.
OBS는 강력하지만 후편집이 없습니다. Screen Studio는 macOS 전용에 월 구독료가 있습니다. Loom은 클라우드에 영상이 올라가므로 프라이버시 민감 업무에 부적합합니다.
MIT 라이선스로 완전 무료, 모든 영상이 로컬에 저장되어 클라우드 의존 없음, macOS·Windows·Linux 모두 지원, 자동 줌·어노테이션·배경 커스텀 등 후편집 기능까지 내장합니다.
| 기능 | OpenScreen | Screen Studio | OBS | Loom |
|---|---|---|---|---|
| 가격 | 무료 (MIT) | $29/월 | 무료 | 프리미엄 |
| 자동 줌 | 지원 | 지원 | 없음 | 없음 |
| 영상 편집 내장 | 지원 | 지원 | 없음 | 제한적 |
| 어노테이션 | 지원 | 지원 | 없음 | 없음 |
| 오픈소스 | MIT | 없음 | GPL | 없음 |
| 크로스플랫폼 | macOS/Win/Linux | macOS만 | 전체 | 웹 기반 |
| 카테고리 | 기술 | 역할 |
|---|---|---|
| UI 프레임워크 | React 18 + TypeScript | 컴포넌트 기반 UI |
| 스타일링 | Tailwind CSS + PostCSS | 유틸리티 퍼스트 CSS |
| UI 컴포넌트 | Radix UI (11개 프리미티브) | 접근성 있는 헤드리스 UI |
| 애니메이션 | GSAP, Motion (Framer Motion) | 고성능 애니메이션 |
| 그래픽 렌더링 | PixiJS + pixi-filters | WebGL 기반 타임라인 시각화 |
| 타임라인 | dnd-timeline | 드래그 앤 드롭 타임라인 |
| 카테고리 | 기술 | 역할 |
|---|---|---|
| 런타임 | Electron | Node.js + Chromium 데스크톱 앱 |
| 빌드 | electron-builder | 크로스플랫폼 패키징 (.dmg, .exe, .AppImage) |
| IPC | contextBridge + ipcRenderer | 보안 프로세스 간 통신 |
| 카테고리 | 기술 | 역할 |
|---|---|---|
| 녹화 | MediaRecorder API | 화면/오디오 캡처 |
| 코덱 우선순위 | AV1 > H264 > VP9 > VP8 | 지원 여부 감지 후 최적 선택 |
| 영상 파싱 | mp4box, web-demuxer | MP4 컨테이너 처리 |
| 오디오 믹싱 | Web Audio API (AudioContext) | 시스템 + 마이크 오디오 합성 |
| MP4/WebM 처리 | mediabunny | MP4/WebM 처리 라이브러리 |
| GIF 내보내기 | gif.js | GIF 파일 생성·내보내기 |
| 온디바이스 자막 | @xenova/transformers (Whisper) | 오프라인 자동 자막 생성 |
| 카테고리 | 기술 | 역할 |
|---|---|---|
| 빌드 도구 | Vite 7 + vite-plugin-electron | HMR 지원 Electron 개발 |
| 테스트 | Vitest (유닛) + Playwright (E2E) | 이중 테스트 전략 |
| 린팅 | Biome | Rust 기반 초고속 린터/포매터 |
| Git 훅 | Husky + lint-staged | 커밋 전 자동 검증 |
Electron의 BrowserWindow를 4개로 분리해 각 화면의 역할을 명확히 구분합니다.
// windows.ts에서 HUD 오버레이 위치 계산
const primaryDisplay = screen.getPrimaryDisplay();
const { width, height } = primaryDisplay.workAreaSize;
x = Math.round((width - 600) / 2); // 화면 중앙
y = height - 160 - 20; // 화면 하단 20px 위
// frame: false, transparent: true, alwaysOnTop: true
// preload.ts — 렌더러에 노출하는 API만 명시적으로 선언
contextBridge.exposeInMainWorld('electronAPI', {
storeRecordedVideo: (buffer) => ipcRenderer.invoke('store-video', buffer),
getSources: () => ipcRenderer.invoke('get-sources'),
// ... 약 30개 API
});
원칙: 렌더러 프로세스는 절대 Node.js API에 직접 접근 불가. 웹 페이지가 악성 코드를 실행해도 파일 시스템이나 OS 기능에 접근할 수 없습니다.
function computeBitrate(width: number, height: number, fps: number): number {
const pixels = width * height;
let bitrate;
if (pixels >= 3840 * 2160) bitrate = 45_000_000; // 4K
else if (pixels >= 2560 * 1440) bitrate = 28_000_000; // QHD
else bitrate = 18_000_000; // 1080p
return fps >= 60 ? bitrate * 1.7 : bitrate;
}
{ past: EditorState[], present: EditorState, future: EditorState[] }
// pushState() — 버튼 클릭 같은 이산 액션 → 체크포인트 생성
// updateState() — 슬라이더 드래그 같은 연속 액션 → present만 업데이트
// commitState() — 드래그 끝 → dirty 플래그 리셋
// 최대 80단계 히스토리로 메모리 제한
const audioContext = new AudioContext();
const destination = audioContext.createMediaStreamDestination();
const systemSource = audioContext.createMediaStreamSource(systemStream);
const micSource = audioContext.createMediaStreamSource(micStream);
const micGain = audioContext.createGain();
micGain.gain.value = 1.4; // 마이크 볼륨 40% 부스트
systemSource.connect(destination);
micSource.connect(micGain).connect(destination);
// destination.stream을 MediaRecorder에 전달
멀티 윈도우 관리 패턴, contextIsolation + contextBridge를 사용한 보안 IPC 통신, 시스템 트레이 통합, OS별 분기 처리, electron-builder로 크로스플랫폼 패키징(DMG, EXE, AppImage)을 배웁니다.
navigator.mediaDevices.getDisplayMedia()로 화면 캡처, getUserMedia()로 마이크/웹캠 캡처, 코덱 지원 여부 확인(MediaRecorder.isTypeSupported()), ondataavailable 이벤트로 청크 수집 → Blob 조립, WebM duration 메타데이터 버그와 해결법(fix-webm-duration)을 배웁니다.
AudioContext → createMediaStreamSource() → GainNode → MediaStreamDestination 파이프라인, 두 개 이상의 오디오 소스를 하나로 믹싱하는 오디오 그래프 설계, AnalyserNode로 실시간 오디오 레벨 시각화를 배웁니다.
Canvas 대신 WebGL로 타임라인 렌더링(성능 핵심), pixi-filters(드롭 섀도 등) 적용법, 타임라인 UI에서 WebGL이 왜 Canvas보다 나은지 이해합니다.
Context API 활용(I18n, Shortcuts) — 전역 상태를 Redux 없이 관리, 커스텀 훅으로 로직 분리, 3-상태 Undo/Redo 패턴(past/present/future + dirty 추적), Radix UI 프리미티브를 래핑한 커스텀 UI 컴포넌트 시스템을 배웁니다.
| OS | 최소 버전 | 비고 |
|---|---|---|
| macOS | 13 (Ventura) | 시스템 오디오는 14.2+ 필요, CoreAudio Tap API 사용 |
| Windows | 10+ | 전체 기능 지원 |
| Linux | Ubuntu 20.04+ | PipeWire 필요 (오디오 캡처) |
| 항목 | 권장 | 비고 |
|---|---|---|
| CPU | 4코어 이상 | 녹화 + 인코딩 동시 처리 |
| RAM | 8GB 이상 | Electron + MediaRecorder + 영상 편집 |
| GPU | 하드웨어 가속 지원 | PixiJS WebGL 렌더링, AV1 인코딩 |
| 저장공간 | 녹화 시간에 비례 | 4K 60fps 기준 ~45Mbps ≈ 5.6MB/s |
순수 HTML + JavaScript로 화면 녹화 → WebM 다운로드 기능을 구현합니다. Electron 없이 브라우저만으로 가능합니다.
// 힌트: 이 API들을 조합
const stream = await navigator.mediaDevices.getDisplayMedia({ video: true });
const recorder = new MediaRecorder(stream, { mimeType: 'video/webm;codecs=vp9' });
마이크 입력을 AudioContext + AnalyserNode로 분석해서 실시간 볼륨 바를 그립니다.
OpenScreen의 아키텍처를 참고해 Electron + React + Vite로 최소한의 화면 녹화앱을 만듭니다. HUD 오버레이(투명 창, 최상위), 시작/정지 버튼, contextBridge 보안 IPC, 파일 저장까지 구현합니다.
useEditorHistory.ts를 참고해 범용 useHistory<T>() 훅을 직접 구현합니다. 슬라이더 드래그를 하나의 히스토리로 묶는 dirty 추적 로직까지 포함합니다.
PixiJS로 비디오 타임라인 UI를 만들고, 특정 구간에 자동 줌 효과를 적용하는 영상 편집기 프로토타입을 제작합니다. OpenScreen의 video-editor/timeline/ 폴더 구조를 참고합니다.
Electron 공식 튜토리얼 완주, main/renderer/preload 프로세스 모델 이해, contextBridge + IPC 패턴으로 간단한 앱 만들기, electron-builder로 패키징 테스트.
vite-plugin-electron 세팅부터 HMR 동작까지 직접 구성, 청크 분할(manualChunks) 설정 실험, 환경변수로 개발/프로덕션 분기 처리.
getDisplayMedia/getUserMedia 옵션 파라미터 마스터, 코덱 호환성 매트릭스 학습(AV1, H264, VP9), AudioContext 오디오 그래프 설계, AnalyserNode로 FFT 기반 시각화 구현.
PixiJS 기초(Stage, Container, Sprite, Graphics), WebGL vs Canvas 성능 차이 벤치마킹, pixi-filters로 시각 효과 적용, 드래그 가능한 타임라인 UI 프로토타입.
커스텀 훅 설계 원칙(관심사 분리, 합성 가능성), Context API vs Zustand/Jotai 선택 기준, Radix UI 프리미티브 래핑 패턴, 3-상태 히스토리 패턴 범용 구현.
Terser 설정으로 번들 최소화, Electron 앱 성능 프로파일링, Playwright E2E 테스트 작성, electron-builder로 자동 업데이트 구현(electron-updater).
| 키워드 | 설명 |
|---|---|
| Electron | Chromium + Node.js 기반 크로스플랫폼 데스크톱 앱 프레임워크. 웹 기술로 네이티브 앱을 만든다 |
| Main Process | Electron의 백엔드 역할. Node.js API, 파일 시스템, OS 기능에 접근 가능. 창 생성/관리 담당 |
| Renderer Process | Electron의 프론트엔드 역할. 각 BrowserWindow가 독립된 렌더러 프로세스를 가짐 |
| Preload Script | 렌더러 프로세스가 로드되기 전에 실행되는 스크립트. contextBridge로 안전한 API만 노출 |
| contextBridge | Electron의 보안 메커니즘. 메인 프로세스의 기능을 렌더러에 선별적으로 노출하는 다리 역할 |
| contextIsolation | 렌더러의 JS 컨텍스트를 preload 스크립트와 분리. XSS 공격 시에도 Node.js API 접근 차단 |
| IPC | Inter-Process Communication. 메인↔렌더러 간 통신. ipcMain.handle() + ipcRenderer.invoke() 패턴 |
| MediaRecorder API | 브라우저 내장 미디어 녹화 API. MediaStream을 받아 WebM/MP4로 인코딩 |
| getDisplayMedia() | 화면 공유/녹화용 API. 사용자가 화면/창/탭을 선택하면 MediaStream 반환 |
| getUserMedia() | 카메라/마이크 접근 API. 오디오/비디오 MediaStream 반환 |
| AudioContext | Web Audio API의 핵심. 오디오 처리 그래프(노드 연결)를 생성/관리하는 컨텍스트 |
| GainNode | 오디오 볼륨 조절 노드. 0.0(무음)~1.0+(증폭) 범위 |
| AnalyserNode | 오디오 주파수/시간 도메인 분석 노드. 실시간 레벨 미터, 스펙트럼 시각화에 사용 |
| PixiJS | WebGL 기반 2D 렌더링 엔진. Canvas API보다 GPU 가속으로 훨씬 빠른 그래픽 처리 |
| WebGL | 브라우저에서 GPU를 직접 활용하는 저수준 그래픽 API |
| AV1 | 차세대 비디오 코덱. VP9 대비 30% 더 효율적인 압축. 인코딩은 느리지만 품질/크기 최적 |
| WebM | Google의 오픈소스 비디오 컨테이너 포맷. VP8/VP9/AV1 코덱 지원 |
| Vite | 차세대 프론트엔드 빌드 도구. ESModule 기반 HMR로 개발 서버 즉시 시작 |
| vite-plugin-electron | Vite와 Electron을 통합하는 플러그인. HMR 지원 Electron 개발 환경 제공 |
| Radix UI | 접근성(a11y) 완벽 지원 헤드리스 UI 프리미티브. 스타일 없이 동작만 제공해 커스텀 자유도 최대 |
| Biome | Rust로 만든 초고속 린터+포매터. ESLint+Prettier를 하나로 대체. 10~100배 빠름 |
| GSAP | 고성능 JavaScript 애니메이션 라이브러리. CSS 애니메이션보다 세밀한 제어 가능 |
| electron-builder | Electron 앱 패키징/배포 도구. DMG, NSIS, AppImage 등 OS별 설치파일 생성 |
| Playwright | Microsoft의 크로스브라우저 E2E 테스트 프레임워크. Electron 앱 테스트도 지원 |