Chrome Built-in AI — 브라우저에서 Word·Excel·PPT·PDF를 AI로 요약하기

9 min read
Chrome Built-in AISummary APIofficeParserJavaScript브라우저 AI
Chrome Built-in AI — 브라우저에서 Word·Excel·PPT·PDF를 AI로 요약하기

브라우저가 AI 요약 엔진이 된다

서버를 쓰지 않고, API 키도 없이, 순수하게 브라우저 안에서 Word·Excel·PPT·PDF 파일을 AI로 요약하는 게 가능해졌다. Chrome의 내장 AI 기능인 Summary API와 오피스 파일 파서 officeParser를 조합하면 된다.

흐름은 단순하다.

사용자가 파일 선택 → officeParser가 텍스트 추출 → Chrome Summary API가 요약

서버 왕복 없이 사용자 기기에서 전부 처리된다. 문서가 외부 서버로 전송되지 않으므로 민감한 업무 문서에도 쓸 수 있다.

[💡 잠깐! 이 용어는?] Chrome Built-in AI: Chrome 브라우저에 Gemini Nano 모델을 내장한 기능. window.Summarizer, window.LanguageModel 등의 API로 접근한다. 별도 모델 다운로드 없이 브라우저가 설치 시 함께 제공하는 모델을 활용한다.


준비: officeParser 설치

officeParser는 Node.js 기반 라이브러리지만, Vite 등으로 번들하면 브라우저에서도 동작한다.

officeParser 설치
npm install officeparser

지원 포맷:

파일 형식확장자파싱 결과
Word.docx본문 텍스트
Excel.xlsx시트별 셀 데이터
PowerPoint.pptx슬라이드별 텍스트
PDF.pdf페이지별 텍스트

officeParser가 핵심을 처리해준다. 반환값은 형식에 따라 조금씩 다르다.


Summary API 기본 사용법

Chrome의 window.Summarizer API는 긴 텍스트를 짧게 요약해준다.

src/summarizer.js — Summary API 초기화
async function createSummarizer(context) {
  const available = await window.Summarizer.availability();
 
  if (available === 'unavailable') {
    throw new Error('Summary API를 사용할 수 없습니다.');
  }
 
  const summarizer = await window.Summarizer.create({
    type: 'tldr',
    length: 'long',
    sharedContext: context,
  });
 
  return summarizer;
}

[💡 잠깐! 이 용어는?] sharedContext: 요약 전에 모델에 전달하는 배경 정보. "이건 회의록이다", "이건 재무 보고서다" 같은 맥락을 주면 요약 품질이 높아진다.

type: 'tldr'는 "너무 길어서 안 읽음(Too Long Didn't Read)" 형식의 요약을 의미한다. 핵심만 뽑아내는 데 적합하다. length: 'long'은 요약문 자체의 길이 옵션이다.

요약 실행:

src/summarizer.js — 텍스트 요약 실행
async function summarizeText(text, summarizer) {
  const result = await summarizer.summarize(text, {
    context: '이 문서의 핵심 내용을 요약해주세요.',
  });
  return result;
}

파일 형식별 텍스트 추출

Word (.docx)

Word 문서는 가장 단순하다. parseOfficeAsync가 전체 본문을 하나의 문자열로 반환한다.

src/parsers/docx.js — Word 파일 텍스트 추출
import { parseOfficeAsync } from 'officeparser';
 
async function extractFromDocx(file) {
  const data = await parseOfficeAsync(file);
  return data.toText();
}

PDF (.pdf)

PDF도 비슷하다. 페이지 순서대로 텍스트가 이어진다.

src/parsers/pdf.js — PDF 텍스트 추출
import { parseOfficeAsync } from 'officeparser';
 
async function extractFromPdf(file) {
  const data = await parseOfficeAsync(file);
  return data.toText();
}

PowerPoint (.pptx)

PPT는 슬라이드별로 데이터가 분리된다. 슬라이드 번호를 붙여서 컨텍스트를 살리는 게 좋다.

src/parsers/pptx.js — PowerPoint 슬라이드별 추출
import { parseOfficeAsync } from 'officeparser';
 
async function extractFromPptx(file) {
  const data = await parseOfficeAsync(file);
  const slides = data.slides || [];
 
  return slides
    .map((slide, index) => `[슬라이드 ${index + 1}]\n${slide.text}`)
    .join('\n\n');
}

슬라이드 헤더를 붙이면 Summary API가 "3번째 슬라이드는 결론 파트"라는 구조를 인식하고 요약에 반영한다.

Excel (.xlsx)

Excel은 다른 형식과 다르게 접근해야 한다. 행/열 데이터를 그대로 넘기면 AI가 맥락을 잃는다. CSV 형태로 변환해서 넘기는 게 효과적이다.

src/parsers/xlsx.js — Excel을 CSV 형식으로 변환
import { parseOfficeAsync } from 'officeparser';
 
async function extractFromXlsx(file) {
  const data = await parseOfficeAsync(file);
  const sheets = data.sheets || [];
 
  return sheets
    .map((sheet) => {
      const header = `[시트: ${sheet.name}]`;
      const rows = sheet.rows
        .map((row) => row.cells.map((cell) => cell.value ?? '').join(','))
        .join('\n');
      return `${header}\n${rows}`;
    })
    .join('\n\n');
}

비유하면 스프레드시트는 표이고, AI는 이야기를 읽는 독자다. 표를 그대로 주면 독자가 헷갈린다. "1행은 헤더, 2행부터 데이터"라는 구조를 CSV로 명확히 보여줘야 한다.


전체 통합: 파일 타입 자동 감지

src/doc-summarizer.js — 파일 형식 자동 감지 및 요약
import { parseOfficeAsync } from 'officeparser';
 
const FILE_CONTEXTS = {
  docx: 'Word 문서입니다. 본문의 주요 내용을 요약해주세요.',
  pdf: 'PDF 문서입니다. 핵심 정보를 추출해주세요.',
  pptx: '프레젠테이션 파일입니다. 각 슬라이드의 핵심 메시지를 요약해주세요.',
  xlsx: '스프레드시트 데이터입니다. 데이터의 주요 패턴과 인사이트를 요약해주세요.',
};
 
async function extractText(file) {
  const ext = file.name.split('.').pop().toLowerCase();
  const data = await parseOfficeAsync(file);
 
  if (ext === 'xlsx') {
    const sheets = data.sheets || [];
    return sheets
      .map((sheet) => {
        const rows = sheet.rows
          .map((row) => row.cells.map((c) => c.value ?? '').join(','))
          .join('\n');
        return `[시트: ${sheet.name}]\n${rows}`;
      })
      .join('\n\n');
  }
 
  if (ext === 'pptx') {
    const slides = data.slides || [];
    return slides
      .map((slide, i) => `[슬라이드 ${i + 1}]\n${slide.text}`)
      .join('\n\n');
  }
 
  return data.toText();
}
 
async function summarizeDocument(file) {
  const ext = file.name.split('.').pop().toLowerCase();
  const context = FILE_CONTEXTS[ext] ?? '문서의 핵심 내용을 요약해주세요.';
 
  const text = await extractText(file);
 
  const summarizer = await window.Summarizer.create({
    type: 'tldr',
    length: 'long',
    sharedContext: context,
  });
 
  const summary = await summarizer.summarize(text, { context });
  return summary;
}

파일 확장자에 따라 컨텍스트도 다르게 넘긴다. 같은 문서라도 "이건 프레젠테이션이야"라고 알려주는 것과 그냥 텍스트로 넘기는 건 요약 결과가 다르다.


알려진 제한 사항

제한내용
파일 크기대용량 파일에서 QuotaExceededError 발생. Excel 기준 200행은 OK, 1000행은 실패
브라우저 지원Chrome 138+ 필요. Firefox·Safari 미지원
언어영어 요약 품질이 가장 높음. 한국어도 동작하나 결과 품질이 상대적으로 낮음
모델 크기Gemini Nano는 경량 모델. 복잡한 수식·도표 해석은 GPT-4급과 차이 있음

QuotaExceededError는 컨텍스트 윈도우 초과다. 큰 파일은 청크 단위로 나눠서 각각 요약한 뒤 합치는 방식으로 우회할 수 있다.

src/chunked-summarizer.js — 대용량 파일 청크 요약
async function summarizeInChunks(text, summarizer, chunkSize = 3000) {
  const chunks = [];
  for (let i = 0; i < text.length; i += chunkSize) {
    chunks.push(text.slice(i, i + chunkSize));
  }
 
  const chunkSummaries = await Promise.all(
    chunks.map((chunk) => summarizer.summarize(chunk))
  );
 
  const combined = chunkSummaries.join('\n\n');
  return summarizer.summarize(combined, {
    context: '아래는 문서의 각 부분을 요약한 내용입니다. 전체를 통합 요약해주세요.',
  });
}

정리

  • officeParser로 Word·Excel·PPT·PDF를 텍스트로 추출할 수 있다.
  • Chrome window.Summarizer.create()sharedContexttype: 'tldr'를 설정하면 브라우저 내 AI 요약이 동작한다.
  • Excel은 CSV 형식으로 변환, PPT는 슬라이드 번호를 붙여 넘기면 요약 품질이 높아진다.
  • 대용량 파일은 청크로 나눠 2단계 요약으로 우회한다.
  • 서버 없이 브라우저에서 전부 처리되므로 민감한 문서에도 적용할 수 있다.

Summary API는 아직 실험 단계지만, 서버리스 AI 요약이 필요한 내부 도구나 프로토타입에는 충분히 써볼 만하다.


참고:

관심 있을 만한 포스트

Chrome Built-in AI — LanguageModel API로 이미지에서 텍스트 추출하기

Chrome의 LanguageModel API를 사용해 서버 없이 브라우저에서 이미지 OCR을 구현하는 방법과 실제 테스트 결과를 정리한다.

Chrome Built-in AILanguageModel

Bun v1.3.12 — 브라우저 자동화와 인프로세스 Cron이 기본 내장됐다

Playwright 없이 브라우저를 제어하는 Bun.WebView, 그리고 서버 재시작 없이 작업을 스케줄링하는 Bun.cron의 기술적 구조.

Bun브라우저 자동화

Zustand 소프트 삭제 — enumerable:false로 컴포넌트 크래시 없이 처리하기

JavaScript property descriptor의 enumerable 플래그를 활용해 삭제된 엔티티를 투명하게 처리하는 Zustand 패턴을 소개한다.

Zustand상태 관리

JavaScript 이미지 프리로딩 — 5가지 방법 비교

new Image, link preload, hidden div, Cache API, fetch — 각 프리로딩 방식의 장단점과 상황별 선택 기준을 정리한다.

JavaScript성능

JavaScript 물리 엔진 만들기 — 100줄로 구현하는 2D 물리 시뮬레이션

벡터 연산, 원 충돌 감지, 충격량 기반 응답까지 순수 JavaScript로 2D 물리 엔진을 직접 만든다.

Physics EngineCanvas

Native JSON Modules — 번들러 없이 JSON을 import하는 시대

Import Attributes와 함께 표준이 된 native JSON module. 어떻게 동작하고, 기존 번들러 방식과 뭐가 다른지 정리했다.

JavaScriptESM

Babel 7.29.0 — 10년 역사의 마지막 마이너, 그리고 8 RC1

2026년 1월 31일, Babel 7의 마지막 마이너 릴리스가 공개됐다. 이 버전이 갖는 역사적 의미와 Babel 8 RC1의 핵심 변화를 정리한다.

BabelJavaScript

Error.isError() — realm을 넘나드는 안전한 에러 검사 API

instanceof Error가 iframe과 worker에서 실패하는 이유, 그리고 이를 근본적으로 해결하는 Error.isError()의 동작 원리를 정리한다.

JavaScriptError.isError