본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 21. 06:48

사용자 브라우저에서 실행되는 무료 AI로 웹 앱을 강화하는 방법

요약

Chrome 브라우저에 내장된 Gemini Nano와 Prompt API를 활용하여 서버 비용 없이 온디바이스 AI 기능을 구현하는 방법을 소개합니다. 실제 사례로 텍스트를 Mermaid 다이어그램 코드로 변환하는 웹 앱 구현 과정을 다룹니다.

핵심 포인트

  • Chrome 내장 Gemini Nano를 통해 API 키와 추론 비용 없는 AI 구현 가능
  • Prompt API를 사용하여 브라우저 내에서 로컬 모델에 직접 접근
  • 데이터가 브라우저를 벗어나지 않아 보안 및 프라이버시 강화
  • availability() 함수를 통한 모델 상태(사용 가능, 다운로드 중 등) 관리 필수

언제까지는 구현할 수 없었던 기능의 한 종류가 있었습니다. 바로 언어 모델이 필요한 모든 것이었습니다. API 키를 연결하고, 토큰당 비용을 지불했으며, 사용자가 입력하는 모든 프롬프트는 다른 사람의 서버로 전송되었습니다. 작은 공개 도구의 경우, 그 계산만으로도 아이디어가 시작하기도 전에 무산되는 경우가 많았습니다.

상황이 바뀌었습니다. Chrome의 최신 버전에는 언어 모델인 Gemini Nano가 탑재되어 있으며, 이를 Prompt API를 통해 모든 웹 페이지에 노출하고 있습니다. 이 모델은 사용자의 장치에서 실행됩니다. API 키도 필요 없고, 추론 비용(inference bill)도 없으며, 데이터가 브라우저를 벗어나지 않습니다.

저희는 이것을 실제 작동하는 도구, 즉 무료 Mermaid 다이어그램 에디터에 적용했습니다. 사용자가 일반 영어로 다이어그램을 설명하면 브라우저가 자동으로 Mermaid 코드를 작성해 줍니다. 이 게시물은 개발자 버전의 이야기입니다. 즉, API가 실제로 어떻게 작동하는지, 작은 온디바이스(on-device) 모델을 신뢰할 수 있게 만드는 코드 방법, 그리고 얻는 것과 포기하는 것에 대한 솔직한 계산을 다룹니다.

2026년 '브라우저 내 AI'의 의미

중요한 단어는 ‘내장(built-in)’입니다. 이것은 WebGPU에 4GB 모델을 다운로드하여 직접 실행하는 것을 의미하지 않습니다. 이 모델은 Chrome과 함께 제공되며, 사용자는 작은 표준 트랙 JavaScript API를 통해 접근합니다.

Chrome 148 기준으로 Prompt API는 웹 페이지용으로 안정화되었습니다 (Chrome 138부터 확장 프로그램에 사용할 수 있었습니다). 이것은 증가하는 내장 API 제품군 중 범용적인 멤버입니다:

  • Prompt API (LanguageModel): 일반 자연어 프롬프팅이며, 현재 멀티모달(text 외 이미지 및 오디오 입력도 가능)을 지원합니다.
  • Summarizer, Writer, Rewriter, Proofreader: 작업별 텍스트-투-텍스트 기능입니다.
  • TranslatorLanguage Detector: 전문가 모델 기반이며 데스크톱 전용입니다.

Prompt API는

// 먼저 기능 탐지(Feature-detect)를 수행합니다. 오래된 브라우저에는 이 기능이 전혀 없을 것입니다.
if ('LanguageModel' in self) {
const status = await LanguageModel.availability();
...

이것이 전부입니다. API 키도, SDK도, 네트워크 호출도 필요 없습니다. 오리진(origin)에서 모델을 처음 사용할 때 Chrome이 모델을 다운로드하며, 그 이후에는 로컬에 저장되어 오프라인에서도 작동합니다.

availability()는 UI를 구축할 때 기준으로 삼아야 하는 관문입니다. 이 함수는 다음 네 가지 상태 중 하나를 반환합니다:

  • "unavailable": 장치에서 실행할 수 없음 (디스크 공간 부족, 지원되지 않는 하드웨어, 지원되지 않는 옵션 등).
  • "downloadable": 지원되지만, 모델을 먼저 다운로드해야 함. 시작하려면 사용자의 제스처(user gesture)가 필요함.
  • "downloading": 다운로드 진행 중.
  • "available": 지금 바로 사용 가능.

실제 사례 연구: 일반 텍스트를 유효한 다이어그램으로 변환하기

Mermaid는 아주 작은 텍스트 언어입니다. 예를 들어 A --> B라고 쓰면 플로우차트(flowchart)가 됩니다. 익숙해지면 매우 유용하지만, 한 달에 한 번 정도만 접한다면 금방 잊어버리기 쉽습니다. 명확한 해결책은 사용자가 다이어그램을 설명하면 모델이 Mermaid 코드를 작성하게 하는 것입니다. 여기서 까다로운 부분은 작은 모델의 출력을 신뢰할 수 있게 만드는 것입니다.

Gemini Nano는 크기가 작습니다. 모델에 코드를 요청하면 때때로 출력을 마크다운 펜스(markdown fences)로 감싸거나, 수다스러운 서문을 붙이거나, 미세한 구문 오류(syntax error)가 있는 다이어그램을 생성하기도 합니다. 이를 그대로 렌더러(renderer)에 전달한다면, 다섯 번 중 한 번은 작동이 깨지는 도구를 배포하는 셈이 됩니다.

해결 방법은 모델을 초안 작성자(drafter)로 취급하고, 사용자 앞에 실제 검증기(validator)를 두는 것입니다. Mermaid는 자체 파서(parser)를 제공하므로, 이를 신뢰할 수 있는 근거(source of truth)로 사용합니다:

const clean = (s) => s.replace(/```
(?:mermaid)?/g, '').trim();

async function describeToMermaid(description) {
  if ((await LanguageModel.availability()) === 'unavailable') return null;

  const session = await LanguageModel.create({
    initialPrompts: [{
      role: 'system',
      content:
        'You write Mermaid diagram source. Output only valid Mermaid code. ' +
        'No prose, no explanations, no markdown fences.',
    }],
  });

try {
    let code = clean(await session.prompt({% raw %}`Mermaid 다이어그램을 생성하세요: ${description}`{% endraw %}));

    // 신뢰의 근거(Source of truth): 모델의 확신이 아니라, Mermaid 자체 파서(parser)입니다.
    try {
      await mermaid.parse(code);
    } catch (err) {
      // 정확히 한 번의 자기 수정(self-correction) 단계를 거칩니다. 에러를 모델에게 다시 전달합니다.
      code = clean(await session.prompt(
        {% raw %}`다음 Mermaid 코드는 파싱에 실패했습니다:\n${err.message}\n`{% endraw %} +
        {% raw %}`수정된 Mermaid 코드만 반환하세요.`{% endraw %}
      ));
      await mermaid.parse(code); // 여전히 오류가 발생한다면, 예외를 던지며 호출자가 이를 처리합니다.
    }

    return code;
  } finally {
    session.destroy(); // 모델을 해제합니다. 세션을 계속 열어두는 것은 비용이 발생합니다.
  }
}
{% raw %}

저 '검증 및 재시도(validate-and-retry)' 루프가 데모와 실제 도구를 가르는 차이점입니다. 모델은 자신의 실수를 바로잡을 기회를 단 한 번 얻습니다. 만약 두 번 모두 실패한다면, 쓰레기 같은 결과물을 렌더링하는 대신 친절한 메시지를 보여주고 에디터를 그대로 유지합니다. 파서(parser)가 권위자이며, 모델은 단지 빠른 초안을 작성할 뿐입니다.

...


```js
const schema = { type: 'boolean' };

const result = await session.prompt(
  `이 텍스트가 일련의 단계들을 설명하고 있습니까?\n\n${input}`,
  { responseConstraint: schema }
);
console.log(JSON.parse(result)); // true | false

Mermaid 소스는 JSON 스키마(JSON Schema)로 깔끔하게 표현할 수 없으며, 이것이 바로 우리가 파서에 의존하는 정확한 이유입니다. 하지만 분류(classification), 추출(extraction), 또는 양식 채우기(form-filling)의 경우, 구조화된 출력(structured output)은 정리(cleanup) 코드의 한 범주를 통째로 제거해 줍니다.

...


```js
async function setupAI(generateButton) {
  if (!('LanguageModel' in self)) return; // Chrome이 아니거나 너무 오래된 버전인 경우

  const status = await LanguageModel.availability();
  if (status === 'unavailable') return;

  generateButton.hidden = false;

generateButton.onclick = async () => {
    // 모델 다운로드에는 사용자 제스처(user gesture)가 필요합니다. 이 클릭이 바로 그 역할을 합니다.
    const session = await LanguageModel.create({
      monitor(m) {
        m.addEventListener('downloadprogress', (e) => {
          showProgress(Math.round(e.loaded * 100)); // 첫 실행 시 수 GB에 달함
        });
      },
    });
    // ...세션 사용...
  };
}

사람들을 괴롭히는 두 가지 세부 사항:

  • 사용자 활성화 (User activation). 모델을 여전히 다운로드해야 하는 경우, create()는 실제 사용자 제스처(클릭, 키 누름, 탭) 내에서 실행되어야 합니다. 페이지 로드 시 호출하면 오류가 발생합니다. 확실하지 않다면 navigator.userActivation.isActive를 확인하세요.
  • 첫 다운로드 용량이 큽니다. 수 기가바이트(multi-gigabyte)에 달하는 모델입니다. downloadprogress를 모니터링하고 사용자에게 알려주지 않으면, "생성(Generate)" 버튼이 몇 분 동안 멈춰 있는 것처럼 보일 수 있습니다.

이점 (The gains)

이것은 진정으로 새로운 기능이며, 적절한 기능에 적용한다면 타의 추종을 불허합니다:

  • 실행 비용이 무료입니다. 추론 서버(inference server), API 청구서, 피크 시간대의 속도 제한(rate limits) 관리가 필요 없습니다. 무료 공개 도구의 경우 이것이 핵심이며, 사용당 비용이 전혀 들지 않습니다.
  • 구조적으로 프라이버시가 보장됩니다. 프롬프트(prompt)와 응답(response)이 네트워크에 전혀 닿지 않습니다. 데이터가 Google이나 다른 누구에게도 전송되지 않습니다. 내부 시스템이나 민감한 워크플로우를 설계하는 사람들에게 "물리적으로 기기를 떠날 수 없다"는 말은 그 어떤 개인정보 보호정책보다 강력한 약속입니다.
  • 첫 로드 이후에는 오프라인에서도 작동합니다. 모델이 기기에 한 번 저장되면, 비행기 안에서도 기능을 사용할 수 있습니다.
  • 낮은 지연 시간(Low latency), 콜드 스타트(cold starts) 없음. 왕복 시간(round trip)이 없습니다. 짧은 프롬프트의 경우 즉각적인 느낌을 줍니다.
  • 보안해야 할 백엔드가 없습니다. 유출될 키도 없고, 속도 제한을 걸 프록시도 없으며, 남용될 표면(abuse surface)도 없습니다. "클라이언트에서 실행되는 AI"의 공격 표면(attack surface)은 상쾌할 정도로 작습니다.

손실 (The losses)

마찬가지로 솔직하게 말하자면, 바로 이 지점에서 "어디서나 그냥 사용하자"라는 꿈이 무너집니다:

손실 (The losses)

마찬가지로 솔직하게 말하자면, 바로 이 지점에서 "어디서나 그냥 사용하자"라는 꿈이 무너집니다:

  • 하드웨어 요구 사항이 높습니다. Chrome은 프로필 볼륨에 약 22GB의 여유 디스크 공간을 필요로 하며, 4GB 이상의 VRAM을 가진 GPU 또는 16GB 이상의 RAM과 4개 이상의 코어를 가진 CPU가 필요합니다. 충분한 실물 노트북들이 이 기준을 충족하지 못합니다.
  • 데스크톱 Chromium 전용입니다. 데스크톱의 Chrome(Windows 10/11, macOS 13+, Linux) 또는 Chromebook Plus의 ChromeOS에서만 가능합니다. 대부분의 휴대폰, Safari, 오늘날의 Firefox에서는 불가능합니다. 여러분은 청중의 일부를 위해 구축하고 있습니다.
  • 첫 다운로드 용량이 큽니다. 첫 사용 시 수 기가바이트에 달하는 용량입니다. 이후에는 좋지만, 처음에는 어색합니다.
  • 작은 모델입니다. Gemini Nano는 Gemini Pro가 아닙니다. 이탈(drifts)하고, 형식 지침을 잊어버리며, 최첨단 모델이라면 저지르지 않을 실수를 합니다. 위에서 설명했듯이, 반드시 검증 과정으로 감싸야 합니다. 원시 출력은 제안으로 취급해야 합니다.
  • 제한적인 컨텍스트와 언어를 가집니다. 적당한 컨텍스트 창( QuotaExceededErrorcontextoverflow 이벤트를 확인하세요)을 가지고 있으며, Chrome 149 기준으로 언어 모델이 영어, 스페인어, 일본어, 독일어, 프랑스어를 대상으로 합니다.
  • 웹 환경에서 여전히 성숙 중입니다. 웹 Prompt API는 안정적이지만 활발하게 진화하고 있습니다. temperature/topK와 같은 샘플링 매개변수는 현재 확장 기능 전용이며, 아직 Web Workers에서는 사용할 수 없습니다.

그렇다면 실제로 언제 사용해야 할까요?

이 결정은 주로 해당 기능이 필수적인지 아니면 보너스인지, 그리고 데이터가 얼마나 민감한지에 달려 있습니다.

온디바이스 AI를 활용할 시점은 다음과 같습니다. 기능이 점진적 향상(progressive enhancement)일 수 있을 때, 개인 정보 보호가 실제 판매 포인트일 때, 작업 부하가 작고 빈번하며 (분류, 추출, 재작성, 초안 작성), 아예 백엔드를 구동하고 싶지 않을 때입니다. 이는 놀라울 정도로 많은 "있으면 좋은" AI에 해당합니다.

기능이 모든 사용자에게 핵심적이거나, 거대 모델(Large Model) 또는 프런티어 모델(Frontier Model)이 필요할 때, 모든 하드웨어에서 출력 품질이 일관되어야 할 때, 혹은 지금 당장 모바일과 Safari에서 작동해야 할 때는 서버 측(Server-side) 방식을 유지하세요. 그리고 영원히 하나만 선택해야 하는 것도 아닙니다. 일반적인 패턴은 하이브리드(Hybrid) 방식으로, 기기 내(On-device)에서 실행이 가능하면 기기에서 실행하고, 그렇지 않으면 클라우드 모델로 폴백(Fallback)하는 것입니다. Chrome의 문서는 정확히 이 용도를 위한 폴리필(Polyfill)과 Firebase AI Logic 폴백을 다루고 있습니다.

우리의 Mermaid 에디터의 경우 선택은 쉬웠습니다. 다이어그램 생성기는 보너스 기능이며, 이를 실행할 수 있는 사람들은 즐겁고 프라이빗한 경험을 얻고, 그 외의 모든 사람들은 완전히 작동하는 에디터를 사용할 수 있습니다. 아무도 한계에 부딪히지 않습니다.

보너스적인 전쟁 이야기: 오염된 캔버스 (Tainted Canvas)

우리의 오후 시간을 앗아갔지만 여러분의 시간은 아껴줄 수 있는 세부 사항 하나를 공유합니다. 다이어그램을 PNG로 내보내는 것은 숨겨진 캔버스(Canvas)에 그리는 것을 의미했는데, Chrome에서 Tainted canvases may not be exported.(오염된 캔버스는 내보낼 수 없습니다)라는 오류가 계속 발생했습니다.

원인은 이렇습니다: Mermaid가 임베디드 HTML 요소(foreignObject) 내부에 텍스트 레이블을 렌더링하고 있었고, 브라우저는 이를 캔버스에 대한 보안 오염(Security taint)으로 취급하여 내보내기를 차단했습니다. 해결책은 Mermaid가 레이블을 임베디드 HTML 대신 실제 SVG <text>로 렌더링하도록 구성하는 것이었습니다. 보너스로, 이제 텍스트가 PNG 내보내기 시 깨끗하게 유지되며 SVG 내에서도 선택 가능한 상태로 남게 되었습니다. 만약 완전히 로컬 작업처럼 보이는 내보내기에서 오염된 캔버스(Tainted-canvas) 오류를 본다면, 먼저 foreignObject가 있는지 확인하세요.

직접 시도해보고, 무언가를 만들어 보세요

Mermaid 에디터는 현재 라이브 상태이며 무료로 제공됩니다. 최신 데스크톱 Chrome을 사용 중이라면, 다이어그램을 설명해 보세요. 기기 외부로 아무것도 나가지 않은 채 브라우저가 직접 작성하는 것을 볼 수 있습니다. 최신 버전이 아니더라도 실시간 미리보기, 테마, 내보내기 기능이 포함된 빠른 에디터를 여전히 사용할 수 있습니다.

더 넓은 관점에서 보자면: 여러분이 백엔드 비용을 산정해 왔던 AI 기능의 의미 있는 부분들을 이제 클라이언트에서 무료로 실행할 수 있으며, 이는 여러분의 서버가 제공했던 것보다 더 나은 프라이버시를 제공합니다. 하드웨어 사양과 브라우저 지원 문제로 모든 사례에 적합하지는 않겠지만, 적합한 경우에는 정말 아름답게 작동할 것입니다.

이것은 우리가 고객 업무에 적용하는 AI에 대한 실용적인 관점이기도 합니다. 우리는 헤드라인을 장식하기 위한 AI보다는 조용히 실제 업무를 수행하는 AI (AI agents)와, 사용자의 실제 작업 방식에 맞춰 구축된 맞춤형 소프트웨어 (custom software)에 훨씬 더 많은 관심을 두고 있습니다. 만약 당신의 워크플로(workflow)에 작고 날카로운 전용 도구가 필요하다면, 우리는 바로 그런 종류의 문제를 해결하는 것을 좋아합니다.

Bitvea 제작. 당신은 비즈니스에 집중하세요. IT는 저희가 책임집니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0