전체 글 보기
8 분 소요

toncenter 429 "Too Many Requests" 오류를 없애는 방법

toncenter의 429 Too Many Requests 오류가 왜 AI 에이전트를 가장 세게 때리는지, 백오프로 빠르게 줄이는 법, 그리고 보장된 처리량을 주는 전용 키라는 진짜 해법까지 정리했습니다.

toncenter429 오류TON rate limitTON MCPTONNodeTON AI 에이전트

TON 위에서 도는 토큰 에이전트는 늘 최악의 순간에 죽습니다. 사용자가 "내 잔액이랑 최근 거래 좀 보여줘"라고 하면 에이전트는 정직하게 toncenter로 갑니다. 그런데 돌아오는 건 데이터가 담긴 JSON이 아니라 건조한 HTTP 429 Too Many Requests 한 줄입니다. 에이전트는 한 틱에 지갑 잔액과 계정 상태, 트랜잭션 이력을 모으고 get 메서드도 두어 개 두드리려 했을 뿐인데, 공개 toncenter는 두 번째 요청에서 문을 닫아버립니다. 사용자에게는 "문제가 발생했습니다"가 보이고, 여러분에게는 똑같은 상태 코드로 도배된 빨간 로그 벽이 보입니다. 이건 여러분 코드의 버그가 아닙니다. toncenter의 공개 rate limit이고, 초당 한 요청보다 조금이라도 활발하게 움직이는 에이전트라면 예외 없이 여기에 부딪힙니다.

toncenter 429가 어디서 나오는지, 왜 하필 AI 에이전트가 TON에서 Too Many Requests를 가장 자주 얻어맞는지, 백오프로 오류 빈도를 빠르게 떨어뜨리는 법, 그리고 보장된 처리량을 주는 전용 키로 넘어가 천장 자체를 없애는 법까지 차례로 살펴보겠습니다.

toncenter의 429 "Too Many Requests"는 무슨 뜻인가

429는 "요청이 너무 많다"는 뜻의 표준 HTTP 응답입니다. 서버가 고장 난 것도, 여러분이 보낸 데이터를 거부한 것도 아닙니다. 허용된 호출 빈도를 넘겼으니 속도를 늦추겠다(rate limiting)고 말하는 것뿐입니다. toncenter(v2)라면 이때 응답 본문은 대략 이렇게 생겼습니다.

{ "ok": false, "error": "Rate limit exceeded", "code": 429 }

핵심은 "ok": false"code": 429입니다. 이건 HTTP 상태 코드를 본문에 그대로 복사해 넣은 값이지, 컨트랙트 내부의 오류 코드가 아닙니다. 그리고 한 가지 더 눈여겨볼 점이 있습니다. 계정 데이터가 담기는 result 필드가 아예 없고, 한도 초과 메시지는 error 필드에 들어 있다는 것입니다. 그래서 result에서 데이터를 꺼내려고 만든 코드는 undefined를 받고, 십중팔구 스택 저 아래 어딘가에서 알 수 없는 파싱 오류를 내며 죽습니다. 진짜 원인은 error에 적혀 있는데도 말입니다. 규칙은 간단합니다. ok: false가 오면 존재하지도 않는 result를 파헤칠 것이 아니라, 먼저 code를 확인하고 error를 읽어야 합니다.

속설 하나는 따로 짚고 넘어가겠습니다. TON 커뮤니티에는 "228 오류"라는 말이 돌아다닙니다. 이건 API 코드가 아니라 밈입니다. 어떤 서버도 여러분에게 228을 돌려주지 않습니다. 실제 한도 코드는 429이고, 문서에서 찾아야 할 것도 그것입니다. 429는 일시적 오류입니다. 똑같은 호출이라도 더 천천히 보내거나 유효한 키를 달고 보내면 통과합니다.

키 없이 쓰면 toncenter가 초당 약 1요청만 주는 이유

API 키 없는 공개 toncenter는 여러분을 대략 초당 한 요청으로 묶어둡니다. 버그도, 인색함도 아닙니다. 동시에 수천 명이 쓰는 공용 무료 자원을 지키기 위한 방어입니다. 경험 많은 개발자도 걸려 넘어지는 지점이 두 개 있습니다.

  • 공용 풀이란 익명 트래픽 이야기입니다. 키가 없으면 전 세계에서 날아오는 이름 없는 모든 요청과 함께 약 1 rps짜리 단일 공개 한도를 나눠 씁니다. 피크 시간대에는 실제로 쓸 수 있는 빈도가 그보다 더 낮아질 수도 있습니다.
  • 유료 키는 천장을 올려줍니다 — 단, 그 키가 요청에 실제로 실려 갈 때에 한합니다. 전형적인 함정이 있습니다. 키는 분명히 있는데 HTTP 클라이언트를 리팩터링하는 과정에서 X-API-Key 헤더가 사라져, 다시 공개 한도에 갇힌 채 유료 요금제가 "왜 안 먹히지" 하며 몇 시간을 허비하는 경우입니다.

초당 한 요청은 브라우저에서 손으로 디버깅하거나 1분에 한 번 잔액을 확인하는 스크립트에는 충분합니다. 하지만 자동화라면, 하물며 에이전트라면 치명적으로 부족합니다.

AI 에이전트가 429를 가장 자주 맞는 이유: 버스트 패턴

문제의 핵심은 바로 여기에 있습니다. 보통의 애플리케이션은 요청을 어느 정도 고르게 보냅니다. AI 에이전트는 다릅니다. 버스트(burst, 폭발적 몰림)로 움직입니다. 에이전트는 틱 단위로 동작하는데, 추론 한 스텝에서 컨텍스트를 모아야 하므로 수십 개의 호출을 거의 동시에 연달아 던집니다.

한 스텝을 상상해 봅시다. "결제가 들어왔는지 확인해줘"라는 요청입니다. 여기에 답하려고 에이전트는 순식간에 다음을 연달아 호출합니다.

  1. get_masterchain_info — 블록체인의 현재 헤드 파악;
  2. get_balance — 지갑 잔액;
  3. get_account_state — 계정 상태와 플래그;
  4. get_transactions — 최근 트랜잭션;
  5. run_get_method — 컨트랙트의 get 메서드 읽기;
  6. get_jetton_balance — 겸사겸사 USDT 잔액까지.

한 틱에 여섯 번의 호출. 한도는 초당 하나. 첫 번째는 통과하고 나머지는 429를 돌려받습니다. 그러면 에이전트는 그 자리에 멈춰 서거나, 불완전한 데이터 위에서 환각을 시작합니다. 게다가 이건 "잘못 만든 에이전트"의 문제가 아닙니다. 컨텍스트를 먼저 모으고 그다음에 생각한다는, 자율 추론의 정상적인 아키텍처입니다. 더 나쁜 건, 오류를 받은 에이전트가 그걸 "고쳐보려고" 같은 호출을 다시 던지면서 이미 바닥난 쿼터를 마저 갉아먹는다는 점입니다. 공개 한도는 애초에 이런 부하 프로파일을 감당하도록 설계되지 않았습니다.

TON 글로벌 설정에 들어 있는 공개 라이트서버도 사정이 비슷합니다. 부하가 걸리면 not ready를 뱉거나 ADNL 타임아웃으로 떨어져 나갑니다. 이건 따로 정리해 두었습니다: 라이트서버가 "not ready"를 답하는 이유와 대처법. tonapi.io도 똑같은 429 병을 앓고 있는데, 분석은 여기에 있습니다.

빠른 처방: 지수 백오프 재시도와 Retry-After

지금 당장 해야 할 첫 번째 일은 전속력으로 벽을 들이받는 짓을 멈추는 것입니다. 429가 이미 날아왔다면 곧바로 서버를 다시 두드리지 마세요. 밴이 길어질 뿐입니다. 이건 대증요법입니다. 429의 빈도는 줄여주지만 천장을 올려주지는 않습니다. 제대로 된 대증요법은 네 부분으로 이뤄집니다.

1. 지터를 섞은 지수 백오프. 다음 시도는 앞선 시도보다 더 오래 기다리게 하고, 거기에 무작위 값을 얹으세요. 병렬 워커들이 서로 동기화되어 같은 1초에 몰려드는 일을 막기 위해서입니다.

async function fetchWithBackoff(url, opts = {}, maxRetries = 5) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const res = await fetch(url, opts);
    if (res.status !== 429) return res;

    // 서버가 준 Retry-After를 우선 사용, 없으면 지터를 섞은 지수 백오프
    const retryAfter = res.headers.get("Retry-After");
    const baseMs = retryAfter
      ? Number(retryAfter) * 1000
      : Math.min(1000 * 2 ** attempt, 16000);
    const jitter = Math.random() * 300;
    await new Promise((r) => setTimeout(r, baseMs + jitter));
  }
  throw new Error("toncenter: 재시도해도 429가 풀리지 않았습니다");
}

2. Retry-After 헤더가 왔다면 존중하세요. toncenter는 429에 이 헤더를 대개 붙여주지 않으므로, 승부는 여러분이 만든 백오프 공식에 걸어야 합니다. 그래도 서버가 얼마나 기다리라고 알려줬다면 추측하지 말고 딱 그만큼 기다리세요(위 코드의 if (retryAfter) 분기가 하는 일이 그것입니다).

3. 동시성을 제한하세요. toncenter 앞에 초당 약 1요청 이상은 내보내지 않는 큐나 세마포어를 두세요. 그러면 에이전트의 버스트가 시간축으로 펴집니다. 앞서 본 여섯 개 호출 목록이 순차적으로, 약 6초에 걸쳐 실행되지만 429는 한 번도 나지 않습니다.

4. 반복되는 읽기는 캐시하세요. get_masterchain_info는 한 스텝 안에서 한 번만 요청해 재사용하면 됩니다. jetton 메타데이터(decimals, 심볼)는 변하지 않으니 한 번만 읽으세요. 300 ms 전에 읽은 잔액이 그새 바뀌었을 가능성은 거의 없습니다.

이 방법들은 실제로 효과가 있고 에이전트를 훨씬 예의 바르게 만들어 줍니다. 다만 솔직하게 인정합시다. 백오프는 천장을 올려주지 않습니다. 여러분은 여전히 1 rps에 갇혀 있고, 이제 쓰러지는 대신 얌전히 줄을 서 있을 뿐입니다. 밀리초면 끝날 일에 사용자는 몇 초를 기다립니다. 반응성이 생명인 에이전트 입장에서 이건 병이 아니라 증상만 치료하는 셈입니다. 공개 API를 우회하는 다른 방법들은 2026년 toncenter 대안 모음에 정리해 두었습니다.

진짜 해법: 전용 키, 그리고 MCP로 만나는 TON

문제의 뿌리는 여러분이 좁은 공개 채널을 수천 개의 익명 요청과 나눠 쓴다는 데 있습니다. 429를 진짜로 없애는 유일한 길은 공용 쿼터 대신 보장된 전용 처리량을 갖는 것입니다. 그러면 여섯 개짜리 에이전트 버스트가 다섯 번째에서 벽에 부딪히는 대신 통째로 통과하고, 에이전트는 전속력으로 컨텍스트를 모을 수 있습니다. 백오프 재시도는 네트워크 장애에 대비한 보험으로 남지만, 더 이상 생존의 주된 수단은 아니게 됩니다.

여기에 더해 HTTP 상태 코드와 씨름하는 일 자체를 없애는 길도 있습니다. TON 데이터가 필요한 주체가 다름 아닌 AI 에이전트라면, 파싱하고 429까지 처리해야 하는 raw REST 응답보다 MCP를 통해 완성된 도구로 넘겨주는 편이 자연스럽습니다.

MCP(Model Context Protocol)는 AI 에이전트(Claude, Cursor, ChatGPT/Codex를 비롯한 모든 MCP 클라이언트)가 외부 도구를 호출하는 방식을 정한 표준입니다. 에이전트에게 toncenter로 보낼 HTTP 요청을 올바르게 만드는 법, 429를 잡는 법, Retry-After를 읽는 법, JSON을 파싱하는 법을 가르치는 대신 타입이 정해진 도구를 쥐여주면, 네트워크와 관련된 궂은일은 전부 서버가 떠맡습니다.

TONNode는 TON 전용 hosted MCP 서버이며 도구는 정확히 16개입니다. 에이전트가 보통 toncenter 한도를 뚫어버리는 그 여섯 가지 읽기 작업은 여기서 이미 만들어진 호출로 존재합니다.

  • get_masterchain_info — 마스터체인의 헤드;
  • get_balance — GRAM 잔액;
  • get_account_state — 상태, 플래그, 마지막 트랜잭션;
  • get_transactions — 트랜잭션 이력;
  • run_get_method — 컨트랙트의 임의 read-only get 메서드;
  • get_jetton_balance — jetton 또는 USDT 잔액(jetton 지갑 주소는 온체인에서 계산됩니다).

(참고로 GRAM은 2026년 6월에 이름이 바뀐 Toncoin입니다. 네트워크는 여전히 TON이라 불리고, 바뀐 건 코인 이름뿐입니다.)

내부적으로 @tonnode/mcp 패키지는 TON 네이티브 프로토콜, 즉 ADNL로 HTTP 중간 계층 없이 동작합니다. 다시 말해 REST 엔드포인트 하나를 다른 REST 엔드포인트로 바꾸는 수준이 아닙니다. 에이전트가 네트워크와 직접 대화하고, 여러분은 한도와 얽힌 HTTP 시맨틱을 직접 처리하는 일에서 벗어납니다. 패키지는 오픈소스(MIT)이며 npm과 GitHub(tonnode/mcp)에 올라와 있습니다.

실전에서의 차이는 이렇습니다. 에이전트는 더 이상 429가 무엇인지, Retry-After가 무엇인지, ADNL 타임아웃이 무엇인지 알 필요가 없습니다. "이 주소의 잔액과 최근 트랜잭션을 줘"라고 말하면 구조화된 응답을 받습니다. 똑같은 여섯 개짜리 버스트가 공용 공개 한도가 아니라, 여러분의 키에 묶인 처리량을 가진 서버로 향합니다.

연결 방법과 무료로 시작하는 법

길은 두 가지이고, 아예 가입 없이 시작할 수도 있습니다.

무료로, 로컬에서

공개 설정만으로 읽기 도구 전체를 쓸 수 있습니다. 여러분이 쓰는 MCP 클라이언트 설정에 다음을 넣기만 하면 됩니다.

{
  "mcpServers": {
    "ton": {
      "command": "npx",
      "args": ["-y", "@tonnode/mcp"]
    }
  }
}

키는 필요 없고 npx가 알아서 패키지를 가져옵니다. 에이전트가 429 한 번 없이 TON을 읽는다는 사실을 직접 확인해보기에는 이걸로 충분합니다. 자세한 설명은 TON용 MCP 무료로 쓰기 가이드에 있습니다.

전용 키를 붙인 hosted 엔드포인트

실제 부하를 감당할 보장된 처리량이 필요해지면, 자기 키를 달고 hosted 엔드포인트에 연결합니다.

{
  "mcpServers": {
    "ton": {
      "type": "http",
      "url": "https://mcp.tonnode.io/mcp",
      "headers": { "Authorization": "Bearer tn_live_…" }
    }
  }
}

그다음부터는 그냥 사람 말로 에이전트와 대화하면 됩니다. 필요한 도구는 에이전트가 알아서 고릅니다.

"EQC… 주소를 확인해줘. get_balance로 잔액을, get_account_state로 계정 상태를, get_transactions로 최근 트랜잭션 10건을 가져와. 그다음 get_jetton_balance로 USDT 잔액도 봐줘."

에이전트는 눈을 감은 채 rate limit에 몸을 던지는 대신, 필요한 도구를 필요한 순서로 호출합니다.

요금제

모든 요금제에서 16개 도구를 전부 쓸 수 있습니다. 여러분이 지불하는 건 오직 처리량입니다.

요금제 가격 처리량
Hobby 영구 무료 분당 60 요청
Pro 월 $29 분당 300 요청
Scale 월 $199 분당 1200 요청

분당 60 요청짜리 무료 Hobby조차 약 1 rps인 공개 toncenter와는 전혀 다른 세계입니다. 분당 요청 수는 얼추 비슷해 보여도, 이쪽은 익명 무리와 나눠 쓰는 몫이 아니라 보장된 여러분의 몫입니다. 호출 열 개짜리 에이전트 버스트도 429 한 번 없이 통째로 통과합니다. Hobby 키는 로그인 직후 카드 없이 발급됩니다.

유료 요금제 결제는 TonConnect를 통해 TON 네트워크의 GRAM 또는 USDT로 하거나, Telegram의 xRocket 계정을 통해 BTC/ETH/SOL 등으로 할 수 있습니다.

기대치가 부풀지 않도록 솔직한 단서를 몇 가지 답니다. TONNode는 지금 읽기와 트랜잭션 구성 작업을 담당하지만, pay-per-request나 REST API v2, 웹훅, SSE 스트림, 가동률 퍼센트가 적힌 서면 SLA는 완성된 제품으로 제공하지 않습니다. 깊은 이력을 가진 아카이브 노드는 아직 동기화 중이며, 이건 오늘의 보장이 아니라 로드맵 항목입니다. 위에서 설명한 것들은 지금 이미 동작합니다.

현실적인 전환 계획

  1. 무료 Hobby 키를 받으세요(분당 60 요청, 카드 불필요): tonnode.io/dashboard?plan=hobby.
  2. 위의 hosted 설정을 여러분의 MCP 클라이언트에 넣으세요.
  3. 손으로 짠 toncenter 호출을 get_balance, get_account_state, get_transactions, run_get_method, get_jetton_balance 도구로 교체하세요.
  4. 부하가 늘어 에이전트가 분당 60 요청에 부딪히는 순간, 월 $29짜리 Pro(분당 300 요청)로 넘어가세요: tonnode.io/pricing.

정리

  • toncenter의 429 "Too Many Requests"는 여러분 코드가 망가졌다는 뜻이 아니라 약 1 rps짜리 공개 한도에 부딪혔다는 신호입니다. (그리고 이건 확실히 "228"이 아닙니다. 그런 코드는 존재하지 않습니다.)
  • AI 에이전트가 이 오류를 가장 자주 맞는 이유는 버스트 패턴입니다. 추론 한 틱에 수십 번의 호출이 나갑니다.
  • 지수 백오프 재시도, Retry-After, 세마포어, 캐시는 429의 빈도를 낮춰주지만 천장은 움직이지 않습니다. 대가는 속도입니다.
  • 진짜 출구는 보장된 처리량을 주는 전용 키입니다. 그리고 그 데이터가 다름 아닌 에이전트에게 필요한 것이라면, TONNode는 똑같은 TON 읽기를 MCP 도구로 넘겨주고 "429를 어떻게 처리하지"라는 질문은 여러분 코드에서 그냥 사라집니다.

무료로 시작하세요: Hobby 키 받기 — 분당 60 요청, 카드 불필요. 에이전트에 실제 부하가 걸리고 버스트가 촘촘하다면 처음부터 월 $29, 분당 300 요청의 Pro를 택하세요.

에이전트에게 TON 접근 권한을 주세요

16가지 MCP 도구: 읽기, 논커스터디얼 스왑, 크로스체인, 지갑. 무료 요금제 60 요청/분, 카드 불필요.