TON에 멤풀이 있을까? 블록에 담기기 전에 볼 수 있는 것
TON에 멤풀이 있을까? Bitcoin 같은 단일 글로벌 풀은 없습니다. 노드가 블록 이전에 보는 것, toncenter의 pending이 에뮬레이션인 이유, 멤풀 스트림이 보여줄 수 있는 것과 없는 것.
개발자 채팅에서 "TON에 멤풀이 있나요?"라고 물으면 자신만만한 답이 두 가지 돌아옵니다. 하나는 "아니요, TON에는 멤풀이 없습니다." 다른 하나는 "있습니다, toncenter의 pending 트랜잭션이 여기 있잖아요." 둘 다 어떤 면에서는 맞습니다. TON에는 Bitcoin처럼 모든 노드가 보관하고 합의하는 네트워크 전체의 단일 미확인 트랜잭션 풀이 없습니다. 하지만 메시지는 블록에 담기기 전에도 분명히 존재하고, 노드는 그것을 보며, 몇몇 API는 그 창을 들여다보게 해 줍니다.
이 글에서는 TON에서 이 단어가 무엇을 뜻하는지, toncenter의 "pending"이 왜 에뮬레이션인지, 블록 이전 메시지 스트림이 무엇을 말해 줄 수 있고 없는지, 그리고 TONNode 멤풀 스트림이 어떻게 동작하는지를 한계부터 설명합니다.
TON에서 "멤풀"이 뜻하는 것
Bitcoin이나 Ethereum에서 멤풀은 구체적인 실체입니다. 모든 풀 노드가 미확인 트랜잭션 집합을 보관하고, 피어에게 전파하며, 블록 생산자는 보통 수수료 기준으로 그중에서 고릅니다.
TON은 다른 단위에서 출발합니다. 사용자는 "트랜잭션"을 보내지 않습니다. 지갑 앱이 외부 메시지(external message)에 서명해 노드에 건넵니다. docs.ton.org의 표현을 빌리면 "외부 메시지는 블록체인 바깥에서 보내지며, 따라서 선택적인 외부 발신자 주소만 가진다"입니다. 수신 컨트랙트, 즉 사용자의 경우 지갑 컨트랙트가 서명과 시퀀스 번호를 확인하고 ACCEPT를 호출해야 비로소 트랜잭션이 생깁니다. "들어오는 외부 메시지가 처리될 때, 트랜잭션은 컨트랙트가 그 메시지를 수락하는 경우에만 생성된다."
여기서 세 가지 결과가 따라오며, 이것이 "TON 멤풀"이 프로토콜 객체가 아니라 느슨한 표현인 이유입니다.
- 입찰할 것이 없습니다. 외부 메시지에는 발신자의 지불이 실려 있지 않습니다. 목적지 컨트랙트가 수락한 뒤에 가스를 내며, 그 전에 메시지를 검사할 수 있도록 가스 크레딧을 씁니다. 메시지에 가격이 없으니 가격순으로 정렬되는 큐도 없습니다.
- 단일 큐가 없습니다. TON은 샤딩되어 있습니다. 계정은 주소가 시작하는 접두사의 샤드체인에 속하고, 지갑으로 보내는 메시지는 그 샤드의 블록을 만드는 노드에게만 의미가 있습니다. 외부 메시지를 받은 노드는 공개 오버레이에 브로드캐스트하고, 문서는 "검증자들은 이를 서로 공유하며, 실수로(또는 의도적으로) 여러 번 전달할 수 있다"고 적습니다. 각 노드는 자기가 들은 것을 보관할 뿐, 합의된 집합은 어디에도 없습니다.
- 거부된 메시지는 흔적을 남기지 않습니다. 서명이 틀렸거나, seqno가 이미 쓰였거나,
valid_until이 지났거나, 지불할 잔액이 없어 컨트랙트가 수락하지 않으면 트랜잭션은 만들어지지 않고 어떤 블록도 그 시도를 기록하지 않습니다.
그래서 누군가 "TON 멤풀"이라고 말할 때 정직한 풀이는 이렇습니다. 어떤 노드가 받아서 브로드캐스트했지만 아직 어떤 블록에도 담기지 않은 외부 메시지들. 몇 초짜리 창이고, 노드마다 다르게 보이며, 그 안의 일부는 영원히 실행되지 않습니다. 멤풀 스트림이 보여주는 것이 바로 이 창입니다.
toncenter의 "pending"이 에뮬레이션인 이유
toncenter v3 API에는 GET /api/v3/pendingTransactions가 있고, "지정한 필터에 맞는 pending 트랜잭션을 조회한다"로 문서화되어 있으며 계정이나 trace id로 필터링합니다. Streaming API는 finality 필드가 pending, confirmed, finalized 중 하나인 이벤트를 전달하고, 첫 단계를 정확히 정의합니다. "pending — 에뮬레이션 또는 투기적 실행의 결과. 이 상태는 무효화될 수 있다."
toncenter의 pending 트랜잭션은 노드의 큐에서 건져 올린 것이 아닙니다. 인덱서가 외부 메시지를 가져와 검증자가 할 법한 방식으로 현재 계정 상태에 대해 실행해 보고, 예측된 트랜잭션과 그것이 만들 액션을 게시합니다. 실제 블록이 도착하면 이벤트는 confirmed로, 이후 finalized로 다시 발행되고, 예측이 틀리면 trace_invalidated 알림이 뒤따릅니다. 구독은 주소 단위입니다. WebSocket의 subscribe 연산은 addresses 목록을 받으며, 이는 "trace만 구독할 때는 비워둘 수 있지만, trace가 아닌 이벤트 유형에는 필수"입니다.
이는 대부분의 제품이 묻는 질문, 즉 "내 사용자의 결제가 통과했는가, 그리고 1초 먼저 보여줄 수 있는가"에 훌륭한 답입니다. 다만 네트워크의 블록 이전 원시 흐름, 즉 에뮬레이션되기 전의 모든 지갑의 모든 메시지는 주지 않습니다. 이 둘은 서로 다른 제품입니다.
TON 멤풀 스트림이 보여줄 수 있는 것과 없는 것
멤풀 스트림은 또 다른 제품입니다. 외부 메시지를 듣는 순간 그대로 전달하는 노드죠. 그 위에 무언가를 만들기 전에는 기능보다 한계가 중요합니다. 아래는 멤풀 문서의 데이터 품질 절에서 가져온 내용입니다.
커버리지는 부분적입니다. 스트림에는 한 노드가 공개 오버레이에서 받은 것만 담깁니다. 그 노드에 닿지 않은 메시지는 스트림에 없고, 스트림에 없다는 사실은 아무것도 증명하지 않습니다. TONNode는 완전성이나 속도 수치를 공개하지 않으며 메시지를 가장 먼저 본다고 주장하지 않습니다.
pending은 포함을 뜻하지 않습니다. checked 메시지는 노드의 브로드캐스트 검사를 통과한 것이지 검증자의 실행을 통과한 것이 아닙니다. 2026년 10월의 90분 표본에서 checked 메시지 다섯 개 중 대략 하나는 끝내 체인에 수락되지 않았습니다.
이른 메시지는 검증되지 않았습니다. 노드의 가장 이른 훅은 브로드캐스트 서명 검사 이전, 즉 오버레이의 어떤 피어든 바이트를 주입할 수 있는 지점에서 실행됩니다. 스트림은 이를 "path":"early","unverified":true로, 기본값으로 전달합니다. 어떤 용도에서는 앞선 시간이 확실성보다 중요하기 때문입니다. 자동으로 동작하는 모든 것은 "include_unverified":false를 보내거나, 같은 cell_hash의 checked 사본을 기다려야 합니다.
parsed는 최선의 노력입니다. 디코딩된 지갑 본문(v4r2, v5r1, highload_v3, 제톤 전송, DEX 스왑)은 메시지 바이트만으로 추론되므로, 지갑 레이아웃을 흉내 낸 컨트랙트는 잘못 라벨링될 수 있습니다.
중복이 발생합니다. 같은 cell_hash가 early로 왔다가 다시 checked로, 재연결 뒤에 또, 드물게는 중복 제거 창 이후에도 올 수 있습니다. 처리는 cell_hash 기준으로 멱등해야 합니다.
일부 메시지는 의도적으로 버려집니다. 65,535바이트를 넘는 BoC, 외부 메시지가 아닌 BoC, 단순 addr_std가 아닌 목적지가 그렇습니다.
이 중 하나라도 여러분의 용도를 깨뜨린다면 필요한 것은 멤풀이 아니라 확정된 트랜잭션입니다. 들어오는 USDT 결제 감지가 대표적인 예입니다. 결제는 블록 안의 트랜잭션이며, 그 전의 어떤 것도 주문을 결제 완료로 표시해서는 안 됩니다.
TONNode 멤풀 스트림의 동작 방식
TONNode의 스트림은 WebSocket 하나, wss://mempool.tonnode.io/v1/stream입니다. 서버는 Authorization: Bearer tnmp_…로 인증합니다. 브라우저는 헤더를 설정할 수 없으므로, 키를 가진 백엔드가 POST /v1/ticket에 30초짜리 일회용 티켓을 요청하고, 반환된 서브프로토콜을 new WebSocket(url, subprotocols)에 넘깁니다. 모든 연결의 첫 메시지는 hello이며, 문서에서 그대로 옮겼습니다.
{"v":1,"type":"hello","contract":"1.1","epoch":"9f3c1a7be2d04c11","head_seq":123456,"oldest_seq":118020,
"ts_gw_us":1791322891600000,"key_id":"0123456789ab",
"limits":{"max_conn":3,"max_filters":null,"delay_ms":0,"replay_limit":null}}클라이언트가 구독하기 전에는 아무것도 전달되지 않습니다. 필터는 선택 사항이며 OR로 결합됩니다. dest(보내는 지갑), out_dest(지갑이 보내는 곳), op(제톤 전송의 0x0f8a7ea5 같은 op 코드), pool(DeDust 풀). "filters":{}는 전체 스트림이고, 구독 하나는 최대 10,000개 항목을 담으며, 이후의 subscribe는 재생 없이 필터를 교체합니다. 네 가지 필터를 모두 쓰고 이른 메시지를 제외하는 구독은 다음과 같습니다.
{"v":1,"type":"subscribe",
"filters":{"dest":["0:2a18ac1734f34579e6a6c2a9e738bb5799d21e7a73ef106895c00c34549a9167"],
"out_dest":["EQB3ncyBUTjZUA5EnFKR5_EnOMI9V1tTEAAPaiU71gc4TiUt"],
"op":["0x0f8a7ea5"],
"pool":["0:a0d1bc3a139cbc6b39a3e3633f74476be441343f9d0fd88b949fca0327b65a75"]},
"include_unverified":false}서버는 적용된 고유 항목 수와 전달이 시작되는 지점으로 확인해 줍니다.
{"v":1,"type":"subscribed","filters":4,"include_unverified":false,"from_seq":123451}그 뒤로는 메시지당 JSON 객체 하나가 seq 순서로 도착합니다. 원시 boc, 해시들(cell_hash, TEP-467 정규화 norm_hash, sha256), 목적지 지갑, path와 unverified, 타임스탬프 두 개, 그리고 본문 레이아웃이 인식되면 지갑 유형, seqno, valid_until, 나가는 전송과 스왑이 담긴 parsed입니다.
재생. 서버는 최근 약 60초의 이벤트를 최대 64 MiB까지 보관합니다. 연결이 끊기면 재연결해 epoch와 마지막으로 처리한 seq를 담아 resume을 보내면, 놓친 것을 새 필터를 거쳐 받습니다. gap 이벤트는 무엇이 건너뛰어졌고 왜인지 알려줍니다. slow, source_reconnect, ring.
요금제. 키 하나의 동시 연결 수 외에는 아무것도 측정하지 않습니다. Test는 7일, 연결 1개, $5. Start는 30일, 연결 1개, $15. Pro는 30일, 연결 3개, $30. Business는 30일, 연결 10개, $100. 그 이상은 문의. 메시지 쿼터 없음, 추가 지연 없음, 무료 요금제 없음. 키는 콘솔에서 노드 요금제와 같은 잔액으로 구매하며, 전체 표는 요금 페이지에 있습니다.
스트림에 없는 것. TONNode 자체 라이트서버를 통해 보낸 메시지는 멤풀 구독자에게 중계되지 않습니다. TONNode 노드 키로 보내면 그 트랜잭션은 이 스트림에 나타나지 않습니다. 자신이 통제하는 지갑을 관찰하려면 다른 경로로 보내거나 체인에서 자신의 전송을 읽으십시오.
Node.js, Python, Go로 된 완전한 소비자 코드, 티켓을 쓰는 브라우저 흐름, 오류 코드는 멤풀 스트림 문서에 있습니다.
TonAPI 스트리밍과 toncenter 스트리밍, 솔직한 비교
블록 이전 창을 다루는 서비스는 셋이며, 서로 대체할 수 없습니다. TonAPI Streaming API는 GET /v2/sse/mempool과 선택적 계정 필터가 있는 WebSocket subscribe_mempool 메서드를 제공했지만, 자체 문서는 이제 "Streaming API is deprecated — please use Webhooks API for real-time updates"로 시작합니다. Toncenter Streaming API는 wss://toncenter.com/api/streaming/v2/ws에서 트랜잭션, 액션, 트레이스, 상태 변화를 최종성 수준과 함께 전달합니다. pending 이벤트는 에뮬레이션되며 무효화될 수 있고, 구독은 트레이스를 제외한 모든 것에 주소를 요구합니다.
| TonAPI 스트리밍 | Toncenter 스트리밍 | TONNode 멤풀 스트림 | |
|---|---|---|---|
| 자체 문서 기준 상태 | 사용 중단; webhooks 권장 | 현행 | 현행 |
| "pending"의 의미 | 멤풀 메시지 | 에뮬레이션된 트랜잭션 또는 액션; 무효화될 수 있음 | 원시 외부 메시지; 실행되지 않음 |
| 범위 | 멤풀 피드, 계정 필터 선택 | 트레이스를 제외하고 주소 필수 | 전체 스트림, 또는 최대 10,000개 항목 필터 |
| 최종성 | 멤풀 피드에는 해당 없음 | pending, confirmed, finalized | 없음; 체인에서 확인 |
| 끊김 후 재생 | 문서화되지 않음 | 문서화되지 않음 | resume으로 최근 약 60초 |
셋 중 어느 것도 커버리지를 비교할 수 있는 수치를 공개하지 않습니다. 결정하기 전에 자신의 트래픽으로 측정하십시오.
멤풀 스트림이 필요한 사람과 필요 없는 사람
아마 필요할 경우:
- DEX나 트레이딩 봇을 운영하고, 스왑이 브로드캐스트되고 실행되기까지의 몇 초가 여러분의 우위라면. 단, 무엇이든 움직이기 전에
include_unverified:false나 확인 단계를 둬야 합니다; - 지갑 집합이나 풀을 지켜보며, 블록이 도착할 때가 아니라 브로드캐스트되는 순간에 전송이나 스왑을 보고 싶다면;
- 네트워크를 연구한다면: 메시지 빈도, 지갑 버전, 바쁜 DEX 라우터, 끝내 실행되지 않는 메시지의 수.
필요 없을 경우:
- 결제를 감지한다면. 결제는 블록 안의 트랜잭션입니다.
get_transactions로 읽고, pending 메시지로 주문을 결제 완료로 표시하지 마십시오; - 잔액이나 내역을 보여준다면. 멤풀에는 상태가 없습니다. LiteServers 장과 lt와 해시로 보는 트랜잭션 내역을 쓰십시오;
- 모든 메시지가 필요하거나 TONNode 라이트서버를 통한 자신의 전송을 봐야 한다면. 커버리지는 오버레이의 본성상 부분적이고, 자신의 전송은 설계상 스트림에 없습니다.
트레이딩 사례라면 TON 트레이딩 에이전트 만들기가 멤풀 피드 앞단에 놓일 읽기, 견적, 스왑 루프를 다룹니다.
FAQ
TON에 멤풀이 있을까?
단일 글로벌 멤풀은 없습니다. TON에는 모든 노드가 보관하고 합의하는 네트워크 전체의 미확인 트랜잭션 풀이 없습니다. 존재하는 것은 특정 노드가 공개 오버레이에서 받았지만 아직 블록에서 보지 못한 외부 메시지의 집합이며, 노드마다 다르고, 몇 초 동안만 유지되며, 영원히 실행되지 않을 메시지를 포함합니다.
TON의 대기 중 트랜잭션을 볼 수 있을까?
예, 두 가지 의미에서 그렇습니다. Toncenter는 외부 메시지를 현재 상태에 대해 에뮬레이션해 만든 pending 트랜잭션과 액션을 주소별로 보여주며, 나중에 무효화할 수 있습니다. TONNode 같은 멤풀 스트림은 노드가 듣는 그대로의 원시 외부 메시지 자체를 어떤 실행보다도 먼저 보여줍니다. 둘 다 확정된 트랜잭션은 아니며, 그것은 오직 블록뿐입니다.
pending 메시지가 왜 블록에 없을까?
트랜잭션은 수신 컨트랙트가 메시지를 수락할 때만 생성되기 때문입니다. 지갑은 잘못된 서명, 이미 쓰인 seqno, 만료된 valid_until, 지불할 수 없는 메시지를 거부하고, 거부된 메시지는 체인에 흔적을 남기지 않습니다. 메시지는 그 샤드의 블록을 만드는 노드에 닿기 전에 유실될 수도 있습니다. 2026년 10월의 90분 표본에서 checked 메시지 다섯 개 중 대략 하나는 끝내 수락되지 않았습니다.
TON 멤풀 스트림은 완전할까?
아니요, 어떤 스트림도 완전할 수 없습니다. TONNode 스트림에는 한 노드가 공개 오버레이에서 받은 것만 담기고, 그 노드에 닿지 않은 메시지는 스트림에 없습니다. TONNode는 완전성이나 속도 수치를 공개하지 않으며 메시지를 가장 먼저 본다고 주장하지 않습니다. 스트림에 없다는 것이 어떤 일이 일어나지 않았다는 증거가 되지는 않습니다.
스트림의 "unverified"는 무슨 뜻일까?
노드의 브로드캐스트 서명 검사 이전, 오버레이의 어떤 피어든 바이트를 주입할 수 있는 지점에서 기록된 이른 메시지로, 쓰레기 데이터나 위조일 수 있습니다. 이른 메시지는 기본값으로 전달되며, "include_unverified": false로 구독하면 노드의 브로드캐스트 검사는 통과했지만 아직 검증자가 실행하지 않은 checked 메시지만 받습니다.
TONNode 멤풀 스트림 비용은 얼마일까?
요금제는 키 하나의 동시 연결 수로 정해집니다. Test는 7일에 연결 1개로 $5, Start는 30일에 연결 1개로 $15, Pro는 30일에 연결 3개로 $30, Business는 30일에 연결 10개로 $100입니다. 메시지 쿼터, 추가 지연, 무료 요금제는 없습니다.
연결하기 전에
데이터 품질 절을 한 번 더 읽고, 이른 메시지가 정말 필요한지 결정하고, 처리를 cell_hash 기준으로 멱등하게 만들고, 돈이 움직이기 전에 체인에서 확인하십시오. 그래도 맞는다면 Test 키는 요금 페이지에서 7일에 $5입니다. 아니라면 확정된 상태를 읽는 프라이빗 라이트서버 액세스가 대부분의 제품에 실제로 필요한 도구입니다.

