웹에서 동영상 스토리지 관리하기

동영상은 관리하기 어려운 애셋입니다. 스트리밍에는 많은 대역폭이 필요하고 캐싱은 간단하지 않습니다. 키오스크 디스플레이와 같이 동영상이 연속 재생되는 경우 이러한 문제가 더욱 심각해집니다. 예를 들어 회사의 기기 수백 대가 하루 종일 매일 30개의 동영상을 반복 재생하는 경우 네트워크가 빠르게 과부하될 수 있습니다. 동영상을 스트리밍하는 대신 캐시에서 제공하면 다운로드 비용이 한 번만 발생하고, 이후 재생 속도가 빨라지며, 오프라인으로 재생할 수 있습니다. 이렇게 하려면 브라우저의 스토리지 기능을 활용하면 됩니다. 이 중 캐시 스토리지 APIIndexedDB가 동영상 파일을 저장하는 데 가장 적합합니다. 둘 다 좋은 옵션이지만 인기 있는 서비스 워커 라이브러리 Workbox와의 통합을 위해 Cache Storage API에 중점을 두겠습니다.

서비스 워커에서 동영상 캐싱

동영상과 같은 대규모 애셋을 다운로드하고 캐싱하는 작업은 특히 시간과 프로세서 집약적인 작업일 수 있으므로 기본 스레드에서 벗어나 백그라운드에서 실행해야 합니다. 서비스 워커는 특히 캐싱 작업을 오프로드하는 데 유용합니다. 페이지와 네트워크 간의 프록시 역할을 하여 요청을 가로채고 네트워크 응답에 추가 로직(예: 캐싱 전략)을 적용할 수 있습니다.

다양한 캐싱 전략이 있으며 각 전략은 서로 다른 사용 사례에 도움이 되도록 설계되었습니다. 예를 들어 캐시에서 파일을 제공하고, 캐시가 없으면 네트워크로 대체하려면 다음 코드를 작성하면 됩니다.

self.addEventListener('fetch', function (event) {
  event.respondWith(
    caches.match(event.request).then(function (response) {
      return response || fetch(event.request);
    }),
  );
});

다양한 애셋 유형 또는 서로 다른 캐싱 전략이 필요한 URL에 대해 이를 관리하는 것은 반복적이고 오류가 발생하기 쉬운 프로세스일 수 있습니다. Workbox라우팅 도우미, 캐싱 전략 등 서비스 워커 코드를 더 선언적이고 재사용 가능한 방식으로 작성할 수 있는 도구 세트를 제공합니다.

이전 전략을 캐시 우선이라고 합니다. Workbox를 사용하여 동일한 작업을 수행하려면 다음을 포함하면 됩니다.

registerRoute(
  ({ request }) => request.destination === 'video',
  new CacheFirst()
);

Workbox는 기타 캐싱 전략Webpack, Rollup과 같은 빌드 도구와의 통합을 비롯한 일반적인 서비스 워커 작업에 대한 유사한 레시피를 제공합니다.

Workbox를 설정한 후 동영상을 캐시할 시점을 선택해야 합니다. 여기에는 두 가지 접근 방식이 있습니다. 페이지 로드 시 적극적으로 또는 동영상이 요청될 때 지연적으로 로드하는 것입니다.

Eager 접근 방식

사전 캐싱은 서비스 워커 설치 중에 파일이 캐시에 저장되어 서비스 워커가 시작되는 즉시 사용할 수 있도록 하는 기술입니다. Workbox는 빌드 프로세스 중에 액세스할 수 있는 파일의 사전 캐싱을 자동으로 설정할 수 있습니다.

다음 Workbox 코드를 서비스 워커에서 사용하여 파일을 미리 캐시할 수 있습니다.

import { addPlugins, precacheAndRoute } from 'workbox-precaching';
import { RangeRequestsPlugin } from 'workbox-range-requests';

addPlugins([new RangeRequestsPlugin()]);
precacheAndRoute(self.__WB_MANIFEST);
  • import(s) - 해당 Workbox 모듈에서 필요한 바인딩을 로드합니다. 서비스 워커는 아직 ESModule을 범용적으로 지원하지 않으므로 프로덕션에서 작동하려면 Workbox 기반 서비스 워커를 번들러를 통해 전달해야 합니다.
  • RangeRequestsPlugin - Range 헤더가 있는 요청이 캐시된 응답으로 처리될 수 있도록 합니다. 브라우저가 일반적으로 미디어 콘텐츠에 Range 헤더를 사용하기 때문에 필요합니다.
  • addPlugins - 모든 Workbox 요청에 Workbox 플러그인을 추가할 수 있습니다.
  • precacheAndRoute - 프리캐시 목록에 항목을 추가하고 해당 가져오기 요청을 처리하는 경로를 만듭니다.
  • __WB_MANIFEST - Workbox CLI (또는 빌드 도구 플러그인)가 사전 캐시 매니페스트로 대체하는 자리표시자입니다.

서비스 워커를 Workbox CLI 또는 원하는 빌드 도구에 전달하고 사전 캐시 생성 방법을 구성합니다. 다음 예와 같은 workbox-config.js 파일은 CLI에 서비스 워커 렌더링 방법을 알려줍니다.

module.exports = {
  globDirectory: '.',
  globPatterns: ['**/*.{html,mp4}'],
  maximumFileSizeToCacheInBytes: 5000000,
  swSrc: 'sw.js',
  swDest: 'sw.js',
};
  • globDirectory - 사전 캐시 파일 검색을 시작할 루트 폴더
  • globPatterns - 미리 캐시해야 하는 파일 패턴 ('glob')입니다.
  • maximumFileSizeToCacheInBytes - 파일을 미리 캐시할 수 있는 최대 크기(바이트)입니다.
  • swSrc - 서비스 워커를 생성하는 데 사용될 파일의 위치입니다.
  • swDest - 생성된 서비스 워커의 대상입니다. 소스 파일과 동일할 수 있지만 각 실행에 self.__WB_MANIFEST가 있는지 확인하세요.

빌드 프로세스가 실행되면 서비스 워커의 새 버전이 생성되고 self.__WB_MANIFEST가 파일 목록으로 대체됩니다. 각 파일에는 수정사항을 나타내는 해시가 있습니다.

precacheAndRoute([
  {
    revision: '524ac4b453c83f76eb9caeec11854ca5',
    url: 'ny.mp4',
  },
]);

빌드 프로세스가 실행될 때마다 이 목록은 일치하는 파일의 현재 집합과 현재 수정사항 해시로 다시 작성됩니다. 이렇게 하면 파일이 추가, 삭제 또는 변경될 때마다 서비스 워커가 다음 설치 시 캐시를 업데이트합니다.

지연 방식

빌드 시점에 모든 동영상을 사용할 수 없거나 필요할 때만 동영상을 캐시하려는 경우 지연 로딩 방식을 사용해야 합니다. 이 접근 방식에서는 캐싱과 제공이 분리되어야 합니다. 동영상 재생 중에 네트워크에서 일부 콘텐츠만 가져오기 때문에 스트리밍 중에 파일을 캐싱하는 것은 작동하지 않습니다.

파일 캐싱

캐시는 Cache.open()을 사용하여 만들 수 있으며, Cache.add() 또는 Cache.addAll()을 사용하여 캐시에 파일을 추가할 수 있습니다. 앱이 캐시할 동영상의 JSON 목록을 수신하는 경우 다음과 같이 동영상 캐시에 추가할 수 있습니다.

// Open video cache
const cache = await caches.open('video-cache');
// Fetch list of videos
const videos = await (await fetch('/video-list.json')).json();
// Add videos to cache
await cache.addAll(videos);

이 접근 방식의 장점은 다른 웹 작업자에서도 서비스 워커 수명 주기와 독립적으로 캐싱 단계를 제어할 수 있다는 것입니다. 단점은 스토리지 관리 부분이 개발자에게 달려 있다는 것입니다. 파일 변경사항을 추적하고, 브라우저에 현재 캐시된 파일을 추적하고, 변경된 파일만 업데이트되도록 파일 업데이트를 관리하는 자체 알고리즘을 작성해야 합니다.

캐시된 동영상 파일 제공

그런 다음 캐시 우선과 같은 서비스 워커 런타임 캐싱 전략을 사용하여 이전에 캐시된 동영상 파일을 제공할 수 있습니다.

import { registerRoute } from 'workbox-routing';
import { CacheFirst } from 'workbox-strategies';
import { CacheableResponsePlugin } from 'workbox-cacheable-response';
import { RangeRequestsPlugin } from 'workbox-range-requests';

registerRoute(
  ({ request }) => request.destination === 'video',
  new CacheFirst({
    cacheName: 'video-cache',
    plugins: [
      new CacheableResponsePlugin({
        statuses: [200],
      }),
      new RangeRequestsPlugin(),
    ],
  }),
);
  • import(s) - 해당 workbox 모듈에서 필요한 바인딩을 로드합니다.
  • registerRoute - 응답을 제공하는 함수 (캐싱 전략 및 플러그인)로 요청을 라우팅합니다.
  • CacheFirst - 요청이 캐시에서 제공되는 경우 캐시에서 요청을 처리하고, 그렇지 않은 경우 네트워크에서 가져와 캐시를 업데이트하는 캐싱 전략입니다.
  • CacheableResponsePlugin - 응답이 캐시 가능하려면 어떤 헤더가 있어야 하는지 나타내는 데 사용됩니다. 동영상이 스트리밍될 때 부분 콘텐츠 응답 (206)이 캐시되지 않도록 동영상을 캐시하는 경로의 상태를 200개만 포함해야 합니다.
  • RangeRequestsPlugin - Range 헤더가 있는 요청이 캐시된 응답으로 처리될 수 있도록 하는 플러그인 브라우저가 일반적으로 미디어 콘텐츠에 Range 헤더를 사용하기 때문에 필요합니다.

집중 스트리밍을 실행하는 앱의 경우 동영상 로딩을 최적화하는 것이 중요합니다. 브라우저의 캐시 스토리지 API와 Workbox를 활용하면 이 어려운 작업을 관리할 수 있어 사용자의 대역폭을 절약하고, 서버 부하를 줄이며, 동영상 재생 속도를 높이고, 오프라인 상태에서도 동영상을 재생할 수 있습니다.