들어가며: 브라우저 AI의 숨은 병목, 중복 캐시

최근 웹 브라우저에서 직접 AI 모델을 실행하는 '온디바이스 AI' 트렌드가 주목받고 있습니다. Transformers.js, WebLLM, wllama 같은 라이브러리를 사용하면 별도의 서버 없이도 사용자 브라우저에서 바로 자연어 처리나 음성 인식 같은 작업을 수행할 수 있죠.

하지만 여기엔 한 가지 큰 문제가 있습니다. 같은 모델 파일을 여러 웹사이트에서 각자 다운로드하고 저장한다는 점입니다. 예를 들어 Xenova/whisper-tiny.en 모델(약 177MB)을 사이트 A에서 다운로드했더라도, 사이트 B에서 같은 모델을 사용하려면 처음부터 다시 내려받아야 합니다. 이는 브라우저의 'Cache Isolation(캐시 격리)' 정책 때문인데요, 보안과 프라이버시를 위해 출처(origin)별로 캐시를 분리하기 때문에 동일한 URL의 리소스라도 다른 사이트에서는 캐시 히트가 발생하지 않습니다.

실제로 Chrome DevTools의 Storage 패널을 열어보면, 같은 Wasm 런타임 파일(ort-wasm-simd-threaded.asyncify.wasm, 약 4.7MB)도 사이트마다 따로 저장되는 모습을 확인할 수 있습니다. 이는 사용자 디스크 공간 낭비일 뿐만 아니라, 네트워크 트래픽과 로딩 시간에도 악영향을 줍니다.

이 글에서는 이 문제를 해결하기 위해 제안된 Cross-Origin Storage API의 개념과, Transformers.js에서 실험적으로 적용하는 방법을 상세히 살펴보겠습니다.

Cross-Origin Storage API architecture diagram showing shared cache across different origins for AI model files Coding Session Visual

Cross-Origin Storage API: 해시 기반의 공유 캐시

Cross-Origin Storage(COS) API는 navigator.crossOriginStorage라는 새로운 인터페이스를 통해 출처 간(Cross-Origin) 파일 저장 및 공유를 가능하게 합니다. 여기서 핵심은 파일 식별자로 URL이 아닌 **암호학적 해시(SHA-256)**를 사용한다는 점입니다.

기본 동작 흐름

// 1. 해시 값 준비 (SHA-256)
const hash = {
  algorithm: 'SHA-256',
  value: '8f434346648f6b96df89dda901c5176b10a6d83961dd3c1ac88b59b2dc327aa4',
};

try {
  // 2. COS에서 파일 조회 시도
  const handle = await navigator.crossOriginStorage.requestFileHandle(hash);
  // 캐시 히트! 바로 Blob으로 읽어서 사용
  const fileBlob = await handle.getFile();
  console.log('COS 캐시 사용 성공!', fileBlob.size, 'bytes');
} catch {
  // 3. 캐시 미스 -> 네트워크에서 다운로드 후 COS에 저장
  const fileBlob = await fetch('https://cdn.example.com/model.onnx')
    .then(r => r.blob());
  const handle = await navigator.crossOriginStorage.requestFileHandle(
    hash,
    { create: true, origins: '*' }  // 모든 출처에서 접근 가능
  );
  const writableStream = await handle.createWritable();
  await writableStream.write(fileBlob);
  await writableStream.close();
  console.log('COS에 저장 완료! 다음 방문자는 이 파일을 재사용합니다.');
}

접근 제어: origins 옵션

COS는 모든 파일을 무조건 공유하지 않도록 origins 옵션을 제공합니다.

origins동작사용 예시
'*'전역 공유. 모든 출처에서 해시로 조회 가능공개 AI 모델 가중치, 공용 Wasm 런타임
['https://app1.example.com', 'https://app2.example.com']특정 출처만 접근 가능회사 내부 전용 모델, 독점 라이브러리
생략(기본값)동일 사이트(same-site) 내에서만 공유조직 내 서브도메인 간 공유 리소스

중요한 규칙: 한 번 '*'(전역)로 저장된 파일은 이후에 origins를 좁힐 수 없습니다. 반대로, 특정 출처만 허용한 파일은 나중에 더 넓은 범위로 업그레이드할 수 있습니다. 이는 악의적인 사이트가 공용 파일을 감추는 것을 방지하기 위함입니다.

무결성 보장

COS는 파일 저장 시 해시를 검증합니다. 쓰기 작업 중 데이터가 선언된 해시와 일치하지 않으면 에러가 발생합니다. 따라서 COS에서 읽은 파일은 항상 기대한 바이트 그대로임을 보장받을 수 있습니다. 이는 CDN에서 다운로드한 모델 가중치를 별도로 검증할 필요가 없어짐을 의미합니다.

프라이버시 고려 사항

출처 간 공유 캐시는 '이 파일이 캐시되어 있는가'를 통해 사용자의 방문 이력을 유추할 수 있는 사이드 채널 공격 가능성이 있습니다. COS는 이 문제를 두 가지 방식으로 완화합니다:

  1. origins 필드: 민감한 리소스는 '*'로 저장하지 않도록 개발자에게 권장
  2. 가용성 게이팅(Availability Gating): 전역 파일이라도 충분히 많은 출처에서 접근되지 않으면 존재 여부를 확인시켜 주지 않음 (파일이 없을 때와 동일한 에러 반환)

따라서 COS 조회 실패는 '파일이 없다'는 확정적인 의미가 아니라 '지금은 알려줄 수 없다'는 의미일 수도 있습니다. 앱은 항상 실패 시 네트워크 폴백(fallback)을 구현해야 합니다.

Cloud infrastructure diagram illustrating how Cross-Origin Storage reduces redundant downloads of Wasm runtime and model weights Programming Illustration

Transformers.js에서 COS 적용하기

Transformers.js 라이브러리는 이미 COS 실험 지원을 PR #1549에 도입했습니다. 사용법은 매우 간단합니다.

1. opt-in 플래그 설정

import { env, pipeline } from "https://cdn.jsdelivr.net/npm/@huggingface/transformers@4.2.0";

// 👇 Cross-Origin Storage 캐시 백엔드 활성화 (실험적)
env.experimental_useCrossOriginStorage = true;

const asr = await pipeline(
  'automatic-speech-recognition',
  'Xenova/whisper-tiny.en',
  { device: 'webgpu' }
);

const result = await asr('jfk.wav');
console.log(result);

experimental_ 접두사는 의도적입니다. 아직 표준화되지 않은 API이며, 주요 버전 업데이트 없이 변경될 수 있음을 의미합니다.

2. 동작 방식

플래그가 설정되면 Transformers.js는 Xet-추적 모델 파일(대용량 ONNX 가중치 파일)의 SHA-256 해시를 자동으로 계산하여 navigator.crossOriginStorage의 키로 사용합니다.

  • COS에 파일이 이미 존재하는 경우: 네트워크 요청 없이 즉시 로드
  • COS에 파일이 없는 경우: 일반 다운로드 후 COS에 저장 (다른 출처의 다음 방문자가 재사용)

3. 모델 레지스트리와의 연계

Transformers.js의 ModelRegistry.is_pipeline_cached() API는 COS와 직접 통합되어 있어, 사용자 캐시에 어떤 모델이 있는지 확인한 후 최적의 모델을 선택하는 전략을 구현할 수 있습니다.

// 사용자 COS에 whisper-tiny, medium, large-v3 중 어떤 것이 캐시되어 있는지 확인
const cachedModel = await ModelRegistry.is_pipeline_cached([
  'Xenova/whisper-tiny.en',
  'Xenova/whisper-medium.en',
  'Xenova/whisper-large-v3'
]);

// 캐시된 가장 큰 모델을 선택 (더 정확한 결과)
if (cachedModel) {
  const pipeline = await createPipeline(cachedModel);
  // ...
}

4. 실제 효과

두 개의 다른 출처(예: https://googlechrome.github.iohttps://rawcdn.rawgit.net)에서 COS를 활성화한 Transformers.js 앱을 실행하면, 첫 번째 사이트에서 다운로드한 177MB의 Whisper 모델이 두 번째 사이트에서는 밀리초 단위로 로드됩니다. Wasm 런타임(4.7MB)도 동일하게 공유됩니다.

5. 주의사항 및 한계

  • 브라우저 네이티브 미지원: 현재 COS API는 어떤 브라우저에도 네이티브 구현되어 있지 않습니다. 실험하려면 Chrome 확장 프로그램 Cross-Origin Storage Extension을 설치해야 합니다.
  • 폴백 안전성: 확장 프로그램이 설치되지 않은 환경에서는 env.experimental_useCrossOriginStorage = true 설정이 무시되고 기존 Cache API로 폴백됩니다. 따라서 프로덕션에 적용해도 사이드 이펙트는 없습니다.
  • 프라이버시 리스크: 전역 공유 파일이 너무 적은 사이트에서만 사용되면 사용자 식별에 악용될 가능성이 있습니다. Chrome 팀은 이에 대한 구체적인 완화 방안을 계속 연구 중입니다.

Network topology visualization showing multiple web origins connecting to a shared Cross-Origin Storage pool Software Concept Art

국내 개발 생태계에서의 적용 맥락

국내 웹 서비스 환경에서 COS API가 특히 유용할 수 있는 시나리오는 다음과 같습니다.

  1. AI 기반 문서 편집기: 네이버, 카카오, 토스 등에서 제공하는 AI 문서 요약, 맞춤법 검사, 이미지 생성 기능. 사용자가 여러 서비스를 이용할 때 같은 AI 모델을 중복 다운로드하는 비효율을 줄일 수 있습니다.
  2. 대규모 SaaS 플랫폼: 하나의 기업이 여러 서브도메인(예: service1.company.com, service2.company.com)에서 동일한 AI 모델을 사용하는 경우, COS의 기본 same-site 공유 정책으로 쉽게 최적화 가능합니다.
  3. 공공 CDN 연계: 한국의 경우 cdn.jsdelivr.net이나 unpkg 같은 글로벌 CDN에 의존하기보다, 국내 CDN(KT Cloud, Naver Cloud 등)과 COS를 함께 사용하여 트래픽 비용을 절감할 수도 있습니다.

이 기술의 한계 또는 주의사항

  • 표준화 지연 가능성: COS는 아직 초기 제안 단계입니다. W3C 표준화 과정에서 API 디자인이 크게 바뀌거나 채택되지 않을 가능성도 있습니다.
  • 확장 프로그램 의존성: 현재 실험은 확장 프로그램을 통해서만 가능하며, 일반 사용자에게 확장 프로그램 설치를 요구하기는 현실적으로 어렵습니다.
  • 보안 감사 필요: 출처 간 공유 캐시는 새로운 공격 표면을 만들 수 있습니다. 특히 해시 충돌이나 타이밍 공격에 대한 면밀한 검토가 필요합니다.

다음 단계 학습 방향

  1. 직접 실험해보기: Cross-Origin Storage Extension을 설치하고, 공식 데모 페이지에서 COS 동작을 확인해보세요.
  2. Transformers.js 기여: PR #1549의 코드를 분석하고, 자신의 프로젝트에 COS 백엔드를 통합하는 방법을 연구해보세요.
  3. 관련 표준 문서 읽기: Explainer 문서WICG 논의를 팔로우하여 최신 논의를 따라가세요.
  4. 유사 기술 비교: Cache API, Origin Private File System(OPFS), Service Worker 캐시와 COS의 차이점을 이해하면 더 풍부한 아키텍처 결정을 내릴 수 있습니다.

근거 자료: Hugging Face 블로그 - Cross-Origin Storage API 소개


함께 보면 좋은 글

본 콘텐츠는 신뢰할 수 있는 출처를 바탕으로 AI 도구를 활용하여 초안이 작성되었으며, 편집자의 검토를 거쳐 발행되었습니다. 전문가의 조언을 대체하지 않습니다.