IndexedDB → OPFS 마이그레이션

이혜란·2026년 4월 9일

기타 자료 공유

목록 보기
12/13
post-thumbnail

브라우저 스토리지 전환 | 비디오 렌더링 최적화

1. OPFS(Origin Private File System)란?

OPFS는 Web File System Access API의 일부로, 브라우저가 특정 Origin(도메인)에 전용으로 제공하는 샌드박스형 가상 파일 시스템입니다. 2022년 이후 주요 브라우저에 표준으로 탑재되었으며, 기존 웹 스토리지 API 대비 월등한 성능을 제공합니다.

핵심 특징

  • Origin-Private: 도메인 단위로 격리된 전용 파일 시스템 (사용자 파일 시스템과 분리)
  • 고성능 바이너리 I/O: 대용량 파일을 원시 바이트 단위로 읽고 쓸 수 있음
  • 동기식 API: Web Worker 내에서 동기(blocking) 방식으로 파일 접근 가능
  • 스트림 지원: ReadableStream / WritableStream과 통합 가능
  • 용량: IndexedDB와 동일한 스토리지 쿼터 공유 (보통 수 GB 이상)

기본 사용법 예제

파일 쓰기 (비동기)

// OPFS 루트 디렉토리 획득
const root = await navigator.storage.getDirectory();
 
// 파일 핸들 생성 (없으면 자동 생성)
const fileHandle = await root.getFileHandle('video-chunk.bin', { create: true });
 
// 쓰기 스트림 열기
const writable = await fileHandle.createWritable();
await writable.write(videoChunkBuffer); // ArrayBuffer 또는 Blob
await writable.close();

파일 읽기 (비동기)

const root = await navigator.storage.getDirectory();
const fileHandle = await root.getFileHandle('video-chunk.bin');
const file = await fileHandle.getFile();
const buffer = await file.arrayBuffer();

동기식 API (Web Worker 전용 — 고성능)

// worker.js 내부
const root = await navigator.storage.getDirectory();
const fileHandle = await root.getFileHandle('frame-data.bin', { create: true });
 
// 동기 접근 핸들 — createSyncAccessHandle은 Worker에서만 사용 가능
const syncHandle = await fileHandle.createSyncAccessHandle();
 
// 바이트 오프셋 지정 랜덤 쓰기
const offset = frameIndex * FRAME_SIZE;
syncHandle.write(frameBuffer, { at: offset });
 
// 부분 읽기
const readBuf = new ArrayBuffer(FRAME_SIZE);
syncHandle.read(readBuf, { at: offset });
 
syncHandle.flush();
syncHandle.close();

디렉토리 생성 및 파일 목록

const root = await navigator.storage.getDirectory();
 
// 하위 디렉토리 생성
const projectDir = await root.getDirectoryHandle('my-project', { create: true });
 
// 파일 목록 순회
for await (const [name, handle] of projectDir.entries()) {
  console.log(name, handle.kind); // 'file' | 'directory'
}

2. IndexedDB vs OPFS 장단점 비교

항목IndexedDBOPFS
저장 방식키-값 기반 객체 저장소 (NoSQL)파일 시스템 기반 (계층적 디렉토리)
API 유형비동기 (async)비동기 + 동기 (Worker 내)
대용량 처리❌ 느림 (직렬화/역직렬화 오버헤드)✅ 빠름 (원시 바이너리 스트림 직접 접근)
메모리 효율❌ 낮음 (전체 객체 로드)✅ 높음 (부분 읽기/쓰기 가능)
Worker 지원일부 지원✅ 완전 지원 (동기 API 사용 가능)
랜덤 접근키 기준만 가능✅ 바이트 오프셋 기반 직접 접근
트랜잭션✅ 지원 (ACID 보장)❌ 미지원
복잡한 쿼리✅ 인덱스 기반 검색 가능❌ 미지원 (파일 단위 접근)
브라우저 지원✅ 모든 주요 브라우저Chrome 86+, Safari 15.2+, Firefox 111+
주요 활용처구조화된 메타데이터, 설정값, 소량 데이터대용량 바이너리 (영상, 오디오, 이미지)

IndexedDB 장점

  • ACID 트랜잭션: 데이터 무결성 보장 (충돌 발생 시 롤백 가능)
  • 복잡한 쿼리: 인덱스 기반 검색으로 특정 레코드 빠르게 조회 가능
  • 광범위한 브라우저 지원: IE 11을 포함한 모든 브라우저에서 오랫동안 지원
  • 구조화 데이터: JSON 객체를 그대로 저장하고 스키마 관리 용이

IndexedDB 단점

  • 직렬화 오버헤드: 저장 시 객체를 직렬화하고, 읽을 때 역직렬화하여 대용량 데이터에서 느림
  • 부분 접근 불가: 저장된 객체 전체를 로드해야 하며 바이트 단위 랜덤 접근 미지원
  • 비디오/이미지 성능: 수백 MB 이상의 바이너리 처리에 부적합

OPFS 장점

  • 고속 바이너리 I/O: 파일 시스템 수준의 빠른 읽기/쓰기 (Native에 가까운 속도)
  • 랜덤 접근: 바이트 오프셋으로 특정 구간만 읽거나 쓸 수 있어 메모리 효율적
  • Worker 동기 API: createSyncAccessHandle()로 Worker 내 동기식 접근 가능
  • 스트림 통합: WritableStream과 연계해 실시간 데이터 저장에 적합

OPFS 단점

  • 트랜잭션 없음: 동시 접근 시 충돌 처리를 직접 구현해야 함
  • 쿼리 불가: 파일 이름 기반 접근만 가능, 복잡한 데이터 검색 부적합
  • 브라우저 지원: 최신 브라우저만 지원 (Chrome 86+, Safari 15.2+, Firefox 111+)
  • 메타데이터 관리: 파일 메타 정보(길이, 타임스탬프 등)는 별도로 관리 필요

3. 비디오 편집 렌더링에 적합한 기술

✅ 결론: 비디오 편집 렌더링에는 OPFS + Web Worker 조합이 적합합니다.

왜 OPFS인가?

비디오 편집 렌더링 파이프라인은 다음과 같은 특성을 갖습니다.

  • 대용량 데이터: 1분 분량의 4K 영상은 수백 MB ~ 수 GB에 달함
  • 프레임 단위 접근: 특정 타임코드의 프레임만 빠르게 읽어야 함 (랜덤 접근 필수)
  • 연속 쓰기: 렌더링 결과물을 실시간으로 파일에 순차 기록
  • UI 블로킹 방지: 렌더링 작업이 메인 스레드를 방해하면 안 됨

OPFS는 이 모든 요구사항을 충족합니다. 수 GB 파일을 직접 핸들링할 수 있고, at 옵션으로 특정 프레임 바이트 오프셋에 직접 접근하며, Web Worker 내 동기 API로 렌더링 루프를 단순화할 수 있습니다.

권장 아키텍처

// 메인 스레드: 타임라인 편집 UI
const worker = new Worker('render-worker.js');
worker.postMessage({ type: 'START_RENDER', config: renderConfig });
 
// render-worker.js: OPFS 기반 렌더링 루프
const root = await navigator.storage.getDirectory();
const outHandle = await root.getFileHandle('output.mp4', { create: true });
const syncHandle = await outHandle.createSyncAccessHandle();
 
for (let frame = 0; frame < totalFrames; frame++) {
  const frameData = renderFrame(frame);           // CPU 렌더링
  syncHandle.write(frameData, { at: frame * FRAME_BYTE_SIZE });
}
 
syncHandle.flush();
syncHandle.close();

IndexedDB가 여전히 필요한 경우

비디오 편집 도구라도 역할을 나눠 두 기술을 병용하는 것이 최선입니다.

IndexedDB 담당OPFS 담당
프로젝트 메타데이터원본 영상 파일 캐시
클립 목록 및 타임라인 정보렌더링 출력 파일
사용자 설정 및 환경설정프레임 버퍼 / 썸네일 이미지
편집 히스토리 (Undo/Redo)오디오 웨이브폼 데이터

4. 요약

📋 핵심 정리
IndexedDB는 구조화된 메타데이터 관리에, OPFS는 대용량 바이너리 파일 처리에 각각 최적화되어 있습니다. 비디오 편집 렌더링처럼 대규모 I/O가 필요한 환경에서는 OPFS로의 마이그레이션이 성능과 메모리 효율 모두에서 올바른 선택이라 생각합니다.

  • OPFS의 핵심 강점: 원시 파일 I/O, 바이트 오프셋 랜덤 접근, Worker 동기 API
  • IndexedDB의 강점: ACID 트랜잭션, 복잡한 쿼리, 광범위한 브라우저 지원
  • 비디오 렌더링 최적 스택: OPFS + Web Worker (createSyncAccessHandle 활용)
  • 실무 권장: 두 기술을 역할에 따라 병용하는 하이브리드 방식이 현실적 최선

0개의 댓글