KYC 없이 — 신분증, 셀피, 서류가 필요 없습니다. 암호화폐로 결제하세요: BTC, USDT, USDC, ETH, SOL, LTC
언어: 한국어
API 키 받기

문서 · Node.js

Node.js 예제: fetch로 검색, 작은 풀, 인용 포함 답변

Node 18 이상에는 fetch이 기본 포함되어 있어 API에 패키지가 전혀 필요 없습니다. 이 페이지에서는 검색 한 번, rate limit을 넘지 않으면서 여러 검색을 실행하는 풀, 그리고 소스를 번호가 붙은 인용이 포함된 답변으로 바꾸는 루프를 보여줍니다.

마지막 업데이트: · 4 분 소요

빠른 답변

Node.js에서 AI 에이전트용 웹 검색 API를 어떻게 호출하나요?

Node 18+의 기본 fetch을 사용해 Bearer 키와 함께 검색 쿼리를 https://llmwebsearch.com/api/v1/search로 POST하세요. LLMWebSearch은 순위가 매겨진 결과와 상위 3개 페이지를 Markdown으로 반환하므로, 번호를 붙여 모델에 넘기면 인용이 포함된 답변을 만들 수 있습니다. 검색 한 번에 1크레딧이며, 2026년 10월 기준 US$1.20/1K 검색부터 시작합니다. npm 패키지는 필요 없습니다. KYC 없이, 암호화폐 결제.

필요한 것

Node.jsfetch 기본 포함을 위한 18 이상 버전; 최상위 await를 위해 스크립트를 .mjs로 저장
패키지없음
키환경 변수의 LLMWEBSEARCH_API_KEY
답변 루프용OpenAI 호환 채팅 endpoint: LLM_BASE_URL, LLM_API_KEY, LLM_MODEL
과금크레딧 1개로 검색 1회를 이용할 수 있습니다. 최대 20개의 순위 결과를 받고, 상위 3개 페이지의 본문을 읽어 Markdown으로 반환합니다. 4~10개 페이지를 읽으면 크레딧 2개가 됩니다. 오류로 끝난 호출에는 비용이 청구되지 않습니다

재사용 가능한 검색 함수는 어떻게 작성하나요?

호출을 한 번 감싸서 어디서든 재사용하세요. 아래 함수는 본문을 보내고, 모든 HTTP 실패 시 읽을 수 있는 오류를 던지며, 파싱된 JSON을 반환합니다. 오류에는 rate_limited 또는 insufficient_credits 같은 API 자체의 code가 담겨 있어 호출하는 쪽에서如何处理할지 결정할 수 있습니다.

search.mjs
const API = 'https://llmwebsearch.com/api/v1/search';

export async function search(body) {
  const res = await fetch(API, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.LLMWEBSEARCH_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(body),
  });
  const data = await res.json();
  if (!res.ok) {
    const err = new Error(`${res.status} ${data.error?.code}: ${data.error?.message}`);
    err.status = res.status;
    throw err;
  }
  return data;
}

const data = await search({ q: 'how to size a postgres connection pool', read: 3 });
for (const r of data.results) {
  console.log(r.position, r.content_status, r.url, r.word_count ?? '');
}

rate limit에 걸리지 않고 여러 검색을 실행하려면 어떻게 하나요?

작은 풀을 통해 실행하세요. 고정된 수의 워커가 공유 목록에서 다음 검색 쿼리를 하나씩 가져가는 방식입니다. 워커 4개가 합리적인 시작점입니다. 모든 계정에는 분당 호출 제한이 있으며 대시보드에 표시됩니다. 지원팀에 요청하면 상향할 수 있습니다.

아래 풀은 라이브러리가 필요 없습니다. 각 워커가 자기 결과를 따로 보관하고, 실패한 검색은 실행을 중단하는 대신 오류와 함께 기록됩니다. 연구 에이전트에서는 잘못된 하위 질문 하나가 전체 작업을 망치면 안 되기 때문에 이 점이 중요합니다.

pool.mjs
const API = 'https://llmwebsearch.com/api/v1/search';
const questions = [
  'what is connection pooling in postgres',
  'recommended pool size per cpu core',
  'pgbouncer transaction mode limitations',
  'connection pool exhaustion symptoms',
  'pool size for serverless functions',
];

async function search(q) {
  const res = await fetch(API, {
    method: 'POST',
    headers: { Authorization: `Bearer ${process.env.LLMWEBSEARCH_API_KEY}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({ q, read: 2, max_chars: 4000 }),
  });
  const data = await res.json();
  if (!res.ok) return { q, error: data.error?.code ?? String(res.status) };
  return { q, urls: data.results.filter((r) => r.content_status === 'ok').map((r) => r.url) };
}

async function runPool(items, size, task) {
  const out = [];
  let next = 0;
  const worker = async () => {
    while (next < items.length) {
      const i = next++;
      out[i] = await task(items[i]);
    }
  };
  await Promise.all(Array.from({ length: size }, worker));
  return out;
}

for (const row of await runPool(questions, 4, search)) console.log(row);

결과를 인용이 포함된 답변으로 바꾸려면 어떻게 하나요?

출처에 번호를 매기고, 각 출처 옆에 URL을 붙이고, 예산에 맞게 줄인 다음, 모델에게 번호로 인용하도록 요청하세요. API는 작성된 답변이 아니라 출처를 반환합니다. 자체 모델이 페이지를 읽고 답변을 작성하며 URL을 인용합니다. 아래 스크립트는 세 개의 환경 변수로 선택한 OpenAI 호환 chat/completions endpoint와 통신하므로, 호스팅 모델과 로컬 모델 모두에서 작동합니다.

약 24,000자, 대략 6,000토큰의 예산을 출처들 사이에 고르게 나눕니다. 페이지를 읽을 수 없었던 결과는 스니펫으로 전달되며, 그렇게 표시됩니다.

answer.mjs
const SEARCH = 'https://llmwebsearch.com/api/v1/search';
const BUDGET = 24000; // characters, about 6,000 tokens

async function sources(question) {
  const res = await fetch(SEARCH, {
    method: 'POST',
    headers: { Authorization: `Bearer ${process.env.LLMWEBSEARCH_API_KEY}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({ q: question, max_results: 5, read: 3 }),
  });
  const { results } = await res.json();
  const share = Math.floor(BUDGET / Math.max(results.length, 1));
  return results
    .map((r, i) => {
      const body = r.content_status === 'ok' ? r.content.slice(0, share) : `(snippet only) ${r.snippet}`;
      return `[${i + 1}] ${r.title} - ${r.url}\n${body}`;
    })
    .join('\n\n');
}

async function answer(question) {
  const prompt = 'Answer using only the sources below. Cite them as [1], [2] and so on. '
    + 'Say so if they do not answer the question.\n\n' + (await sources(question)) + '\n\nQuestion: ' + question;
  const res = await fetch(`${process.env.LLM_BASE_URL.replace(/\/$/, '')}/chat/completions`, {
    method: 'POST',
    headers: { Authorization: `Bearer ${process.env.LLM_API_KEY}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({ model: process.env.LLM_MODEL, messages: [{ role: 'user', content: prompt }] }),
  });
  const data = await res.json();
  return data.choices[0].message.content;
}

console.log(await answer('How should I size a Postgres connection pool?'));

Node에서 GET과 POST 중 어느 것을 써야 하나요?

애플리케이션 코드에서는 JSON 본문과 함께 POST를 사용하세요. include_domains 같은 배열과 긴 질문은 검색 쿼리 문자열보다 본문에 담아 보낼 때 더 깔끔하게 전달됩니다. GET은 빠른 테스트와 본문을 보낼 수 없는 도구를 위한 것입니다. 검색 쿼리 문자열은 URLSearchParams로 만들고 목록은 쉼표로 이어 붙이세요.

두 방식 모두 비용이 같고 동일한 JSON을 반환합니다. 검색 레퍼런스에 두 방식의 모든 파라미터가 나와 있습니다.

API 키는 어디에 두어야 하나요?

런타임에 읽는 환경 변수에 두고, 소스 파일에는 절대 두지 마세요. 서버에서는 플랫폼의 시크릿 저장소를 사용하세요. 브라우저에서는 API를 아예 호출하지 마세요. 모든 방문자에게 API 키가 보이게 됩니다. 자체 백엔드를 호출하고, 그 백엔드가 LLMWebSearch를 호출하도록 하세요.

에이전트, 앱, 팀원별로 API 키를 하나씩 만들고, 다른 키는 건드리지 않고 대시보드에서 각각 폐기하세요. 서비스마다 키를 하나씩 두면 대시보드 기록을 읽기 쉽고, 유출된 API 키를 폐기하기도 쉽습니다.

Node.js: 자주 묻는 질문

npm 패키지가 있나요?

없습니다. fetch는 Node 18 이상에 내장되어 있고, API는 HTTPS 위의 순수 JSON입니다. 이 페이지의 함수들이 통합의 전부입니다.

Deno, Bun 또는 edge 런타임에서도 작동하나요?

이 코드는 fetch, JSON, process.env만 사용합니다. fetch가 있는 런타임에서는 process.env를 해당 런타임의 시크릿 읽기 방식으로 바꾸면 작동합니다.

실패한 호출은 어떻게 재시도하나요?

429, 502, 504만 재시도하고, 대기 시간은 매번 두 배로 늘리세요. 400, 401, 402는 절대 재시도하지 마세요. 오류 페이지에서 그 이유와 헬퍼를 확인할 수 있습니다.

US$1.20/1K 검색부터 · KYC 없이

API 키 받기