실행 프로그램과 확장
Transformers.js로 브라우저 안에서 로컬 LLM 실행하기
질문을 입력하면 내 브라우저에서 답변을 만드는 작은 웹 앱을 만들어봐요.
Transformers.js는 AI 모델을 JavaScript로 실행하는 라이브러리예요. ONNX 형식의 모델을 내려받으면 브라우저에서도 답변을 생성할 수 있어요. 이 글에서는 4.3.0의 공식 예제 모델인 LFM2.5-350M을 사용해 질문 입력창과 답변 버튼을 만들어요.
브라우저 로컬 추론은 무엇을 바꾸나요?
보통 웹에서 AI에 질문하면 서버가 답변을 만들어 보내줘요. 브라우저 로컬 추론은 이 작업을 사용자의 컴퓨터가 맡는 방식이에요. Transformers.js의 `pipeline1()`을 한 번 만들고 입력 문장을 전달하면, 내려받은 모델이 같은 페이지에서 답변을 생성해요.
별도 Python 추론 서버를 설치할 필요가 없어 작은 웹 기능을 시험하기 좋아요. 텍스트 분류나 짧은 답변처럼 부담이 작은 작업부터 시작해보세요. 많은 사용자를 동시에 처리하거나 큰 모델을 계속 제공할 때는 별도 서빙 엔진을 검토하는 편이 좋아요.

4.3.0에서 확인할 모델과 장치 선택
Transformers.js 4.3.0은 2026년 9월 16일 공개됐어요. 릴리스 예제는 `onnx-community/LFM2.5-350M-ONNX`에 WebGPU2용 `q4f16`을 사용합니다. 이 모델 저장소에는 CPU/WASM에서 선택할 수 있는 `q4` 파일도 있지만 `q8` 파일은 확인되지 않아, 아래 코드는 장치에 따라 두 형식 중 하나를 고릅니다.
다른 ONNX 모델로 바꿀 때는 선택한 dtype 파일이 해당 저장소에 있는지 확인하세요. 파일 이름과 추론 설정이 일치해야 모델을 불러올 수 있어요.
공식 자료는 이 모델의 최소 시스템 RAM3·GPU4 메모리를 제시하지 않아요. 모델 파일 크기만으로 실행 가능 여부를 단정하지 말고, 처음 실행할 때 브라우저 작업 관리자에서 탭의 메모리 사용량을 확인하세요.
| 브라우저 실행 경로 | 설정 | 사용 조건 |
|---|---|---|
| CPU/WASM | `device` 생략, `dtype: 'q4'` | 이 저장소에 있는 q4 파일을 사용하는 기본 추론 경로 |
| 지원 GPU | `device: 'webgpu'`, `dtype: 'q4f16'` | WebGPU adapter를 얻고 해당 형식을 지원할 때 |
| q8 | 이 모델에서는 선택하지 않음 | 공식 모델 저장소에 q8 ONNX 파일이 없어 사용할 수 없음 |
이 모델 저장소에서 확인한 실행 형식과 브라우저 장치 경로예요.
CPU/WASM
- 설정
- `device` 생략, `dtype: 'q4'`
- 사용 조건
- 이 저장소에 있는 q4 파일을 사용하는 기본 추론 경로
지원 GPU
- 설정
- `device: 'webgpu'`, `dtype: 'q4f16'`
- 사용 조건
- WebGPU adapter를 얻고 해당 형식을 지원할 때
q8
- 설정
- 이 모델에서는 선택하지 않음
- 사용 조건
- 공식 모델 저장소에 q8 ONNX 파일이 없어 사용할 수 없음

localhost에서 여는 정적 HTML 준비
정적 파일 두 개만 있으면 시작할 수 있어요. ES module의 CDN import를 사용하므로 파일을 탐색기에서 직접 여는 대신 로컬 웹 서버를 띄웁니다. `localhost`는 WebGPU가 요구하는 secure context로 취급됩니다. 공개 배포에는 HTTPS를 사용하세요.
새 빈 폴더에서 `index.html`과 `main.js`를 만들고 아래 HTML을 저장하세요. 이 경로는 jsDelivr CDN에서 라이브러리를 모듈로 불러오는 공식 문서 방식입니다. 버전을 URL에 고정하면 이후 CDN의 기본 태그가 바뀌어도 이 예제는 4.3.0을 요청합니다.
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Browser-local text generation</title>
<label>Prompt <input id="prompt" value="Reply in one short sentence: local AI runs in a browser."></label>
<button id="run" disabled>Generate</button>
<pre id="status">Loading model…</pre>
<pre id="output"></pre>
<script type="module" src="./main.js"></script>
</html>
모델을 불러와 한 번 생성하기
아래 `main.js`는 WebGPU를 사용할 수 있는지 확인한 뒤 모델을 불러와요. GPU를 사용할 수 있으면 `q4f16`, 사용할 수 없거나 확인 과정에서 오류가 나면 CPU/WASM용 `q4`를 선택해요. 모델이 준비되면 Generate 버튼이 활성화돼요.
첫 실행에서는 CDN에서 라이브러리를, Hugging Face Hub에서 모델 파일을 받아요. 이 예제의 질문은 별도 추론 서버로 보내지 않고 브라우저 안에서 처리해요. 서비스에 붙일 때는 분석 도구나 로그 수집 코드가 입력을 전송하는지도 확인하세요. 모델을 불러오는 작업은 한 번만 하고, 버튼을 누를 때마다 같은 실행기를 재사용해요.
import { pipeline } from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@4.3.0';
const status = document.querySelector('#status');
const output = document.querySelector('#output');
const promptInput = document.querySelector('#prompt');
const button = document.querySelector('#run');
const modelId = 'onnx-community/LFM2.5-350M-ONNX';
let adapter = null;
try {
adapter = await navigator.gpu?.requestAdapter() ?? null;
} catch (error) {
console.warn('WebGPU unavailable; using CPU/WASM.', error);
}
const device = adapter ? 'webgpu' : undefined;
const dtype = adapter ? 'q4f16' : 'q4';
let generator;
try {
status.textContent = `Loading ${modelId} (${device ?? 'CPU/WASM'}, ${dtype})…`;
generator = await pipeline('text-generation', modelId, { dtype, ...(device ? { device } : {}) });
status.textContent = `Ready: ${device ?? 'CPU/WASM'} / ${dtype}`;
button.disabled = false;
} catch (error) {
status.textContent = `Model load failed: ${error.message}`;
console.error(error);
}
button.addEventListener('click', async () => {
if (!generator) return;
button.disabled = true;
status.textContent = 'Generating…';
try {
const result = await generator(promptInput.value, { max_new_tokens: 48 });
const generated = result[0]?.generated_text;
output.textContent = typeof generated === 'string'
? generated
: Array.isArray(generated)
? generated.at(-1)?.content ?? JSON.stringify(result)
: JSON.stringify(result);
status.textContent = 'Done.';
} catch (error) {
status.textContent = `Generation failed: ${error.message}`;
console.error(error);
} finally {
button.disabled = false;
}
});서버를 띄워 결과와 첫 다운로드 확인
파일을 저장한 폴더에서 터미널을 열고 아래 명령 중 하나만 실행하세요. `http://127.0.0.1:8000`에 접속해 상태 문구가 `Ready:`로 바뀌면 Generate를 눌러요. 처음에는 모델 파일을 받느라 시간이 걸려요. 준비가 끝나면 입력한 문장에 대한 짧은 결과가 표시돼요.
두 명령 모두 내 컴퓨터에서만 접속할 수 있도록 주소를 제한했어요. Node.js를 쓰면 첫 명령을, Python이 설치돼 있으면 두 번째 명령을 선택하면 돼요. 공개 웹사이트에서는 HTTPS를 사용하세요.
# Option A: Node.js
npx serve --listen tcp://127.0.0.1:8000 .
# Option B: Python (choose one server, not both)
python3 -m http.server 8000 --bind 127.0.0.1모델이 열리지 않으면 다운로드와 GPU 오류를 확인해요.
WebGPU adapter가 없으면 CPU/WASM용 `q4`를 사용해요. Safari에서는 Transformers.js 4.3.0이 지원을 추가한 Safari 26 이상인지 확인하고, 다른 브라우저는 해당 버전의 WebGPU 지원을 따로 확인하세요. adapter가 반환돼도 메모리 부족으로 모델 적재가 실패할 수 있습니다.
모델 파일을 불러오지 못하면 브라우저 개발자 도구의 Network에서 CDN 또는 Hub 요청의 차단·실패를 확인하세요. GPU device 오류가 나면 다른 탭과 앱을 닫고 CPU5용 `q4`로 다시 열거나 더 작은 지원 모델을 선택해요. 입력 뒤 오류가 발생하면 콘솔의 첫 에러와 모델 ID·dtype·device 조합을 기록하면 재현에 도움이 됩니다.
브라우저 추출 결과를 JSON 형식으로 받기
답변을 다음 프로그램에 넘기려면 문장보다 JSON이 편할 때가 있어요. 예를 들어 상품 의견에서 감성과 주제만 뽑을 수 있어요. 4.3.0의 실험 기능인 구조화 출력은 JSON Schema로 출력할 필드와 값을 제한해요. 현재는 한 번에 결과 하나를 생성해요.
이 기능에는 별도 패키지가 필요해요. 아래 코드는 앞의 CDN HTML에 그대로 붙이는 대신, Vite 같은 모듈 번들러가 있는 웹 프로젝트에서 사용해요. 의존성을 설치하고 JavaScript 파일에 넣으면 돼요. 출력은 `JSON.parse()`로 읽고, 필요한 필드가 있는지 확인한 뒤 사용하세요.
npm install @huggingface/transformers@4.3.0 @huggingface/transformers-structured-outputimport { pipeline } from '@huggingface/transformers';
import { StructuredOutputProcessor } from '@huggingface/transformers-structured-output';
const generator = await pipeline('text-generation', 'onnx-community/LFM2.5-350M-ONNX', {
dtype: 'q4f16', device: 'webgpu',
});
const processor = new StructuredOutputProcessor(generator.tokenizer, {
type: 'json_schema',
json_schema: {
type: 'object',
properties: {
sentiment: { enum: ['positive', 'negative', 'neutral'] },
topic: { enum: ['price', 'quality', 'delivery', 'other'] },
},
required: ['sentiment', 'topic'],
additionalProperties: false,
},
});
const result = await generator(
[{ role: 'user', content: 'Classify this feedback: Shipping was fast, but the product is expensive.' }],
{ max_new_tokens: 48, do_sample: false, logits_processor: [processor] },
);
const jsonText = result[0].generated_text.at(-1).content;
console.log(JSON.parse(jsonText));용어 각주
파이프라인 — 입력부터 결과까지 이어지는 처리 단계의 묶음입니다. 각 단계에서 서로 다른 모델이나 도구를 사용할 수 있습니다.
본문으로 돌아가기WebGPU — 웹 브라우저에서 그래픽과 범용 GPU 계산을 수행하기 위한 웹 표준 API입니다. 브라우저와 기기별 지원 기능은 다를 수 있습니다.
본문으로 돌아가기시스템 RAM — 프로그램이 실행되는 동안 데이터를 임시로 보관하는 시스템 메모리입니다.
본문으로 돌아가기GPU — 많은 계산을 병렬로 처리하는 프로세서입니다. AI 모델 실행에서는 모델 계산을 맡습니다.
본문으로 돌아가기CPU — 컴퓨터에서 일반적인 프로그램 명령을 실행하는 중앙 처리 장치입니다. AI 작업에서는 GPU 등 다른 프로세서와 역할을 나누기도 합니다.
본문으로 돌아가기
