Node.js에서 실시간 금 시세를 조회하려면 기본 fetch로 api.goldprice.dev/v1/spot/XAU-USD-SPOT에 GET 요청을 보내세요. API 키는 X-API-Key 헤더에 넣습니다. HTTP 라이브러리는 필요하지 않습니다. 응답은 Map에 60초 동안 캐시하고, 가격 계산에는 decimal.js를 사용하세요. 무료 플랜은 월 5,000회 호출을 제공하며 카드가 필요하지 않습니다. 2026년 7월에 Node 22 LTS에서 테스트했습니다.
goldprice.dev API 키 발급
goldprice.dev/onboarding에서 무료 계정을 만드세요. 이메일을 인증하면 대시보드에 ga_live_로 시작하는 키가 표시됩니다. 환경 변수로 설정하세요:
export GOLDPRICE_API_KEY=ga_live_replace_with_your_key_here무료 플랜은 월 5,000회 호출과 31개 통화의 금 현물 시세를 제공합니다. 카드는 필요하지 않습니다.
decimal.js 설치
Node 18+에는 기본 fetch가 있어 HTTP 클라이언트가 필요하지 않습니다. 필요한 의존성은 decimal.js뿐입니다. JavaScript의 Number 계산에서 생기는 오차를 막고 가격을 정확하게 계산합니다. 다음과 같이 설치하세요:
npm install decimal.js금 시세 클라이언트 작성
다음 코드를 goldprice.mjs로 저장하세요. spot()은 심볼별 응답을 Map에 60초 동안 캐시하고, 429 응답 시 대기 시간을 지수적으로 늘리며 최대 3회 재시도합니다. 가격은 Decimal로 반환합니다. 선택 항목인 매수호가와 매도호가는 유료 플랜에서만 제공하며, 없으면 null이 됩니다.
// node: goldprice.mjs// curl-equivalent: https://api.goldprice.dev/v1/spot/XAU-USD-SPOTimport Decimal from "decimal.js";const API_BASE = "https://api.goldprice.dev";const API_KEY = process.env.GOLDPRICE_API_KEY;if (!API_KEY) { throw new Error("GOLDPRICE_API_KEY not set");}const TTL_MS = 60_000;const cache = new Map();/** Fetch live spot price. Cached 60s per symbol, retries 3x on 429. */export async function spot(symbol = "XAU-USD-SPOT") { const cached = cache.get(symbol); if (cached && cached.expiresAt > Date.now()) { return cached.data; } let lastErr; for (let attempt = 0; attempt < 3; attempt++) { const res = await fetch(`${API_BASE}/v1/spot/${symbol}`, { headers: { "X-API-Key": API_KEY }, signal: AbortSignal.timeout(5000), }); if (res.status === 429) { lastErr = new Error("goldprice: 429 rate limited"); const backoffMs = 2 ** attempt * 1000; // 1s, 2s, 4s await new Promise((resolve) => setTimeout(resolve, backoffMs)); continue; } if (!res.ok) { throw new Error(`goldprice: unexpected status ${res.status}`); } const raw = await res.json(); const data = { symbol: raw.symbol, quoteCurrency: raw.quote_currency, price: new Decimal(raw.price), bid: raw.bid == null ? null : new Decimal(raw.bid), ask: raw.ask == null ? null : new Decimal(raw.ask), isStale: raw.is_stale, computedAt: raw.computed_at, }; cache.set(symbol, { data, expiresAt: Date.now() + TTL_MS }); return data; } throw lastErr;}실행
모듈을 가져와 spot()을 호출하세요. 첫 호출은 API에 요청하고, 이후 60초 이내 호출은 네트워크 요청 없이 캐시된 Decimal을 반환합니다. 캐시는 프로세스 안에만 있으므로 프로세스를 다시 시작하면 사라집니다. 프로세스 간 공유가 필요하면 Redis를 사용하세요.
import { spot } from "./goldprice.mjs";const r = await spot("XAU-USD-SPOT");console.log(`${r.symbol}-${r.quoteCurrency}: ${r.price} (computed ${r.computedAt})`);// XAU-USD: 4012.75 (computed 2026-10-23T07:00:18.221118+00:00)통화 또는 금속 변경
심볼 형식은 METAL-CURRENCY-SPOT입니다. 현물 시세를 제공하는 31개 통화 중 원하는 통화의 심볼을 spot()에 전달하세요. Map은 심볼별로 따로 캐시합니다. 여러 통화를 표시하는 대시보드가 5개 심볼을 60초 간격으로 조회하면 캐시 미적중 시 분당 5회, 캐시 적중 시 0회 호출합니다.
// USD spot, defaultawait spot("XAU-USD-SPOT");await spot("XAU-INR-SPOT");await spot("XAU-EUR-SPOT");// Silver in USDawait spot("XAG-USD-SPOT");예상 결과
{ "symbol": "XAU", "quote_currency": "USD", "unit": "troy_ounce", "contract_type": "spot", "price": "4012.75", "is_stale": false, "computed_at": "2026-10-23T07:00:18.221118+00:00"}표준 출력에는 심볼, 표시 통화, decimal.js Decimal 가격, ISO 8601 형식의 computedAt 시각이 한 줄로 표시됩니다. 이후 코드는 spot()이 반환한 일반 객체를 사용합니다.
자주 발생하는 오류
| 코드 | 증상 | 해결 방법 |
|---|---|---|
| 401 | 첫 호출에서 goldprice: unexpected status 401 발생 | API 키가 없거나 유효하지 않습니다. echo $GOLDPRICE_API_KEY로 환경 변수를 확인하세요. 비어 있으면 대시보드의 키를 다시 설정하세요. 환경 변수가 비어 있으면 모듈을 가져올 때 예외가 발생하므로 요청 전에 문제를 확인할 수 있습니다. |
| 429 | 대기 시간을 늘리며 세 번 재시도해도 모두 429가 반환되고 spot()이 실패함 | 분당 호출 한도에 도달했습니다. 일정한 간격의 조회에는 60초 캐시가 도움이 됩니다. 서로 다른 심볼의 요청이 한꺼번에 몰리면 호출 시점을 나누세요. 지속적으로 많은 호출이 필요하면 /pricing에서 유료 플랜을 확인하세요. |
| N/A | 가격은 정상으로 보이지만 계산을 반복하면 작은 오차가 생김 | JavaScript의 Number는 IEEE-754 부동소수점 형식입니다. 0.1 + 0.2 === 0.30000000000000004가 그 예입니다. 금 시세는 소수점 이하 2자리이므로 수천 개 값을 Number로 더하면 베이시스 포인트 수준의 오차가 생깁니다. 계산 중에는 decimal.js의 Decimal을 유지하고, 표시하거나 직렬화할 때만 .toString() 또는 .toNumber()를 호출하세요. |
더 활용하기
- 프로세스 간 캐시를 공유하려면
Map을 Redis 캐시로 바꿔 여러 워커가 캐시된 시세를 함께 사용하도록 구성하세요 /v1/bars?symbol=XAU-USD-SPOT&interval=1d&from=...&to=...용bars()래퍼를 추가하고 시계열 데이터를 백테스트에 사용하세요- 클라이언트를 Express 또는 Fastify 라우트에 연결해 Node 외의 서비스에서도 내부적으로 사용하세요
- 캐시가 없는 같은 심볼에 요청이 몰리면 진행 중인 요청을 공유해 조회를 한 번만 실행하세요
- 캐시 적중률, p50/p95 지연 시간, 429 재시도 횟수를 Prometheus 지표로 제공하세요