Chrome Built-in AI 실전 가이드 — Summarizer·Translator·Writing Assistance를 서버 비용 없이 붙이기
Chrome 138(2025년 6월)에서 Summarizer, Translator, LanguageDetector가 stable로 출시됐고, Chrome 148에서는 LanguageModel(Prompt API)까지 안정화됐습니다. Google I/O 2026에서는 "에이전틱 웹(Agentic Web)"이라는 키워드와 함께 Gemma 197M 초경량 모델도 추가됐고요. 즉, Chrome이 Gemini Nano 모델을 브라우저 안에 직접 탑재했고, 표준 Web API 패턴 그대로 호출할 수 있습니다. API 키도, 서버도, 토큰 비용도 없이요.
실제로 붙여 보면 뉴스 요약 위젯은 초당 수십 KB의 텍스트를 클라우드 왕복 없이 300ms 안팎에 처리하고, 다국어 커뮤니티 댓글 자동 번역도 감지·번역까지 한 번의 사용자 인터랙션 안에 끝납니다. 이 글에서는 가용성 확인부터 폴백 처리, 실제 요약·번역·글쓰기 시나리오 구현까지 프로덕션에 넣을 때 실제로 걸리는 지점들을 정리합니다.
핵심 개념
API 구조: 두 계층으로 나뉩니다
Chrome Built-in AI는 크게 두 레이어로 나눠볼 수 있습니다.
| 레이어 | API | 역할 |
|---|---|---|
| 범용 (Low-level) | LanguageModel (Prompt API) |
자유 형식 프롬프트, 멀티모달 입력, JSON 출력 |
| 태스크 특화 (High-level) | Summarizer, Translator, LanguageDetector, Writer, Rewriter, Proofreader |
특정 작업에 최적화된 고수준 API |
진입점 이야기: window.ai → navigator.ai → 정적 클래스
Origin Trial 초창기(Chrome 127 전후)에는 window.ai.summarizer.create() 같은 형태였습니다. 이후 Chrome 131~137 사이에 진입점이 navigator.ai로 옮겨졌고(대부분 문서·데모에서 이 표기가 쓰입니다), stable 승격 과정에서 각 태스크 API가 전역 정적 클래스로도 노출되는 방식이 표준으로 자리잡았습니다.
정리하면 이렇습니다.
window.ai.*— 초기 프로토타입 문법. 더 이상 쓰지 마세요. 최신 Chrome에서는 동작하지 않습니다.navigator.ai.summarizer.create()— Origin Trial 시기 문서에 광범위하게 남아 있고, 여전히 동작하는 경로가 있습니다.Summarizer.create()(정적 클래스) — 현재 stable 스펙의 권장 방식. 이 글의 모든 예시는 이 방식으로 통일합니다.
새로 작성하는 코드는 정적 클래스 방식으로 쓰고, 레거시 코드에서 navigator.ai.*를 발견하면 마이그레이션 대상으로 표시해 두세요.
availability() — 가장 먼저 확인해야 할 것
모든 API는 사용 전에 반드시 가용성 확인이 필요합니다. 반환값은 네 가지입니다.
const availability = await Summarizer.availability();
// 'available' — 모델이 이미 다운로드되어 바로 사용 가능
// 'downloadable' — 사용 가능하지만 모델 다운로드 필요
// 'downloading' — 현재 다운로드 진행 중
// 'unavailable' — 지원 안 됨 (하드웨어 미충족 또는 Chrome 미지원)여기서 자주 헷갈리는 부분 하나. 'downloadable' 상태에서 create()를 호출하면 자동으로 다운로드가 시작되고 완료된 뒤 세션이 반환됩니다. 별도 트리거는 필요 없습니다. 대신 다운로드 진행 상황을 사용자에게 보여주려면 monitor 콜백으로 downloadprogress 이벤트를 잡아야 합니다. 이미 다른 탭에서 다운로드 중('downloading')이라면 create()가 완료를 대기하고 이어서 세션을 반환합니다.
Summarizer API — 요약의 세 가지 차원
Summarizer.create()에는 세 가지 옵션이 있고, 이 조합이 출력 스타일을 결정합니다.
const summarizer = await Summarizer.create({
type: 'key-points', // 'tldr' | 'teaser' | 'headline' | 'key-points'
format: 'markdown', // 'markdown' | 'plain-text'
length: 'short', // 'short' | 'medium' | 'long'
});| type | 출력 형태 | 적합한 용도 |
|---|---|---|
key-points |
핵심 포인트 목록 | 블로그·뉴스 요약 위젯 |
tldr |
한두 문장 압축 | 이메일 스레드, 채팅 요약 |
teaser |
흥미 유발형 도입 | SNS 미리보기, 카드 UI |
headline |
짧은 제목 형식 | SEO 메타 제목 생성 |
모델 다운로드가 필요한 경우 진행률을 표시할 수 있습니다.
const summarizer = await Summarizer.create({
type: 'key-points',
format: 'markdown',
length: 'short',
monitor(m) {
m.addEventListener('downloadprogress', (e) => {
console.log(`모델 다운로드: ${Math.round(e.loaded * 100)}%`);
});
},
});Translator + LanguageDetector — 조합이 핵심
번역 API는 단독으로도 쓸 수 있지만, 언어 자동 감지와 함께 쓸 때 진가가 발휘됩니다.
const detector = await LanguageDetector.create();
const results = await detector.detect(userInput);
// results[0].detectedLanguage → 'ko', 'en', 'ja' 등 BCP 47 코드
// results[0].confidence → 0~1 신뢰도 점수
const translator = await Translator.create({
sourceLanguage: results[0].detectedLanguage,
targetLanguage: 'en',
});
const translated = await translator.translate(userInput);Translator는 첫 사용 시 언어 쌍별로 별도 번역 전용 모델을 추가 다운로드합니다. Gemini Nano와 분리된 모델이라서 새 쌍을 처음 쓸 때마다 초기 대기가 발생할 수 있습니다.
LanguageModel (Prompt API) — 자유도가 높은 범용 선택지
태스크 API로 해결이 안 되는 경우에는 Prompt API로 직접 프롬프트를 쏠 수 있습니다. initialPrompts로 시스템 컨텍스트를 주입하고, promptStreaming()으로 스트리밍 응답도 받을 수 있습니다.
const session = await LanguageModel.create({
initialPrompts: [
{
role: 'system',
content: '당신은 코드 리뷰를 도와주는 어시스턴트입니다. 한국어로 답하세요.',
},
],
});
const result = await session.prompt('이 함수의 문제점을 알려줘: ' + codeSnippet);
const stream = session.promptStreaming('이 코드를 리팩터링해줘: ' + codeSnippet);
for await (const chunk of stream) {
outputElement.textContent += chunk;
}버전 주의: Chrome 148 기준
promptStreaming()은 델타(증분) 청크를 방출합니다. 이 글의 예시는 이 동작을 전제로outputElement.textContent += chunk방식으로 이어붙입니다. 다만 초기 Origin Trial 빌드에서는 누적 문자열을 방출한 이력이 있어, 배포 전 대상 Chrome 버전에서 실제 청크 형태를 한 번 로그로 찍어 확인하는 걸 권장합니다.
실전 적용
시나리오 1 — 뉴스·블로그 요약 위젯
가장 흔한 활용 패턴입니다. 긴 기사 아래에 "AI 요약 보기" 버튼을 달고, 클릭 시 요약을 생성합니다. 재사용 가능한 클래스로 한 번만 초기화하고, marked로 마크다운을 렌더링합니다.
import { marked } from 'marked';
class ArticleSummarizer {
#summarizer = null;
#initPromise = null;
async init() {
if (this.#summarizer) return true;
if (this.#initPromise) return this.#initPromise;
this.#initPromise = (async () => {
const availability = await Summarizer.availability();
if (availability === 'unavailable') return false;
this.#summarizer = await Summarizer.create({
type: 'key-points',
format: 'markdown',
length: 'short',
monitor(m) {
m.addEventListener('downloadprogress', (e) => {
document.querySelector('#download-progress').textContent =
`모델 준비 중... ${Math.round(e.loaded * 100)}%`;
});
},
});
return true;
})();
return this.#initPromise;
}
async summarize(articleText) {
if (!this.#summarizer) throw new Error('Summarizer not initialized');
return this.#summarizer.summarize(articleText);
}
}
const summarizer = new ArticleSummarizer();
document.querySelector('#summarize-btn').addEventListener('click', async () => {
const btn = document.querySelector('#summarize-btn');
const output = document.querySelector('#summary-output');
const articleText = document.querySelector('#article-content').textContent;
btn.disabled = true;
try {
const ready = await summarizer.init();
const summary = ready
? await summarizer.summarize(articleText)
: await fallbackToCloudSummarizer(articleText);
output.innerHTML = marked(summary);
} catch (err) {
console.error('요약 실패:', err);
output.textContent = '요약을 생성하지 못했습니다. 잠시 후 다시 시도해 주세요.';
} finally {
btn.disabled = false;
}
});init()은 캐시된 인스턴스가 있으면 즉시 반환하고, 동시 클릭에도 #initPromise가 중복 생성을 막습니다. try/catch/finally는 모델 로드 실패·할당량 초과·타임아웃을 흡수합니다.
시나리오 2 — 댓글 자동 감지 및 번역
다국어 커뮤니티에서 외국어 댓글이 올라올 때 "번역 보기" 버튼을 제공하는 패턴입니다. LanguageDetector는 모듈 수준 싱글턴으로 캐시해서 매번 재생성하지 않도록 합니다.
let detectorPromise = null;
function getDetector() {
if (!detectorPromise) detectorPromise = LanguageDetector.create();
return detectorPromise;
}
const translatorCache = new Map();
function getTranslator(sourceLanguage, targetLanguage) {
const key = `${sourceLanguage}->${targetLanguage}`;
if (!translatorCache.has(key)) {
translatorCache.set(
key,
Translator.create({ sourceLanguage, targetLanguage }),
);
}
return translatorCache.get(key);
}
async function translateComment(commentElement) {
const originalText = commentElement.dataset.originalText;
const targetLanguage = 'ko';
const detector = await getDetector();
const [{ detectedLanguage, confidence }] = await detector.detect(originalText);
if (confidence < 0.7) return;
if (detectedLanguage === targetLanguage) return;
const availability = await Translator.availability({
sourceLanguage: detectedLanguage,
targetLanguage,
});
if (availability === 'unavailable') {
return cloudTranslateFallback(originalText, detectedLanguage, targetLanguage);
}
const translator = await getTranslator(detectedLanguage, targetLanguage);
const translated = await translator.translate(originalText);
commentElement.querySelector('.translated-text').textContent = translated;
commentElement.querySelector('.translation-badge').hidden = false;
}시나리오 3 — 이메일 초안 생성과 톤 조정
Writer로 초안을 만들고 Rewriter로 다듬는 파이프라인입니다. Writer·Rewriter·Proofreader는 Chrome 137~148 구간의 Origin Trial 대상이므로, feature detection과 가용성 확인이 모두 필요합니다.
async function draftEmail({ keywords, context, tone = 'formal' }) {
if (!('Writer' in globalThis)) {
return cloudWriterFallback({ keywords, context, tone });
}
const availability = await Writer.availability();
if (availability === 'unavailable') {
return cloudWriterFallback({ keywords, context, tone });
}
const writer = await Writer.create({
tone, // 'formal' | 'neutral' | 'casual'
format: 'plain-text',
length: 'medium',
});
return writer.write(
`다음 키워드를 포함한 이메일 초안을 작성해줘: ${keywords}`,
{ context },
);
}
async function adjustTone(existingText, targetTone) {
if (!('Rewriter' in globalThis)) return existingText;
const availability = await Rewriter.availability();
if (availability === 'unavailable') return existingText;
const rewriter = await Rewriter.create({
tone: targetTone,
format: 'plain-text',
length: 'as-is', // Rewriter의 length는 'shorter' | 'as-is' | 'longer'
});
return rewriter.rewrite(existingText, {
context: '이메일 형식에 맞게 다시 작성해줘',
});
}
Rewriter의length는 스펙상'shorter' | 'as-is' | 'longer'세 값입니다. 원문 길이를 유지하고 싶다면'as-is'를 쓰세요.'same'은 유효한 값이 아닙니다.
시나리오 4 — Prompt API로 온보딩 챗봇
앱 상태를 initialPrompts에 주입해서 맥락 기반 도움말을 제공합니다. LanguageModel은 가장 하드웨어 요구가 큰 API이므로 availability() 확인과 세션 destroy()가 특히 중요합니다.
async function createOnboardingBot(userContext) {
const availability = await LanguageModel.availability();
if (availability === 'unavailable') {
return createCloudChatFallback(userContext);
}
const session = await LanguageModel.create({
initialPrompts: [
{
role: 'system',
content: `당신은 ${userContext.appName} 온보딩 어시스턴트입니다.
현재 사용자 상태:
- 플랜: ${userContext.plan}
- 완료한 단계: ${userContext.completedSteps.join(', ')}
- 현재 페이지: ${userContext.currentPage}
간결하고 친절하게 한국어로 답변하세요.`,
},
],
});
return {
async ask(question) {
// Chrome 148 기준: promptStreaming은 델타 청크를 방출합니다.
const stream = session.promptStreaming(question);
let response = '';
for await (const chunk of stream) {
response += chunk;
updateChatUI(response);
}
return response;
},
destroy() {
session.destroy(); // VRAM/메모리 해제
},
};
}장단점 분석
한눈에 보는 장단점
| 항목 | 내용 |
|---|---|
| 비용 | API 호출·토큰 과금 없음. 트래픽이 늘어도 한계 비용 $0 |
| 프라이버시 | 데이터가 로컬에서만 처리, 외부 서버로 전송되지 않음 |
| 오프라인 | 네트워크 없이도 동작 (모델 다운로드 완료 후) |
| 레이턴시 | 클라우드 왕복 없이 즉각 응답 (모델 로드 완료 시) |
| 통합 난이도 | Promise/async-await/스트리밍 표준 패턴, 인증 불필요 |
| 제약 | 내용 |
|---|---|
| 브라우저 한정 | Chrome 전용. Firefox·Safari·Edge 미지원 |
| 하드웨어 요구 (Prompt API·Writer·Rewriter 기준) | Gemini Nano 모델용 여유 스토리지 22GB 이상, VRAM 4GB 이상 GPU 또는 RAM 16GB + CPU 4코어 이상. 태스크 API 중 Summarizer는 동일 Gemini Nano 위에서 동작하므로 요구사항이 같지만, Translator·LanguageDetector는 훨씬 작은 전용 모델을 쓰기 때문에 스토리지·메모리 요구가 낮습니다. |
| 모바일 미지원 | 대부분 API가 데스크탑 전용. Android Chrome 미지원 |
| 초기 다운로드 | 첫 사용 시 수십~수백 MB 모델 다운로드 대기 |
| 언어 지원 | Translator·Summarizer는 한국어(ko) 포함 영어·스페인어·일본어·독일어·프랑스어·중국어 등 주요 언어를 지원합니다(Chrome 138 stable부터). Writer·Rewriter는 Origin Trial 단계에서 영어 중심으로 확장 중이며, 한국어 품질은 아직 편차가 있어 프로덕션 전 검증이 필요합니다. |
| 할루시네이션 | 소형 모델 특성상 부정확한 응답 가능. 고위험 도메인은 검증 레이어 필요 |
| 정책 종속 | Google 생성 AI 사용 정책 적용, 콘텐츠 모더레이션 Google 통제 |
실무에서 자주 만나는 실수들
1. availability() 생략
create()를 바로 호출하면 모델이 없을 때 예외가 터집니다. 항상 availability()로 상태를 확인하고 분기 처리하세요.
2. 폴백 없이 배포
현재 Chrome 사용자 중에서도 하드웨어 요구사항을 충족하는 비율은 전부가 아닙니다. 'unavailable'일 때 클라우드 API로 전환되는 구조가 없으면 해당 사용자에게 기능이 통째로 사라집니다.
3. 세션 destroy() 누락
LanguageModel.create()로 만든 세션은 VRAM/메모리를 점유합니다. 여러 탭에서 같은 API를 쓰면 리소스 경쟁이 생길 수 있어서, 세션을 다 쓴 후엔 session.destroy()를 호출하세요.
4. Origin Trial 상태 무시
Writer, Rewriter, Proofreader는 Chrome 137~148 한정 Origin Trial입니다. 배포 전에 현재 Trial 기간이 유효한지 확인하고, 'Writer' in globalThis 같은 feature detection을 함께 두세요.
5. Detector·Translator 매 호출 재생성
LanguageDetector.create()나 Translator.create()를 함수 호출마다 새로 부르면 언어 쌍별 모델 로드 비용이 반복 발생합니다. 모듈 수준 싱글턴이나 Map 캐시로 재사용하세요.
어떤 상황에 쓰면 좋을까
세 갈래 모두 결국 Built-in AI + 클라우드 폴백 조합으로 수렴합니다. 폴백을 언제·어느 API로 붙일지의 우선순위만 달라집니다.
마치며
Chrome Built-in AI는 프론트엔드 개발자가 서버 없이 AI 기능을 제품에 넣을 수 있는 현실적인 첫 번째 선택지가 됐습니다. 아직 Chrome 전용이고 하드웨어 요구사항이 높다는 한계는 분명하지만, 데이터 프라이버시가 중요하거나 클라우드 API 비용이 부담스러운 유스케이스에서는 지금 당장 써볼 가치가 있습니다.
핵심을 다시 정리하면 이렇습니다.
availability()→create()→ 사용 →destroy()패턴을 지키기'unavailable'일 때 클라우드 폴백을 반드시 준비하기- Detector·Translator·Summarizer 인스턴스는 캐시해서 초기 로드 비용을 아끼기
- Origin Trial 상태(Writer·Rewriter·Proofreader)를 배포 전에 확인하기
지금 바로 시작해 보고 싶다면 이 순서를 추천합니다.
- Chrome DevTools에서
chrome://flags/#prompt-api-for-gemini-nano활성화 후 콘솔에서await Summarizer.availability()결과 확인 - Chrome AI Playground(
chrome.dev/web-ai-demos/)에서 각 API 직접 체험 - 기존 프로젝트의 텍스트 처리 부분 한 곳만 골라서
Summarizer또는Translator파일럿 적용 후 폴백 포함해서 배포
W3C Web Machine Learning Working Group에서 Translator·Summarizer·Writer API의 표준화 논의가 진행 중이고, Edge는 Chromium 기반이라 실질적 이식이 상대적으로 빠를 것으로 예상됩니다. Firefox는 자체 온디바이스 번역(Firefox Translations)을 이미 운영 중이라 API 통합 논의가 남아 있고, Safari의 경우 아직 공식 로드맵은 없습니다. 즉, 지금은 Chrome 한정이지만 표준화 트랙에 올라온 API 형태로 익혀 두면 이후 다른 브라우저 대응 코스트가 낮습니다.
참고 자료
- AI on Chrome — Built-in AI 공식 개요
- Built-in AI APIs 전체 목록
- Prompt API (LanguageModel) 상세 가이드
- Summarizer API 가이드
- Translator API 가이드
- Writer API 가이드
- Rewriter API 가이드
- Proofreader API 가이드
- Language Detection 가이드
- Built-in AI 시작하기
- Google I/O 2026 Chrome 15대 업데이트
- Build new features using built-in AI — I/O 2026
- New in Chrome 138
- Exploring Chrome's Built-In AI APIs: A Hands-On Guide
- Running LLMs in the Browser: WebGPU, Transformers.js, and Chrome's Built-in AI
- GoogleChrome/modern-web-guidance (GitHub)