---
title: "과거 Solana 토큰 잔액 조회 기능 소개"
description: "getTokenAccountsByOwnerAtSlot은 지갑이 과거 특정 시점에 보유했던 모든 항목을 정확한 잔액과 함께 단 한 번의 호출로 반환합니다."
---

# 과거 Solana 토큰 잔액 조회 기능 소개

<ImageBlock
  src="https://media.alchemy.com/gTABOAS.png"
  alt="getTokenAccountsByOwnerAtSlot — 과거 Solana 토큰 잔액"
  width={1920}
  height={900}
  priority
/>

Solana 지갑에게 오늘 무엇을 보유하고 있는지 물으면 어떤 노드든 한 번의 호출로 답할 수 있습니다. 하지만 작년 봄에 무엇을 보유하고 있었는지, 또는 탈취당하기 직전 정확한 순간에 무엇을 보유하고 있었는지 물으면 그 쉬운 방법이 사라집니다. 노드는 현재 잔액만 제공합니다. 누가 언제 무엇을 보유했는지에 대한 기록을 유지하지 않습니다. 그래서 "이 지갑이 그때 무엇을 보유하고 있었는가"에 대한 정직한 답은 지금까지 "직접 재구성하라"였습니다.

오늘 그 상황을 바꿉니다. [`getTokenAccountsByOwnerAtSlot`](https://www.alchemy.com/docs/chains/solana/solana-api-endpoints/get-token-accounts-by-owner-at-slot)은 과거 어느 시점에 지갑이 보유했던 모든 것을 정확한 잔액과 함께 단 한 번의 호출로 반환합니다.

## 과거를 재구성하는 문제

표준 [`getTokenAccountsByOwner`](https://www.alchemy.com/docs/chains/solana/solana-api-endpoints/get-token-accounts-by-owner)은 단 하나의 질문에만 답합니다: 이 지갑이 지금 무엇을 보유하고 있는가. 대부분의 실시간 앱 흐름에는 이것으로 충분하지만, 답할 수 없는 질문들이 한 부류 남아 있습니다.

과거 잔액을 직접 재구성하려면 계정의 이력을 처음부터 재생해야 합니다. [`getSignaturesForAddress`](https://www.alchemy.com/docs/chains/solana/solana-api-endpoints/get-signatures-for-address)로 지갑의 전체 서명 이력을 가져오고, [`getTransaction`](https://www.alchemy.com/docs/chains/solana/solana-api-endpoints/get-transaction)로 모든 트랜잭션을 조회한 다음, 목표 지점까지 슬롯 단위로 잔액을 다시 계산해야 합니다. 활발히 사용된 지갑이라면 수천 번의 호출과 많은 파싱이 필요하고, 계산이 틀릴 여지도 많습니다. 아카이벌 노드는 과거 상태를 읽는 데 도움이 되지만, "슬롯 X에서 이 소유자의 토큰 계정 목록을 달라"는 질문에 직접 답하지는 않습니다.

## 작동 방식

이 메서드는 `getTokenAccountsByOwner`에서 이미 익숙한 문법을 그대로 유지하면서 한 가지를 추가합니다: `slot`입니다. 슬롯은 Solana의 시계로, 대략 하나의 블록에 해당하므로, 슬롯을 전달한다는 것은 "이 지갑이 그 역사적 시점에 정확히 어떤 상태였는지 알려달라"는 뜻입니다.

이 메서드를 호출하면 지갑의 **토큰 계정**, 즉 지갑이 보유한 각 토큰을 담고 있는 개별 레코드를 반환받습니다. Solana에서는 지갑이 잔액을 직접 보유하지 않으므로, 이 계정들을 나열하는 것이 곧 보유 내역을 읽는 방법입니다. 각 계정에는 잔액과 **lamports**가 함께 제공되는데, lamports는 모든 계정이 온체인에 존재하기 위해 지니고 있는 소량의 SOL(코인의 일부 단위로, 1 SOL은 10억 lamports)입니다. 이 메서드는 Solana의 두 토큰 표준을 모두 다룹니다: 사실상 USDC 같은 잘 알려진 모든 토큰의 기반이 되는 원조 표준인 **SPL Token**, 그리고 전송 수수료와 기밀 잔액 같은 추가 기능을 갖춘 더 새로운 버전인 **Token-2022**입니다. 이 두 표준은 서로 다른 프로그램 ID 아래에 있으므로, 단일 `programId` 필터는 해당 프로그램의 계정만 반환합니다.

이 호출 뒤에는 지속적으로 구축되는 이력 인덱스, 즉 누가 어떤 계정을 얼마나, 어느 슬롯 사이에 보유했는지를 시간에 따라 버전별로 기록한 데이터가 자리하고 있으며, 새 블록이 생성될 때마다 최신 상태로 유지됩니다. 쿼리 범위는 두 가지 방식으로 지정할 수 있습니다. mint 기준으로, 과거 특정 슬롯에서 단일 토큰의 잔액을 읽을 수 있습니다. 또는 program 기준으로, 해당 슬롯에서 그 프로그램 아래 소유된 모든 토큰 계정을 나열할 수 있습니다. 두 표준을 아우르는 전체 포트폴리오를 조회하려면, SPL Token 프로그램 ID로 한 번, Token-2022 프로그램 ID로 한 번 호출한 다음 결과를 합치면 됩니다. 아래 예제는 SPL Token으로만 범위를 한정합니다.

<CodeSnippet
  language="javascript"
  code={`const res = await fetch("https://solana-mainnet.g.alchemy.com/v2/{ALCHEMY_API_KEY}", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "getTokenAccountsByOwnerAtSlot",
    params: [
      "89zoESAF7JqYQz5uhf5eYwg3QsKXQy5QFs4WZQ4hMPnb",
      { programId: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" },
      { encoding: "jsonParsed", slot: 80000000 }
    ]
  })
});
console.log(await res.json());`}
/>

`pageKey`이 요청한 슬롯을 고정하므로 페이징은 일관되게 유지됩니다. 페이징하는 동안 체인의 최신 지점은 계속 진행될 수 있지만, 결과는 여전히 동일한 시점을 나타내며, 페이지당 최대 10,000개의 계정을 처리합니다.

## 왜 중요한가

특정 시점의 보유 내역이 일급 쿼리가 됩니다. 직접 구축하고 유지보수해야 했던 인덱싱 파이프라인이 하나의 RPC 호출로 축소되어, 팀이 배관 작업 대신 제품에 집중할 수 있게 됩니다.

이로써 그동안 고통스러웠던 작업들이 가능해집니다:

- 과거 임의 시점의 포트폴리오 및 손익(PnL) 스냅샷
- 특정 슬롯이나 날짜에 연동된 취득원가 및 세무 보고
- 지갑이 탈취당하기 직전 블록에서 무엇을 보유하고 있었는지 보여주는 등의 분쟁, 포렌식, 인시던트 대응 작업
- 재생 없이 정확한 과거 상태가 필요한 분석 및 인덱싱 파이프라인

테스트 과정에서 온체인 실측 데이터와 결과를 대조하여 검증했습니다. 샘플링한 과거 쿼리들은 슬롯 80,000,000에서의 KIN 잔액과 같은 깊은 과거 기록을 포함해, 체인 잔액 및 lamports와 정확히 일치했습니다.

## 시작하기

이 메서드는 표준 Solana mainnet 엔드포인트에서 사용할 수 있으므로, 이미 Alchemy를 통해 Solana RPC를 보내고 있다면 기존 API 키로 바로 호출할 수 있습니다. `https://solana-mainnet.g.alchemy.com/v2/{ALCHEMY_API_KEY}`을 대상으로 지정하고 `slot`를 추가한 다음, 보유 내역을 읽어오면 됩니다.

키를 설정하고 첫 요청을 보내는 방법은 [Solana API 퀵스타트](https://www.alchemy.com/docs/reference/solana-api-quickstart)를 참고하세요.

## FAQ

### getTokenAccountsByOwnerAtSlot은 무엇을 하나요?

지정한 과거 슬롯 시점의 Solana 지갑 토큰 계정을 잔액 및 lamports와 함께 반환합니다. `getTokenAccountsByOwner`과 동일한 형태에 `slot` 파라미터가 추가된 형태입니다.

### SPL Token과 Token-2022는 무엇인가요?

Solana의 두 토큰 표준입니다. SPL Token은 네트워크상 사실상 모든 잘 알려진 토큰을 아우르는 원조 표준입니다. Token-2022는 전송 수수료와 기밀 잔액 같은 선택적 기능을 추가한 더 새로운 버전입니다. 이 메서드는 두 가지를 모두 지원합니다.

### getTokenAccountsByOwner와 무엇이 다른가요?

`getTokenAccountsByOwner`는 현재 보유 내역만 반환합니다. `getTokenAccountsByOwnerAtSlot`은 실시간 노드 상태가 아닌 이력 인덱스를 읽어, 과거 어느 슬롯에서든 같은 질문에 답합니다.

### 아카이벌 노드나 별도의 인덱서가 필요한가요?

아니요. 이 메서드는 미리 구축된 이력 인덱스를 읽으므로, 아카이벌 인프라를 운영하거나 트랜잭션 이력을 직접 재생할 필요가 없습니다.

### 단일 토큰이 아닌 지갑의 전체 포트폴리오를 조회할 수 있나요?

가능하지만, 지갑이 두 표준을 모두 보유하고 있다면 한 번의 `programId` 호출로는 안 됩니다. 단일 토큰은 `mint`로, 특정 슬롯에서 해당 프로그램 아래의 모든 계정은 `programId`으로 범위를 지정하세요. SPL Token과 Token-2022는 서로 다른 프로그램 ID를 사용하므로, 전체 포트폴리오를 조회하려면 두 곳을 모두 쿼리한 후 응답을 병합해야 합니다.

### 체인이 진행되는 동안 페이지네이션은 어떻게 정확성을 유지하나요?

`pageKey`이 쿼리 슬롯을 고정하므로, 새 블록이 도착하더라도 페이지 간 결과가 일관되게 유지되며, 페이지당 최대 10,000개의 계정을 처리합니다.
