PHP에서 실시간 금 시세를 조회하려면 기본 cURL로 api.goldprice.dev/v1/spot/XAU-USD-SPOT에 GET 요청을 보내세요. API 키는 X-API-Key 헤더에 넣습니다. Composer는 필요하지 않습니다. JSON을 디코딩한 뒤 가격은 문자열로 유지하고, 정확한 소수 계산에는 BCMath를 사용하세요. 심볼별로 60초 동안 캐시합니다. 무료 플랜은 월 5,000회 호출을 제공하며 카드가 필요하지 않습니다. 2026년 6월에 PHP 8.3에서 테스트했습니다.
goldprice.dev API 키 발급
goldprice.dev/onboarding에서 무료 계정을 만드세요. 이메일을 인증하면 대시보드에 ga_live_로 시작하는 키가 표시됩니다. 환경 변수로 설정하세요:
export GOLDPRICE_API_KEY=ga_live_replace_with_your_key_here무료 플랜은 월 5,000회 호출과 31개 통화의 금 현물 시세를 제공합니다. 카드는 필요하지 않습니다.
필수 확장 확인
Composer 패키지는 필요하지 않습니다. PHP 8에는 curl과 json이 포함되어 있으며, bcmath는 정확한 소수 계산을 위한 표준 확장입니다. 세 확장이 모두 활성화되어 있는지 확인하세요:
php -m | grep -E '^(curl|json|bcmath)$'# curl# json# bcmath <- if missing, install php8.3-bcmath (or enable in php.ini)금 시세 클라이언트 작성
다음 코드를 goldprice.php로 저장하세요. spot()은 심볼별 응답을 정적 배열에 60초 동안 캐시하고, 429 응답 시 대기 시간을 지수적으로 늘리며 최대 3회 재시도합니다. 디코딩한 배열을 반환하며, BCMath로 정확하게 계산할 수 있도록 가격은 문자열로 유지합니다.
<?php// php: goldprice.php, native cURL + BCMath, no Composer// curl-equivalent: https://api.goldprice.dev/v1/spot/XAU-USD-SPOTdeclare(strict_types=1);const API_BASE = 'https://api.goldprice.dev';const TIMEOUT = 5; // secondsconst TTL = 60; // secondsfinal class RateLimitedException extends RuntimeException {}final class GoldpriceClient{ private string $apiKey; /** @var array<string, array{data: array, expires: int}> */ private static array $cache = []; public function __construct() { $key = getenv('GOLDPRICE_API_KEY'); if ($key === false || $key === '') { throw new RuntimeException('GOLDPRICE_API_KEY not set'); } $this->apiKey = $key; } /** * Fetch live spot price. Cached 60s per symbol, retries 3x on 429. * Prices stay as strings for BCMath. */ public function spot(string $symbol = 'XAU-USD-SPOT'): array { $now = time(); if (isset(self::$cache[$symbol]) && self::$cache[$symbol]['expires'] > $now) { return self::$cache[$symbol]['data']; } for ($attempt = 0; $attempt < 3; $attempt++) { try { $data = $this->fetch($symbol); self::$cache[$symbol] = ['data' => $data, 'expires' => $now + TTL]; return $data; } catch (RateLimitedException) { sleep(1 << $attempt); // 1s, 2s, 4s } } throw new RateLimitedException('goldprice: 429 after 3 retries'); } private function fetch(string $symbol): array { $ch = curl_init(API_BASE . '/v1/spot/' . rawurlencode($symbol)); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => TIMEOUT, CURLOPT_HTTPHEADER => ['X-API-Key: ' . $this->apiKey], ]); $body = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); curl_close($ch); if ($code === 429) { throw new RateLimitedException('rate limited'); } if ($code !== 200 || $body === false) { throw new RuntimeException("goldprice: unexpected status {$code}"); } return json_decode((string) $body, true, 512, JSON_THROW_ON_ERROR); }}$client = new GoldpriceClient();$r = $client->spot('XAU-USD-SPOT');// Prices are strings; use BCMath for exact math (e.g. price for 5 oz):$fiveOz = bcmul($r['price'], '5', 4);printf("%s-%s: %s (computed %s)\n", $r['symbol'], $r['quote_currency'], $r['price'], $r['computed_at']);printf("5 troy oz = %s %s\n", $fiveOz, $r['quote_currency']);실행
GOLDPRICE_API_KEY를 설정한 셸에서 CLI로 파일을 실행하세요. 첫 호출은 API에 요청합니다. 같은 프로세스에서 60초 이내에 spot()을 다시 호출하면 캐시된 배열을 반환합니다. 정적 캐시는 프로세스별로 유지됩니다. PHP-FPM에서 요청 간 공유하려면 APCu나 Redis를 사용하세요.
php goldprice.php# XAU-USD: 4012.75 (computed 2026-10-23T07:00:18.221118+00:00)# 5 troy oz = 20063.7500 USD통화 또는 금속 변경
심볼 형식은 METAL-CURRENCY-SPOT입니다. 현물 시세를 제공하는 31개 통화 중 원하는 통화의 심볼을 spot()에 전달하세요. 정적 배열은 심볼별로 따로 캐시합니다. 5개 심볼을 표시하는 페이지는 캐시가 없으면 최대 5회 호출하고, 캐시 유효 시간 안에 다시 렌더링하면 저장된 값을 사용합니다.
$client = new GoldpriceClient();// USD spot, default$client->spot('XAU-USD-SPOT');$client->spot('XAU-INR-SPOT');$client->spot('XAU-EUR-SPOT');// Silver in USD$client->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"}CLI는 두 줄을 출력합니다. 첫 줄은 심볼, 통화, 가격, 시각이고, 다음 줄은 BCMath로 계산한 5트로이온스의 가격입니다. 이후 코드는 디코딩한 배열을 사용하며, 가격은 문자열로 유지됩니다.
자주 발생하는 오류
| 코드 | 증상 | 해결 방법 |
|---|---|---|
| 401 | RuntimeException: goldprice: unexpected status 401 발생 | API 키가 없거나 유효하지 않습니다. php -r 'echo getenv("GOLDPRICE_API_KEY");'로 PHP에 환경 변수가 전달되는지 확인하세요. PHP-FPM은 CLI 환경 변수를 공유하지 않습니다. fastcgi_param이나 프로세스 관리자로 키를 설정하세요. 비어 있으면 대시보드에서 다시 복사하세요. |
| 429 | 대기 시간을 늘리며 세 번 재시도해도 모두 429가 반환되고 RateLimitedException 발생 | 분당 호출 한도에 도달했습니다. 일정한 트래픽에는 60초 캐시가 도움이 됩니다. PHP-FPM의 정적 캐시는 요청마다 별개이므로 APCu(apcu_fetch / apcu_store)로 바꿔 요청 간 공유하세요. 지속적으로 많은 호출이 필요하면 /pricing에서 유료 플랜을 확인하세요. |
| N/A | 가격을 float로 변환해 계산하면 반올림 오차가 발생함 | 계산 전에 가격을 (float)로 변환하지 마세요. PHP의 부동소수점 값은 합산 시 정밀도가 떨어집니다. API가 반환한 문자열을 유지하고 소수 자릿수를 명시해 bcadd, bcmul, bccomp를 사용하세요. 함수를 찾을 수 없으면 bcmath 확장을 활성화하세요. |
더 활용하기
- 정적 캐시를
apcu_store/apcu_fetch로 바꿔 한 번 조회한 값을 모든 PHP-FPM 워커가 60초 동안 사용하도록 구성하세요 /v1/bars?symbol=XAU-USD-SPOT&interval=1d&from=...&to=...용bars()메서드를 추가하고 템플릿 엔진으로 데이터를 차트에 표시하세요spot()을 간단한 Laravel 또는 Symfony 서비스로 감싸고 컨테이너에 등록해 의존성을 주입하세요- 여러 워커가 같은 심볼을 조회한다면
If-None-Match/ ETag 검사로 변경되지 않은 응답 본문을 건너뛰세요 bcdiv로 트로이온스를 g으로 환산해 소매용 g당 가격을 표시하세요